Referral ReactorDocs

Authentication

All Referral Reactor API endpoints (except GET /api/v1/health) require authentication via a Clerk-issued API key supplied as a Bearer token in the Authorization header.


Bearer Token Usage

Include your API key in every request using the standard HTTP Authorization header:

Authorization: Bearer <api_key>

curl

curl https://app.referralreactor.com/api/v1/referrals \
  -H "Authorization: Bearer rr_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json"

TypeScript / JavaScript

const BASE_URL = 'https://app.referralreactor.com';
const API_KEY = process.env.REFERRAL_REACTOR_API_KEY; // never hardcode

async function fetchReferrals() {
  const response = await fetch(`${BASE_URL}/api/v1/referrals`, {
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(
      `[${response.status}] ${error.error.code}: ${error.error.message}`
    );
  }

  return response.json();
}

Never expose your API key in client-side code or commit it to source control. Store it in an environment variable and access it server-side only.


Scopes

Each API key is issued with one or more scopes that control which endpoints it can access. Organization-scoped keys are configured in Settings → API Keys.

| Scope | Description | | --------------------- | ------------------------------------- | | referrals:read | Read referrals and their details | | referrals:write | Create and update referrals | | users:read | Read user profiles and lists | | users:write | Create and update users | | organizations:read | Read organization details | | organizations:write | Update organization settings | | bonus-payments:read | Read bonus payments | | webhooks:read | Read webhook endpoints and deliveries | | webhooks:write | Create and manage webhook endpoints |

If a request is made with a key that lacks the required scope for an endpoint, the API returns HTTP 403. See Error Shapes below.


Rate Limiting

The API enforces rate limits using a sliding window algorithm per API key. When a request is made, the response includes the following headers:

| Header | Description | | ----------------------- | -------------------------------------------------------- | | X-RateLimit-Limit | Maximum number of requests allowed in the current window | | X-RateLimit-Remaining | Number of requests remaining in the current window | | X-RateLimit-Reset | Unix timestamp (seconds) when the current window resets |

When the limit is exceeded, the API returns HTTP 429 Too Many Requests. Check X-RateLimit-Reset to know when you can retry.

# Example response headers when approaching the limit
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 3
X-RateLimit-Reset: 1735689600

Error Shapes

All authentication and authorization errors return a consistent JSON body with an error object containing code, message, and requestId fields.

401 Unauthorized

Returned when no valid API key is provided.

{
  "error": {
    "code": "MISSING_AUTHORIZATION",
    "message": "No Authorization header was provided.",
    "requestId": "req_abc123"
  }
}
{
  "error": {
    "code": "INVALID_API_KEY",
    "message": "The provided API key is invalid or has been revoked.",
    "requestId": "req_abc124"
  }
}

| Code | Cause | | ----------------------- | ------------------------------------------------- | | MISSING_AUTHORIZATION | Authorization header is absent from the request | | INVALID_API_KEY | Key is malformed, expired, or revoked |

403 Forbidden

Returned when the API key is valid but lacks the required scope for the endpoint.

{
  "error": {
    "code": "SCOPE_LIMITATIONS",
    "message": "This API key does not have the 'referrals:write' scope required for this endpoint.",
    "requestId": "req_abc125"
  }
}

429 Too Many Requests

Returned when the rate limit for the API key has been exceeded.

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please retry after the reset time.",
    "requestId": "req_abc126"
  }
}

Use the requestId when contacting support — it uniquely identifies the failed request in our logs.


Next Steps