# REST API Authentication and Account Scoping

Source: https://www.affiliatebase.io/docs/api/api-keys-and-rest-api
Last updated: 2026-10-17

> Authenticate AffiliateBase REST API requests with an API key, select the account scope, and handle authentication errors.

This page shows developers how to create an AffiliateBase API key, authenticate requests to the account-scoped REST API under `/api/v1`, limit a key with permissions, and handle rate limits.

For full details, see:
- [REST API Overview](/docs/api/rest-api-overview)
- [REST API Endpoint Reference](/docs/api/rest-api-endpoint-reference)
- [OpenAPI Spec](/docs/api/openapi-spec)

## Create an API key

In the app, owners and admins can create a key in **Settings** -> **API keys**: enter a **Key name**, choose **Expires after** (30 days, 90 days, **1 year** by default, or No expiry), then choose **Create key**. Keys created in the app have full access. The expiry date and last use appear in the **Active API keys** list, and expired keys are marked **Expired**.

Through the API, use these endpoints:
- `GET /api/v1/api_keys`
- `POST /api/v1/api_keys`
- `DELETE /api/v1/api_keys/:id`

The API returns a key secret once, when you create the key. Keys created through the API do not expire unless you set `expires_at`.

## Authenticate requests

The REST API accepts these auth headers:
- `Authorization: Bearer <API_KEY>`
- `Authorization: Basic <base64(API_KEY:)>`
- `X-Api-Key: <API_KEY>`

Only AffiliateBase API keys work at `/api/v1`. Access tokens issued to AI connectors through OAuth (for example, ChatGPT connectors) are refused at `/api/v1` with `403` and the code `FORBIDDEN`, even if the token's permissions would otherwise allow the request. Those tokens work only at the MCP endpoint. See [AI Connectors and MCP](/help/integrations/ai-connectors-and-mcp).

## Scope requests to your account

Provide account context with one of:
- `?account_id=<ACCOUNT_ID>`
- `X-Account-Id: <ACCOUNT_ID>`

`/api/v1` requests without account context return:

```json
{ "error": "Account ID is required", "code": "MISSING_ACCOUNT_ID" }
```

## Quick example

```bash
curl "https://app.affiliatebase.io/api/v1/affiliates?account_id=<ACCOUNT_ID>&page=1&limit=25" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json"
```

## Limit a key with permissions

When you create a key through `POST /api/v1/api_keys`, `permissions` is required and must be a non-empty object. A request that omits `permissions`, sends an empty object, or sends a non-object returns `422` with the code `VALIDATION_ERROR`. For full access, send `{ "all": true }`. Keys created in the app always have full access.

Example request body for a read-only affiliates key:

```json
{
  "name": "Read-only affiliates",
  "permissions": {
    "v1.affiliates.read": true
  }
}
```

### Permission names

A non-full-access key is checked against the resource and action of each request. Read requests (`GET`) need the `read` action. All other methods need `write`. Permission names take the form `v1.<resource>.<action>`, for example `v1.commissions.read`. These resources are available:

| Resource | Covers |
| --- | --- |
| `affiliates` | Affiliates (banning needs a separate exact permission, below) |
| `affiliate_coupons` | Affiliate coupons and individually assigned promo codes |
| `campaigns` | Campaigns |
| `referrals` | Referrals |
| `commissions` | Commissions and commission fraud review |
| `payouts` | Payouts and marking a payout paid |
| `payout_exports` | Payout exports and export payments |
| `payout_runs` | Payout runs |
| `links` | Links |
| `invitations` | Invitations and resending invitations |

### Manage API keys through the API

Creating and changing keys through the API requires either a full-access key or a key that holds exactly `v1.api_keys.manage`. Broad permissions such as `write` do not grant it. A key can only create keys whose permissions it already holds, so a scoped key cannot mint a full-access key. Dashboard users still need the `owner` or `admin` role to manage keys.

### Ban affiliates

`POST /api/v1/affiliates/:id/ban` and `/unban` require the exact permission `v1.affiliates.ban`. Full-access keys (`all` or `*`) have it. Broad permissions such as `write`, `v1.affiliates.write`, or scoped wildcards like `v1.affiliates.*` do not grant it, so a key that can edit affiliates cannot ban them unless you add the permission on purpose:

```json
{
  "name": "Fraud tooling",
  "permissions": {
    "v1.affiliates.read": true,
    "v1.affiliates.ban": true
  }
}
```

A key that manages API keys can only give `v1.affiliates.ban` to a new key when it holds that permission itself. Dashboard users need the `owner` or `admin` role to ban or unban through the API.

### Key lifetime and creator

Keys stop working when the team member who created them is removed from the account. Create long-lived integration keys from a user account that will stay on the team.

A full-access key acts as the team member who created it. A scoped key never inherits its creator's role, so it cannot grant the `owner` role even if its creator is an owner.

## Rate limits

`/api/v1` requests are limited per credential and per IP address.

| Limit | Value |
|-------|-------|
| Per API key (or dashboard session) | 45 requests per 30 seconds |
| Per IP address, across all keys | 180 requests per 30 seconds |

When a limit is exceeded, the API returns `429 Too Many Requests` with the error code `TOO_MANY_REQUESTS` and these headers:

```
RateLimit-Limit: 45
RateLimit-Remaining: 0
RateLimit-Reset: 30
Retry-After: 30
```

These headers are sent on `429` responses only, not on every response. Wait for `Retry-After` seconds before retrying, and back off if you keep receiving `429`. Integrations that run several keys from one IP address share the per-IP limit.

### Promo-code permissions

Individually assigned promo-code reads use `v1.affiliate_coupons.read`; previews and writes use `v1.affiliate_coupons.write`. These REST permissions are separate from the `mcp.affiliate_coupons.read` / `mcp.affiliate_coupons.write` connector permissions. See the [promo-code REST reference](/docs/api/rest-api-endpoint-reference#individually-assigned-promo-codes) or [MCP guide](/docs/api/mcp-promo-codes).

## What the API currently covers

- API keys
- Affiliates
- Affiliate coupons and individually assigned promo codes
- Campaigns
- Referrals
- Commissions
- Payouts
- Payout exports
- Payout runs
- Links
- Invitations

## Next steps

- [REST API Overview](/docs/api/rest-api-overview)
- [REST API Endpoint Reference](/docs/api/rest-api-endpoint-reference)
- [OpenAPI Spec](/docs/api/openapi-spec)
- [Tracking Script Reference](/docs/api/tracking-script-reference)
- [Outbound Webhooks](/docs/api/outbound-webhooks)
