# Authentication

> Authenticate every request with a secret API key in the Authorization header. Keys are read-only, scoped, tied to one brand, and always expire.

- Audience: API
- Page type: reference
- Updated: 2026-10-08
- Canonical URL: https://www.rendezvu.co/docs/api/authentication

The Brand API authenticates with secret keys. A key starts with `rdz_sk_`, belongs to one brand, carries one or more read-only scopes, and expires. You send it as a Bearer token on every request; there is no session, no OAuth flow and no other way in.

## Create a key

Brand admins create keys in the console under **Settings**, then **Integrations**, then **Brand API**. View-only team members can see the list but cannot create, roll or revoke keys.

| Field | Rule |
| --- | --- |
| Name | 1 to 80 characters, so you can tell keys apart later. "Snowflake sync" is a good name. |
| Scopes | At least one. Grant only what the integration reads. |
| Expires in | 1 to 365 days. The default is 90. Every key expires. |
| Allowed IPs | Optional. Up to 20 IPv4 or IPv6 addresses or CIDR ranges. |

The secret appears once, when you create the key. Rendezvu stores only a SHA-256 hash of it, so nobody at Rendezvu can show it to you again. If you lose it, revoke the key and create another. A brand can hold up to 10 active keys.

## Send the key

Put the key in the `Authorization` header as a Bearer token:

```bash
curl https://api.rendezvu.co/api/brand/v1/me \
  -H "Authorization: Bearer $RENDEZVU_BRAND_API_KEY"
```

The header is the only transport the API accepts:

- A key in the query string (`?api_key=`, `?key=` or `?token=`) is refused with `400`. URLs end up in access logs and browser history, so rotate any key you ever sent that way.
- An `x-api-key` header is refused with `400` too.
- A missing or malformed header is `401`, with a `WWW-Authenticate: Bearer` challenge.

## Scopes

Each endpoint needs exactly one scope, named at the top of its reference entry. Some scopes also need your plan to include the matching console feature, so the API never shows you data your plan does not. Without the scope the request is `403`; without the plan feature it is `402`.

| Scope | Reads | Plan feature |
| --- | --- | --- |
| `analytics:read` | Click analytics, per-host performance and attributed orders | Analytics |
| `opportunities:read` | Campaigns, their deliverables and host assignments | Any plan |
| `content:read` | Deliverables and uploads in the content library, and their files | Any plan |
| `roster:read` | Hosts on your active roster, with their public profile | Any plan |
| `recommendations:read` | Hosts recommending your products on public gear lists | Any plan |
| `gifts:read` | Product gifts sent to hosts and the feedback they wrote | Gifting |
| `codes:read` | Host discount codes and their store sync state | Discount codes |
| `surveys:read` | Surveys and their aggregate results | Surveys |

`GET /me` needs no scope.

## When is a key valid?

All four of these are checked on every request, not only when the key is created:

1. The key matches one that is not revoked and not past its expiry.
2. The key belongs to a brand account.
3. The person who created the key is **still** an admin with an active seat on your brand. Remove someone from your team, or change their role, and every key they created stops working at once.
4. If the key has allowed IPs, the request comes from one of them.

Because of the third rule, create keys for long-lived integrations from an account that will stay on the team.

## Restrict a key to your IP addresses

Give a key allowed IPs when your integration runs from fixed addresses, such as a warehouse connector or a NAT gateway. A request from anywhere else is `403`, even with the right key.

- Single addresses and CIDR ranges both work: `203.0.113.7` or `203.0.113.0/24`.
- Ranges wider than `/8` for IPv4 or `/16` for IPv6 are refused.
- Host bits are cleared: `203.0.113.5/24` is stored as `203.0.113.0/24`.

## Rotate and revoke keys

To rotate without downtime, use **Roll key** on the key in the console. It creates a new key with the same name, scopes, allowed IPs and lifetime, and leaves the old key working until you revoke it:

1. Roll the key and copy the new secret.
2. Deploy it to your integration and confirm `GET /me` answers with the new key's id.
3. Revoke the old key in the console. Revocation takes effect on the next request.

If a key has leaked, roll it with **Revoke the current key immediately** instead, or revoke it outright.

Set a reminder before a key's expiry date; an expired key answers `401` like a revoked one.

## Keep keys secret

- Store keys in a secret manager or an environment variable, never in source control.
- Keys are prefixed `rdz_sk_` so secret scanners such as GitHub secret scanning can recognize them.
- If a key leaks, revoke it first and investigate second.

## Every request is logged

Each authenticated request is recorded before it is served: the key, the method, the path without its query string, the IP address, the user agent and the time. Brand admins can review a key's activity in the console. If the log entry cannot be written, the request fails with `503` rather than being served unrecorded.

## Related

- [Errors](https://www.rendezvu.co/docs/api/errors.md): 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.
- [Rate limits](https://www.rendezvu.co/docs/api/rate-limits.md): Each 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.

---

Source: https://www.rendezvu.co/docs/api/authentication (Rendezvu docs, Markdown view). Every page: https://www.rendezvu.co/llms.txt