Errors
The Brand API uses conventional HTTP status codes. 2xx means success, 4xx means something in the request needs to change, and 5xx means retry later.
Every response tells you how it went in its status code. Codes in the 2xx range mean success. Codes in the 4xx range mean the request needs to change: a bad parameter, a missing scope, a resource that is not yours. Codes in the 5xx range mean something went wrong on our side, and the same request may succeed if you retry it.
Error format#
An error body has success: false and a human-readable message. Messages are written for the developer reading the log; do not parse them, branch on the status code instead.
{
"success": false,
"message": "This API key is missing the analytics:read scope"
}Status codes#
| Status | Meaning | When |
|---|---|---|
| 400 | Bad Request | A query parameter is unknown or invalid, or the key was sent in the URL or an x-api-key header. |
| 401 | Unauthorized | The key is missing, malformed, unknown, expired or revoked. The response carries WWW-Authenticate: Bearer. |
| 402 | Payment Required | Your plan doesn't include this data, or the subscription is inactive. |
| 403 | Forbidden | The key lacks the endpoint's scope, or the request came from an IP outside the key's allowlist. |
| 404 | Not Found | The resource does not exist, or it belongs to another brand. |
| 405 | Method Not Allowed | Any method other than GET or HEAD. The API is read-only. |
| 410 | Gone | A retired endpoint, such as the keyless public recommendations feeds. |
| 429 | Too Many Requests | The key or the IP address is over its per-minute limit. |
| 500 | Server Error | Something went wrong on our side. Retry with backoff. |
| 503 | Service Unavailable | Authentication, the plan check or the audit log is briefly unavailable. Retry with backoff. |
A resource that belongs to another brand is always 404, never 403, so the API never confirms that someone else's campaign or survey exists.
Rate limit responses#
A 429 has its own body, along with Retry-After and the X-RateLimit-* headers described in Rate limits:
{
"error": "Rate limit exceeded",
"message": "Rate limit exceeded for this API key (60 requests/minute).",
"retryAfter": 23
}Handle errors#
- Retry
429,500and503with exponential backoff. For a429, wait at leastRetry-Afterseconds first. - Do not retry any other
4xx. Fix the request, the key or its scopes. - Treat
402as a plan question for your Rendezvu admin, not a code problem.
async function rendezvu(path, attempt = 0) {
const res = await fetch(`https://api.rendezvu.co/api/brand/v1${path}`, {
headers: { Authorization: `Bearer ${process.env.RENDEZVU_BRAND_API_KEY}` },
});
const retryable = res.status === 429 || res.status >= 500;
if (retryable && attempt < 5) {
const wait = Number(res.headers.get('retry-after')) || 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
return rendezvu(path, attempt + 1);
}
const body = await res.json();
if (!res.ok) throw new Error(`Rendezvu ${res.status}: ${body.message}`);
return body;
}- AuthenticationAuthenticate every request with a secret API key in the Authorization header. Keys are read-only, scoped, tied to one brand, and always expire.
- Rate limitsEach API key can make 60 requests a minute, and each IP address 120. Every response carries headers that say how much of the limit is left.