> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.spyglass.so/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.spyglass.so/_mcp/server.

# Search brands

POST https://api.spyglass.so/v2/brands
Content-Type: application/json

Find brands.
Search semantically with `query`, or look them up by name, id, or
social handle. Either way, you can also narrow the results with
filters such as product taxonomy, location, and follower count.

Send one search field. Each field is its own mode:

- **Query** (`query`). A natural-language brief. Runs a language model and
  ranks by relevance, so `sortBy` is ignored. Bills at least one row even
  when nothing matches.
- **Name** (`names`). Fuzzy-matches account names (a case-insensitive contains
  match). Pass every name in one array.
- **ID** (`ids`). Looks up known ids. Missing ids are omitted and listed
  in `unmatchedIds`. `limit` and `offset` are ignored.
- **Instagram** (`igUsername`). Case-insensitive contains match on the
  handle. A leading `@` is ignored.
- **TikTok** (`tiktokUsername`). Same match on the TikTok handle.

If a request includes more than one of these fields, only the highest
priority field is used. The rest are ignored:

1. `ids`
2. `igUsername` or `tiktokUsername` (if both are set, either handle can match)
3. `names`
4. `query`

One exception: `query` together with `names` uses both. `names` narrows the
set, and `query` ranks inside it.

`limit` (default 20, max 100) caps the rows returned, and the cost, for
every mode except ID.

Limited to 120 requests per minute per user.
Costs $0.0010 per brand returned, charged against your plan's monthly credits. The count field is what you were charged for.
A `query` search runs a language model, so it bills a minimum of one
row even when nothing matches.

Reference: https://docs.spyglass.so/api-reference/spyglass-api/search/search-brands

## Authentication

- `Authorization` header (bearer token, required) — An API key from Settings → API, prefixed sg_live_.

## Request

### Body (application/json)

This endpoint expects an object.

- `ids` (list of BrandsPostRequestBodyContentApplicationJsonSchemaIdsItems, optional)
- `names` (list of string, optional)
- `igUsername` (string, optional)
- `tiktokUsername` (string, optional)
- `query` (string, optional)
- `location` (string, optional)
- `minFollowers` (integer, optional)
- `maxFollowers` (integer, optional)
- `sortBy` (enum, optional)
  - Allowed values: `NAME`, `MOST_FOLLOWERS`, `LEAST_FOLLOWERS`, `MOST_VIEWS`, `HIGHEST_ENGAGEMENT`, `MOST_ACTIVE_ADS`
- `offset` (integer, optional)
- `limit` (integer, optional)
- `taxonomy` (list of string, optional)

## Response

### 200

Matching brands.

- `count` (integer, required)
- `brands` (list of BrandsPostResponsesContentApplicationJsonSchemaBrandsItems, required)
- `unmatchedIds` (list of string, optional)

## Errors

### 400 Bad Request Error

The request body or query string failed validation. `details` lists the offending fields.

- `error` (ErrorError, required)

### 401 Unauthorized Error

The API key is missing, malformed, unknown, or revoked.

- `error` (ErrorError, required)

### 402 Payment Required Error

The team's monthly credits are exhausted.

- `error` (ErrorError, required)

### 403 Forbidden Error

The team's subscription is inactive, or your membership of it has ended.

- `error` (ErrorError, required)

### 405 Method Not Allowed Error

The HTTP method is not supported on this path. The Allow header lists what is. HEAD is refused on metered GET endpoints because it would be billed without returning data.

- `error` (ErrorError, required)

### 413 Content Too Large Error

The request body exceeds the 100 KB limit.

- `error` (ErrorError, required)

### 429 Too Many Requests Error

Too many requests for this user on this endpoint. Carries a Retry-After header. The per-minute limit is stated on the operation.

- `error` (ErrorError, required)

### 500 Internal Server Error

Something went wrong on our side.

- `error` (ErrorError, required)

## Types

### BrandsPostRequestBodyContentApplicationJsonSchemaIdsItems

Account id given as a platform string or uuid

### BrandsPostResponsesContentApplicationJsonSchemaBrandsItems

- `type` ("BRAND", required)
- `id` (string, required)
- `facebookAdLibraryId` (string, required, nullable)
- `name` (string, required)
- `summary` (string, required, nullable)
- `category` (string, required, nullable)
- `location` (string, required, nullable)
- `language` (string, required, nullable)
- `verified` (boolean, required)
- `facebookUsername` (string, required, nullable)
- `likes` (double, required, nullable)
- `igUsername` (string, required, nullable)
- `igFollowers` (double, required, nullable)
- `igEngagementRate` (double, required, nullable)
- `tiktokUsername` (string, required, nullable)
- `tiktokFollowers` (double, required, nullable)
- `thumbnailUrl` (string, required, nullable)

### ErrorError

- `code` (enum, required)
  - Allowed values: `invalid_request`, `invalid_api_key`, `payload_too_large`, `out_of_credits`, `membership_ended`, `subscription_inactive`, `brand_not_found`, `not_found`, `method_not_allowed`, `rate_limited`, `internal_error`
- `message` (string, required)
- `details` (list of ErrorErrorDetailsItems, optional)

### ErrorErrorDetailsItems

- `path` (string, required)
- `message` (string, required)

## Examples

**Request**

```json
{
  "names": [
    "Nike"
  ],
  "limit": 3
}
```

**Response**

```json
{
  "count": 1,
  "brands": [
    {
      "type": "string",
      "id": "string",
      "facebookAdLibraryId": "string",
      "name": "string",
      "summary": "string",
      "category": "string",
      "location": "string",
      "language": "string",
      "verified": true,
      "facebookUsername": "string",
      "likes": 1.1,
      "igUsername": "string",
      "igFollowers": 1.1,
      "igEngagementRate": 1.1,
      "tiktokUsername": "string",
      "tiktokFollowers": 1.1,
      "thumbnailUrl": "string"
    }
  ],
  "unmatchedIds": [
    "string"
  ]
}
```

**SDK Code**

```python searchBrands_example
import requests

url = "https://api.spyglass.so/v2/brands"

payload = {
    "names": ["Nike"],
    "limit": 3
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript searchBrands_example
const url = 'https://api.spyglass.so/v2/brands';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"names":["Nike"],"limit":3}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go searchBrands_example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.spyglass.so/v2/brands"

	payload := strings.NewReader("{\n  \"names\": [\n    \"Nike\"\n  ],\n  \"limit\": 3\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby searchBrands_example
require 'uri'
require 'net/http'

url = URI("https://api.spyglass.so/v2/brands")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"names\": [\n    \"Nike\"\n  ],\n  \"limit\": 3\n}"

response = http.request(request)
puts response.read_body
```

```java searchBrands_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.spyglass.so/v2/brands")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"names\": [\n    \"Nike\"\n  ],\n  \"limit\": 3\n}")
  .asString();
```

```php searchBrands_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.spyglass.so/v2/brands', [
  'body' => '{
  "names": [
    "Nike"
  ],
  "limit": 3
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp searchBrands_example
using RestSharp;

var client = new RestClient("https://api.spyglass.so/v2/brands");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"names\": [\n    \"Nike\"\n  ],\n  \"limit\": 3\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift searchBrands_example
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "names": ["Nike"],
  "limit": 3
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.spyglass.so/v2/brands")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```