Getting started

Authentication

Every request carries a bearer token in the Authorization header.

bash
Authorization: Bearer sp_live_a1b2c3...

Keys are scoped to one program

A key belongs to exactly one program, and that binding is not something a request can override. Passing a different :programId in the path does not grant access to it.

A mismatched program id returns 404, not 403. A 403 would confirm the program exists, which turns the endpoint into an oracle for enumerating other tenants' ids. “Not yours” and “doesn't exist” are deliberately indistinguishable.

Scopes

  • read — every GET. Lists, summaries, payout previews.
  • write — anything that mutates: reporting conversions, inviting affiliates, dispatching payouts.

A request needing a scope the key lacks returns 403. Issue read-only keys for anything that only renders dashboards — a reporting integration has no business being able to dispatch a payout.

Storing keys

  • Server-side only. A key in browser JavaScript is a public key. The one endpoint that runs in a browser — POST /v1/clicks — takes no key for exactly this reason.
  • Only a hash is stored. The raw key is shown once at creation and cannot be recovered. Lost it? Revoke and reissue.
  • Revocation is immediate. Revoking sets revoked_at; the next request with that key fails.

Rotating a key

There is no in-place rotation, deliberately — it would create a window where neither the old nor the new key is definitively live. Instead: issue a second key, deploy it, confirm traffic has moved (last_used_at on the old key stops advancing), then revoke the old one. Zero downtime, and no ambiguity about which key is in use.