Errors
Errors are JSON with a human-readable message and a stable machine code. Branch on the code, not the message.
{ "error": "Invalid or revoked API key", "code": "INVALID_API_KEY" }Codes
| Code | Type | Description |
|---|---|---|
| AUTH_REQUIRED | 401 | No Authorization header. If you are sending one, you are probably calling the apex host and losing the header on its redirect. Use api.ugcroster.com. |
| INVALID_API_KEY | 401 | Key unknown, revoked, or (for data keys) the owning subscription is not active. |
| BRAND_KEY_REQUIRED | 403 | A data key called outside its read-only scope. Only GET /v1/creators/search and GET /v1/creators/{pk} are data-key endpoints. |
| SUBSCRIPTION_REQUIRED | 403 | A brand key without an active brand plan called a directory endpoint. |
| RATE_LIMITED | 429 | Per-minute limit hit. Back off; the window is 60 seconds. |
| CREDITS_EXHAUSTED | 402 | Monthly credit budget used up. Terminal for the billing period: upgrade or wait for the reset. |
Handling pattern
javascript
const res = await fetch(url, { headers });
if (!res.ok) {
const { code } = await res.json();
switch (code) {
case 'RATE_LIMITED': // retry after the window
case 'CREDITS_EXHAUSTED': // stop until reset or upgrade
case 'INVALID_API_KEY': // rotate the key, check subscription
default: throw new Error(code);
}
}5xx responses carry no stable code and are safe to retry with exponential backoff. Everything 4xx is deterministic: the same request will fail the same way until something changes on your side.