API key reference
Which credential each Affitor call needs, where the program API key lives, how to replace it, and how mandatory rotation is signalled.
Affitor has one self-serve credential: the program API key. It authenticates server-side tracking calls for a single program, you manage it yourself from the dashboard, and it is the key the integration guides, the SDKs, the CLI's tracking setup, and the agent skill all refer to. CLI commands that create or list programs are different: they act as your account, so they authenticate with your CLI login rather than with this key.
The program API key at a glance
| Property | Value |
|---|---|
| Prefix | aff_ |
| Scope | One program. A key authenticates calls for the program it belongs to and nothing else. |
| Sent as | Authorization: Bearer <key> |
| Created | Automatically, when the program is created. A workspace owner can replace it at any time. |
| Visibility | Never returned by a read. The full value is shown only in the response to a regenerate request, so copy it there. |
# Test mode: checks that the key authenticates, without creating a real sale or commission.
curl -X POST https://api.affitor.com/api/v1/track/sale \
-H "Authorization: Bearer $AFFITOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "additional_data": { "test_mode": true } }'A 200 with test_mode: true in data means the key works. The call is not a no-op: it stores a sale event flagged as a test, writes a tracking log entry, and can move your integration checklist. It creates no commission and no platform fee. A real sale needs a transaction_id and a customer that already carries attribution — see Track a sale.
Keys issued before the short prefix was introduced do not start with aff_. Authentication is an exact match on the key itself, so those keys keep working; regenerating gives you an aff_ key.
Where to find it
- Select Settings in the left menu of your program.
- Under Developer, select API Key.
A program is given a key the moment it is created, but creating a program does not hand that value back to you. To get a key you can put in an environment variable, a workspace owner selects Generate — or Regenerate, if one was generated before — on the API Key tab. The full value appears in the response to that action, and only there. Copy it then and store it server-side:
# .env — server-side only. Never ship this key to the browser.
AFFITOR_API_KEY=YOUR_PROGRAM_API_KEYAfter that the tab shows a masked value with only the last few characters visible. If you no longer have the current value stored anywhere, you cannot recover it: generate a new one instead. The full click-path, including the one-time reveal, is in Manage program settings and your API key.
Program read endpoints never return the key. They expose api_token_masked only, so a leaked read response cannot be used to forge tracking calls. The value itself is returned in exactly one place: the response to the owner's own regenerate request.
Which calls need it
| Call | Key required |
|---|---|
POST /api/v1/track/sale | Yes |
POST /api/v1/track/refund | Yes |
POST /api/v1/track/lead — server mode | Yes. Sending the key is what makes the signup a server-attributed lead. |
POST /api/v1/track/lead — browser mode | No. The click cookie carries the attribution. On a program that requires server-side lead tracking, a browser lead is stored as provisional — the response says provisional: true — and a server-mode call is what settles it. |
POST /api/v1/track/click | No. Click tracking is public. |
Every endpoint above is documented in the API reference.
Replace a key
Regenerate the key if it may have leaked, if it was committed to a repository, or as routine hygiene when someone with key access leaves.
Only a workspace owner can generate or regenerate a program key. A member who tries is refused, so ask an owner to run it and to hand you the new value through your secret manager.
- Line up every place
AFFITOR_API_KEYis stored — deployment environment, secret manager, CI — so you can update them the moment you have the new value. - In Settings → API Key, regenerate the key. The old key stops working at that moment.
- Copy the new value from the one-time reveal, update those places, and redeploy.
The two keys never overlap. Regenerating replaces the key in place, and you receive the new value only in the regenerate response, so there is no way to deploy it in advance. Between the regenerate and the redeploy, calls still sending the old key get 401. Pick a window where a short gap in server-side tracking is acceptable.
When Affitor asks you to replace a key
Affitor can mark a specific program key for mandatory rotation — for example after the key was exposed outside your control. Marking it sets a deadline, and the two sides of that deadline behave differently:
- Before the deadline, the key still authenticates requests, so tracking keeps running until you are ready to swap it. Every response to a call made with that key carries
DeprecationandSunsetheaders plus aLinkheader pointing at the error reference, and the JSON body gains awarningsarray carrying the codeapi_key_rotation_requiredand the deadline. - At or after the deadline, the key stops working. Requests come back as
401with the same code inerror.code, and the three headers are still there. That response has nowarningsarray — the warning only exists while the key still works.
Replace the key before the deadline: past it, the old key is refused whether or not you are ready. Doing it early does not remove the changeover gap described under Replace a key — it only lets you choose when that gap happens. Branch on the code, not on the message text. The full header and body shapes are in api_key_rotation_required.
Replacing the key clears the flag: regenerate it in Settings → API Key and the warnings stop.
Agent API keys
Separately from program keys, Affitor issues agent API keys (prefix agt_) to approved tools that read and update programs on a brand's behalf through the /api/agent/v1/... endpoints.
These are issued by Affitor — there is no endpoint to create one yourself, and a program API key does not authenticate agent endpoints. Each agent endpoint also requires a specific scope on the key, so a valid agent key is still refused where it was not granted that scope. If you are building an integration that needs one, contact support.
If you only want an AI coding agent to install tracking for you, you do not need an agent key: point it at skill.md with your program API key in the environment. See Agent Integration.
Which key do I send?
| Your task | Key to send |
|---|---|
| Report a sale, a refund, or a server-mode lead | Program API key (aff_), from Settings → API Key |
| Record a click, or a browser-mode lead | No key — both are public calls. See Which calls need it. |
Read or update programs on a brand's behalf via /api/agent/v1/... | Agent API key (agt_), issued by Affitor |
Verify it worked
Send a test-mode call with the key in hand: it goes through the same authentication as a real sale, then stops before any commission or platform fee is created. Every cause of a 401, and its fix, is listed in the error reference.
- POST /api/v1/track/sale with additional_data.test_mode set to true returns 200 and test_mode: true in data — the key authenticates. The event is stored flagged as a test, and no commission or platform fee is created
- After regenerating, the same test-mode request with the old key returns 401 — rotation is complete
- Read the status before the body: a 200 with no warnings array means this key is not flagged for mandatory rotation. A flagged key that is past its deadline returns 401 and carries no warnings array either, so warnings alone never proves a key is unflagged
- Settings → API Key shows a masked value whose visible characters match the key your server sends
- On a 401, read error.code first. api_key_rotation_required means the key passed its rotation deadline — regenerate it, because re-copying the same key will not bring it back. Any other 401 means the header is malformed or the key matches no program: check the Authorization: Bearer prefix and your environment variable for trailing whitespace
- A rejected call to /api/agent/v1/... has more than one cause, so read the error message instead of inferring from the status. Check the key type — only an agt_ key authenticates agent endpoints, a program key never does — and check that the agent key was granted the scope that endpoint requires