Browse Developers
Build with OnloView as Markdown

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

HeaderWhenValue
`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.

ScopeKey prefixCan do
Full access`olk_live_`Ping, create, fetch, update, search
Read-only`olk_read_`Ping, fetch, search

Create and store a key

  1. 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.

  2. 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.

  3. 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.

  1. Step 1

    Create a second key

    Create the replacement while the current key stays active.

    Expected resultBoth keys authenticate.

  2. 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.

  3. Step 3

    Verify the new key

    Call `/ping` with the new key from the deployed environment.

    Expected resultA `200` response.

  4. 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.

HeaderMeaning
`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`