status, a human-readable message, and a machine-readable error_code (429 responses use code instead):
| Status | Meaning | Where to look |
|---|---|---|
| 400 | Invalid input, or a well-formed domain that can’t be resolved | Bad Request |
| 401 | Missing or invalid API key | Unauthorized |
| 408 | Cold-hit timeout or custom timeoutMS exceeded | Request Timeout |
| 422 | Invalid, disposable, or free email (only on /brand/retrieve-by-email) | Invalid Email |
| 429 | Rate limit exceeded — wait the seconds given in the Retry-After header | Handle Rate Limits |
| 500 | Transient server error | Server Error |
Bad Request (400)
Good news first: you don’t have to sanitize the domain yourself. The API strips the protocol and thewww. subdomain for you, so stripe.com, https://stripe.com, and www.stripe.com all resolve to the same brand.
error_code:
INPUT_VALIDATION_ERROR— the request itself is malformed. A domain with no TLD (stripe), a missing required parameter, an out-of-range value (company name on/brand/retrieve-by-namemust be 3–30 characters), or both/neither of an either-or pair (/web/styleguide,/web/fonts, and/web/screenshoteach takedomainordirectUrl, never both and never neither).WEBSITE_ACCESS_ERROR— the domain is well-formed but the resolver couldn’t reach it (DNS failure, dead site, hostile WAF). This is effectively “no brand here,” and on/brand/retrieveit comes back as a 400, not a 404.NOT_FOUND— no brand matched the identifier you passed. The request is not billed.
INPUT_VALIDATION_ERROR as a user-facing validation message, not a retryable failure. A WEBSITE_ACCESS_ERROR means the brand doesn’t exist or can’t be crawled, so treat it as a clean “not found.”
Unauthorized (401)
The API key is missing, invalid, expired, or deleted. Start by confirming the key is actually being loaded, without ever logging the key itself:- Env var name mismatch. The expected name is
CONTEXT_DEV_API_KEY. Watch for typos likeCONTEXTAPIKEYorCONTEXT_DEV_APIKEY. .envnot loaded. In Node,import "dotenv/config"(orrequire("dotenv").config()) must run before the SDK is initialized. In Python,load_dotenv()frompython-dotenvdoes the same.- Key was rotated. Generate a new key in the dashboard and update the environment variable everywhere the application runs.
Request Timeout (408)
A 408 comes back when either yourtimeoutMS budget elapsed before the API finished, or the cold-hit crawl ran past the 5-minute platform maximum. For reference, cold-hit latency is around 7 seconds at p50 and up to a minute at p99; cached hits return in around 250ms.
Three recovery strategies, in order of preference:
1. Prefetch the domain or email. A warmed cache lands the eventual /brand/retrieve in under a second. See Prefetch for Faster Response.
2. Raise the timeoutMS budget. Minimum 1,000 ms, maximum 300,000 ms (5 minutes). 60 seconds is a sane default for non-time-sensitive paths:
client from the Quickstart:
Invalid Email (422)
Returned only by/brand/retrieve-by-email. The three causes:
- Disposable email service (e.g.
tempmail.com,guerrillamail.com). - Free email provider (
gmail.com,yahoo.com,hotmail.com,outlook.com,aol.com,icloud.com,proton.me). Theerror_codeisFREE_EMAIL_DETECTED. - Malformed email format.
/brand/prefetch-by-email endpoint applies a broader 10,000+ disposable-provider filter automatically.
Server Error (500)
A 500 is transient. Two recovery patterns: 1. Retry with exponential backoff (same shape as the 408 retry above). 2. Fall back to a different lookup method. If/brand/retrieve-by-email 500s, extract the domain and call /brand/retrieve instead:
Missing or partial brand data (200)
A successful 200 does not guarantee every field is populated. Not every brand has every asset (a private company has nostock; some sites have no discovered logos). Always provide defaults:
Debugging recipes
Isolate the issue with a raw cURL request. If a cURL call works and the SDK call does not, the SDK or env-var setup is the suspect:logging.basicConfig(level=logging.DEBUG), Node’s console.log around the call, or running through a local proxy that captures the request.
Related resources
Rate limits
The full 429 recovery contract.
Prefetch
The fastest fix for 408 cold-hit timeouts.
Best practices
Caching, fallbacks, and error handling at the integration level.
Status page
Live API status.