API overview
Base URLs, content type, errors, rate limits, and pagination.
The Rekomi API is JSON-over-HTTPS. Every request needs an API key. Every response is JSON. Every error follows the same shape.
Base URLs
- Production:
https://api.rekomi.com/api/v1 - Staging:
https://rekomi-api-staging-owaet.ondigitalocean.app/api/v1
(Production routes are subject to the Phase 11 DNS cutover. Until then, the staging URL is the canonical endpoint for testing.)
Content type
All requests and responses use application/json. UTF-8 encoded. No XML, no form-encoded bodies.
Content-Type: application/json
Accept: application/jsonAuthentication
Every endpoint (except a small set of public ones like /api/p/by-handle/{handle}/{campaign}, /api/p/by-domain, and /api/v1/track/click) requires a bearer token in the Authorization header:
Authorization: Bearer rk_live_xxxxxxxxxxxxxxxxxxxxxGenerate API keys at /dashboard/settings/api-keys. See Authentication for the full lifecycle (create, rotate, revoke, scope to read vs write).
S2S tracking and webhook payloads have a separate HMAC signing step on top of the bearer auth. See S2S tracking and Webhooks.
Errors
Every error response is JSON in this shape:
{
"error": "validation_failed",
"message": "perPage must be between 1 and 100",
"field": "perPage"
}- error: a stable string code. Use this for branching logic in your code. Codes never change once published.
- message: a human-readable description. Subject to change. Do not parse.
- field (optional): the field that triggered the error, when relevant.
Common error codes:
| Code | HTTP | Meaning |
|---|---|---|
unauthorized | 401 | Missing or invalid API key |
forbidden | 403 | API key valid but not authorized for this endpoint |
not_found | 404 | Resource does not exist or is not visible to your org |
validation_failed | 400 | Request body or query params did not validate |
idempotency_conflict | 409 | Same idempotency key used with different payload |
plan_tier_required | 402 | Feature requires a higher plan tier |
rate_limited | 429 | Too many requests in the window |
server_error | 500 | Something broke on our end |
Never parse the message field. Always branch on error.
Rate limits
Limits are partitioned per principal (Clerk user or API key) for authenticated calls, and per IP for anonymous and webhook traffic:
| Endpoint class | Limit |
|---|---|
| Standard authenticated API (reads and writes) | 600 req/min |
| Write-heavy endpoints (bulk import, affiliate apply) | 6 to 10 req/min |
| Anonymous tracking (click and lead capture) | 60 req/min per IP |
S2S conversion ingest (/api/tracking/s2s) and webhooks | 1500 req/min per IP |
When you exceed the limit, the response is HTTP 429 with these headers:
X-RateLimit-Remaining: 0Retry-After: <seconds>
Wait Retry-After seconds before retrying. Implement exponential backoff for sustained spikes.
Pagination
List endpoints under /api/v1/* return cursor-based pagination envelopes:
GET /api/v1/conversions?take=100&cursor=eyJpZCI6MTIzNH0take: page size. Max 200, default 50.cursor: opaque cursor returned in a prior response'snextCursorfield. Omit for the first page.
Response shape:
{
"items": [ /* up to `take` items */ ],
"nextCursor": "eyJpZCI6MTIzNH0",
"hasMore": true
}When hasMore is false, you have reached the end.
Idempotency
For write endpoints that create new resources, you can supply an Idempotency-Key header (UUID v4 recommended). Within a 60-minute window, the same key with the same payload returns the prior response. The same key with a different payload returns HTTP 409.
Idempotency-Key: 8f14e45f-ceea-467a-bb2c-d8b8c0afc8d8Use this for any write you might retry on network failures.
CORS
The API has restrictive CORS. The default allowlist is just Rekomi's own surfaces (rekomi.com and app.rekomi.com). For server-to-server calls (Node.js, Go, Python, anything not in a browser), CORS doesn't apply, so make whatever request you like.
For browser-side requests from your own domain, proxy through your application server. The brand-side dashboard is the only browser surface in the allowlist today; we don't issue per-organization browser-CORS allowlists for arbitrary partner sites.
The white-label embed iframe is a separate flow with its own per-token origin allowlist; see Embed.
Plan requirements
Programmatic access (API keys) is gated by plan tier. The in-app dashboard at app.rekomi.com is unrestricted on every paid tier; only rk_live_* API calls are gated. The hosted MCP server is the exception: it works on every plan including Trial, since each tool call is relayed through mcp.rekomi.com and gated per-tool by your AI client's consent loop rather than by a direct-API plan check.
| Feature | Required plan | What it includes |
|---|---|---|
Hosted MCP server (mcp.rekomi.com/api/mcp) | Trial+ (every plan) | Connect Claude, Cursor, ChatGPT to your account. 38 tools, read + write, relay-bound tokens. |
S2S conversion tracking (/api/tracking/s2s) | Starter | Record conversions from your backend when cookies aren't viable. |
Public REST API (/api/v1/programs, /affiliates, /conversions, /payouts, /dashboard) | Starter | Full read + write programmatic access to your data. |
Customer-facing webhooks (/api/webhook-endpoints) | Starter | Receive event pushes for conversions, payouts, affiliates. |
| Zapier integration (app store listing) | Starter | 9 triggers, 9 actions, 4 searches. Connect to 7000+ apps without writing code. |
Embed iframe (/api/v1/embed) | Growth | White-label affiliate dashboard hosted on your domain. |
AI Co-Pilot (/api/ai) | Growth | AI suggestions for affiliate matches + campaign copy. |
| Audit log API export | Pro | Programmatic SIEM export of org audit trail. |
Trial users (14-day free trial on the tier picked at signup) get full feature access for the trial window regardless of nominal tier. Plan gates fire as 402 plan_tier_required with the required + current tier in the body:
{
"error": "plan_tier_required",
"required": "Growth",
"current": "Starter",
"trialing": false,
"message": "White-label embed requires Growth tier or higher. Upgrade in Settings → Billing."
}The dashboard (app.rekomi.com) authenticates via Clerk JWTs and bypasses plan gates so brand operators can always see and manage their own data regardless of tier.
Versioning
All routes live under /api/v1. We will introduce /api/v2 if and when we make breaking changes. v1 stays available for at least 24 months after v2 ships. Deprecations are announced via the blog and a Deprecation header on responses.
Machine-readable docs
LLMs and coding agents integrating against Rekomi should fetch /llms/api.txt, a single-file manifest enumerating every /api/v1/* endpoint, request and response shape, error codes, plan gates, webhook events, signature verification steps, and rate-limit policies in plain prose with structured headings. The manifest is regenerated on every API change and is the canonical machine-consumable spec; this page and the rest of /docs/developers/* are the human-friendly views of the same surface.
Where to go next
- Authentication: generate keys, manage scopes.
- S2S tracking: server-side conversion ingest.
- Track leads and signups: capture free signups (automatic for Stripe and Paddle) and email-match a later sale.
- Webhooks: receive events from Rekomi.
- Embed: host an affiliate's dashboard on your domain.
- MCP: connect Claude, Cursor, or ChatGPT to your account via the hosted MCP server.
- Reference: every v1 endpoint with method, scope, and example.