> ## Documentation Index
> Fetch the complete documentation index at: https://onlytraffic.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> How to authenticate with the OnlyTraffic Partners API.

## API key

All requests require the `Authorization` header.

<Steps>
  <Step title="Get your key">
    Open the partner cabinet and go to **Tools -> API** ([partners.onlytraffic.com/tools/api](https://partners.onlytraffic.com/tools/api)). The page lists your keys: up to **5** active keys per account, each with a name.

    Click **Create key** and choose a name, an access level (**Full** or **Read-only**) and an expiry (30, 90, 180 or 365 days, or never). The key is shown **once**, right after creation: copy it immediately. Later the page shows only its prefix (`ot_partners_ab12…`), access level, expiry and last use.

    Keys look like `ot_partners_` followed by 40 hex characters. You can revoke a key at any time: integrations using it stop working immediately, and revoking frees one of the 5 slots.

    If your account still has an older single key (format `XXXXX-XXXXX-XXXXX-XXXXX`), it is listed on the same page as **Legacy key**. It keeps working with full access until you delete it there.
  </Step>

  <Step title="Add the header">
    Include the key in every request:

    ```text theme={null}
    Authorization: your-api-key-here
    ```

    The `Bearer` form is accepted too:

    ```text theme={null}
    Authorization: Bearer your-api-key-here
    ```
  </Step>
</Steps>

<Warning>A Full key reads your data and can start and stop campaigns. Keep every key secret; use a Read-only key for integrations that only need to read.</Warning>

## AI assistants

Keys are also what AI assistants use. When you connect Claude or ChatGPT to your account, you pick one of these keys (or create a new one) on the consent page, without pasting it anywhere. The assistant gets exactly that key's access level, and revoking the key disconnects it. See [AI assistants](/docs/partners/api/ai-assistants).

## Access levels

| Access | What the key can do |
| - | - |
| **Full** | Every endpoint, reads and writes |
| **Read-only** | Every `GET` endpoint. Calls to the write endpoints (`POST`) answer `error_code` `403` with the message `This API key is read-only` |

Expired or revoked keys are rejected like unknown keys: `error_code` `403`, message `Error! Access denied`.

Rate limits are per account, not per key: all keys of an account share the same **120 reads / 30 writes per minute**.

## Base URL

```text theme={null}
https://partners.onlytraffic.com
```

## Example request

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://partners.onlytraffic.com/api/marketer/revshare/campaigns?limit=10" \
    -H "Authorization: your-api-key-here"
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://partners.onlytraffic.com/api/marketer/revshare/campaigns",
      params={"limit": 10},
      headers={"Authorization": "your-api-key-here"}
  )
  data = response.json()
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://partners.onlytraffic.com/api/marketer/revshare/campaigns?limit=10",
    {
      headers: { "Authorization": "your-api-key-here" }
    }
  );
  const data = await response.json();
  ```
</CodeGroup>

## Rate limits

Limits apply per account and are shared by all its keys: **120 requests per minute** for read endpoints and **30 per minute** for write endpoints. When you hit a limit the response carries `error_code` `429` and a `Retry-After` header with the number of seconds to wait.

## Errors

All responses return HTTP `200`. Check the `status` field for the actual result.

<AccordionGroup>
  <Accordion title="403 — Access denied">
    | Error code | Description |
    | - | - |
    | `403` | The key is missing, unknown, expired or revoked, or the account is not an active partner (`Error! Access denied`). Also returned when a Read-only key calls a write endpoint (`This API key is read-only`) |
  </Accordion>

  <Accordion title="404 — Not found">
    | Error code | Description |
    | - | - |
    | `404` | The campaign or order does not exist or is not yours |
  </Accordion>

  <Accordion title="422 — Invalid parameters">
    | Error code | Description |
    | - | - |
    | `422` | Request contains invalid or missing parameters. `message` says what is wrong |
  </Accordion>

  <Accordion title="429 — Rate limit">
    | Error code | Description |
    | - | - |
    | `429` | Too many requests — wait for `Retry-After` seconds and retry. Also returned when another campaign start is still running for your account |
  </Accordion>

  <Accordion title="500 — Server error">
    | Error code | Description |
    | - | - |
    | `500` | Something went wrong on our side. Retry later |
  </Accordion>

  <Accordion title="503 — Service temporarily unavailable">
    | Error code | Description |
    | - | - |
    | `503` | A write proxied to the platform timed out. Retry later. The action may still have been applied: check with the matching read endpoint before repeating a campaign start |
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.