Authentication and API keys
Create the right key scope, send it correctly, rotate it without downtime, and read each authentication failure.
- For
- Backend engineers and operators managing Onlo API credentials
- Time
- 10 minutes
Before you start
- Owner or admin access to your Onlo workspace
- A plan that includes API access
Required headers
| Header | When | Value |
|---|---|---|
| `Authorization` | Always | `Bearer <your API key>` |
| `Content-Type` | On POST and PUT | `application/json` (a charset parameter is fine) |
| `Accept` | Recommended | `application/json` or `*/*` |
Choose a scope
Scope is enforced before Onlo parses your request body, so a read-only key attempting a write is rejected without revealing anything about the payload it would have validated.
| Scope | Key prefix | Can do |
|---|---|---|
| Full access | `olk_live_` | Ping, create, fetch, update, search |
| Read-only | `olk_read_` | Ping, fetch, search |
Create and store a key
- Step 1
Create the key
In Onlo, go to Dashboard → Integrations → API and create a key with the scope you need.
Expected resultThe raw key is shown exactly once. Onlo stores only a hash of it and can never show it again.
- Step 2
Store it in your secret manager
Save it as `ONLO_API_TOKEN` and set `ONLO_API_BASE_URL` to `https://onlo.ai/api/v1`. Deploy it to your backend only.
Expected resultYour application reads the key from the environment, and no key value appears in your source tree.
- Step 3
Verify it end to end
Call `/ping` with the key from the environment where your integration will actually run.
Connection testshell
export ONLO_API_BASE_URL="https://onlo.ai/api/v1" export ONLO_API_TOKEN="olk_live_replace_with_your_key" curl --request GET "$ONLO_API_BASE_URL/ping" \ --header "Authorization: Bearer $ONLO_API_TOKEN" \ --header "Accept: application/json"Expected resultA `200` response echoing your `organization_id` and the `scope` you expect.
Call `GET /ping` from your deployed backend, not from your laptop.
Expected result
A `200` whose `scope` matches the key you created, and whose `organization_id` is your organization.
If you don't see this
- A `401 unauthorized` means the key is missing, malformed, or revoked. Confirm the header is exactly `Bearer <key>` with a single space.
- A `403 https_required` means the request arrived over plain HTTP while your organization requires HTTPS.
- A `403 ip_not_allowed` means your organization has an IP allowlist and your server’s egress address is not on it. Add the address your platform actually egresses from, not your office IP.
- A `403 api_plan_restricted` means the plan does not include API access. This is checked on every request, so it also appears if a subscription lapses.
Rotate without downtime
Both keys work at once, so rotate by adding before removing. Never revoke first — that guarantees an outage for however long your deployment takes.
- Step 1
Create a second key
Create the replacement while the current key stays active.
Expected resultBoth keys authenticate.
- Step 2
Deploy the new key
Update the secret in your backend and roll it out.
Expected resultTraffic moves only when your deployment completes — Onlo does nothing at this step.
- Step 3
Verify the new key
Call `/ping` with the new key from the deployed environment.
Expected resultA `200` response.
- Step 4
Revoke the old key
Revoke the previous key in the dashboard.
Expected resultAny request still using the old key returns `401 unauthorized`.
After revoking, watch your error rate for one full traffic cycle.
Expected result
No `401` responses — every caller is on the new key.
If you don't see this
- If `401`s appear, a caller you did not account for still holds the old key. Create a new key, deploy it to that caller, and treat the old key as compromised if you cannot identify the source.
Rate limits
One bucket per organization, shared by every active key and every one of your callers. The default is 200 requests per second with a burst capacity of 200, refilled continuously. Your organization may be configured lower.
Every response carries the current state in both the `X-RateLimit-*` headers (matching Intercom) and the `RateLimit-*` headers (the IETF draft spelling). They report the same numbers, so read whichever your HTTP client already parses.
| Header | Meaning |
|---|---|
| `X-RateLimit-Limit` / `RateLimit-Limit` | Requests-per-second capacity for your organization |
| `X-RateLimit-Remaining` / `RateLimit-Remaining` | Tokens left after this request |
| `X-RateLimit-Reset` | Epoch second at which capacity is available |
| `RateLimit-Reset` | Seconds until capacity is available |
| `Retry-After` | Seconds to wait, sent only on a `429` |