Reference
REST API
Everything the MCP server does is also available over plain HTTP, so n8n workflows, cron jobs, and custom code get the same surface. Base URL below; all routes are under /v1.
Authentication
Create an API key in the dashboard at https://app.affiliateos.dev/developers and pass it as a Bearer token. Keys look like aff_live_..., are shown once, and are stored only as SHA-256 hashes.
curl https://api.affiliateos.dev/v1/accounts \
-H "Authorization: Bearer aff_live_..."Keys carry scopes; the defaults are read and links:create. Two things are deliberately out of reach of any key: key management itself (create, list, revoke), so a leaked key can’t mint more keys, and connecting or editing a network account, so a leaked key can’t redirect your commissions. Both need a dashboard session.
Conventions
| Topic | Behavior |
|---|---|
| Rate limit | 120 requests per minute per key. Exceeding it returns 429 with a Retry-After header. |
| Errors | Every error is { error: { code, message } } with a matching HTTP status. |
| Pagination | List endpoints take ?cursor=&limit= (default 25, max 100) and return a cursor for the next page. |
| Content type | JSON in, JSON out. |
Networks & accounts
GET /v1/networks
Supported networks with their credential field specs and help text.
GET /v1/accounts
Your connected accounts with status and last sync. Each row also carries missing_credentials — credential fields the network expects that the account does not hold. A field can become required after you connect (CJ’s Website ID did), and the account keeps working for everything except the operation that needs it, so check this before minting rather than after the mint fails.
POST /v1/accounts
Body { network, label, credentials }. Credentials are verified against the network before being sealed and stored; invalid ones are rejected with the connector’s reason.
PATCH /v1/accounts/:id
Body { label?, credentials? }. Credentials are merged over what is stored, so you can add or rotate one field without re-typing a secret you can no longer read back. The merged set is re-verified before anything is written — a rejected edit leaves the working credentials in place — and a successful one clears auth_error and queues a fresh sync.
DELETE /v1/accounts/:id
POST /v1/accounts/:id/sync
Force a sync, rate-limited to once per five minutes per account.
POST, PATCH and DELETE on accounts need a dashboard session — an API key or MCP token gets a 403. Credentials are merged on PATCH, so a write here doesn’t need to know a secret to do damage: swapping CJ’s Website ID or Amazon’s Partner Tag re-points your commissions while the account still reads as active. Reads and /sync stay open to keys and agents. To connect a network from an agent, use the connect handoff below.Connect handoff
How an agent gets a network connected without ever holding the credential. The agent calls start_network_connection over MCP and receives a URL; the human opens it, sees which client asked, and types the credential into a browser form that posts it straight into the vault. These are the routes that page talks to — all three take a dashboard session only, so the token in the URL names a pending request rather than authenticating one.
GET /v1/connect/:token
What the page renders: network, suggested label, the client_name that asked, and the credential_fields to collect.
POST /v1/connect/:token
Body { label, credentials }. Verifies against the network, seals the credential, connects the account and queues the first sync — the same path as the dashboard’s own form. A failed verify leaves the link usable, so a typo doesn’t cost a new one.
POST /v1/connect/:token/cancel
Decline, so the agent polling get_connection_status hears an answer instead of a timeout.
Programs
GET /v1/programs
Hybrid search. Query params: query, network, vertical, status, min_commission_pct. Uses semantic search when an embeddings key is configured and falls back to keyword matching otherwise.
GET /v1/programs/:id
Full detail including commission summary and cookie window.
Transactions, earnings & payments
GET /v1/transactions
Query params: from, to, status, network, attribution_tag, program_id. Defaults to the last 30 days.
GET /v1/earnings/summary
Query params: from, to, group_by=network|program|tag|day, currency=USD. Amounts are converted with daily exchange rates and split by status: pending, approved, reversed, paid.
GET /v1/payments
Payout records, filterable by date range.
Events & webhooks
GET /v1/events
Pull-based event feed. Query params: after (an event id or ISO timestamp high-water mark) and types.
POST /v1/webhooks
Body { url, event_types[] }. Returns the signing secret once. See the webhooks page for verification.
GET /v1/webhooks
DELETE /v1/webhooks/:id
API keys
GET /v1/keys
POST /v1/keys
DELETE /v1/keys/:id