API Keys
Create Siren Cloud API keys for your own code, choose the events and records each key can reach, and expire, revoke, or replace a key.
Siren Cloud
Last updated: October 28, 2026
An API key lets your own code work with Siren Cloud without a person signed in. Your code sends the key with each request, and Siren Cloud lets it do only what the key’s scopes allow. You’d use one when:
- Your own server or checkout sends sales, visits, refunds, or custom events to Siren Cloud.
- A script or reporting tool reads your ledger, such as conversions, transactions, obligations, and payouts.
- Your code reads or manages records such as products, coupons, collaborators, and programs.
- A deploy script or another service creates and manages your webhooks.
You don’t need a key for a store you’ve connected. Stripe, Shopify, and the Siren Cloud Connector already send that store’s sales.
Only Admins see the API keys tab on the Developer screen and create or revoke keys. A key looks like sk_live_ followed by 64 characters, and your code sends it as Authorization: Bearer sk_live_.... Siren Cloud shows a key once, when you create it, and keeps only a fingerprint of it after that. Keep keys on your server and out of browser code.
The list may show a key labeled “Initial API key”, which Siren Cloud creates when it sets up some organizations. It sends every core and custom event type and reads nothing. Its value isn’t shown anywhere, so create your own key for your code.
Make your first call
These steps create a key, check it, and send one test sale you can then find on your dashboard. You need an active program that rewards sales and an active collaborator in it. The test records a real sale in your ledger, so use a collaborator you made for testing.
A sale names the visit that led to it in trackingId, and Siren Cloud records nothing for a sale whose trackingId matches no visit. So the test records a visit first, and the key needs two event scopes, one for each.
1. Create a key for the test
Open Developer, then API keys, and click “Create Key”. Label it “First call test”. Under “Events this key can send”, click “Search scopes…”, type site-visited, and pick event:site-visited. Search again for sale and pick event:sale. Set “Expiration” to 30 days so the key doesn’t outlive the test, click “Create Key”, and copy the key. Then keep it in your terminal:
export SIREN_KEY="sk_live_..."
2. Check the key
curl https://api.sirenaffiliates.com/siren/v1/ping \
-H "Authorization: Bearer $SIREN_KEY"
An active key gets 200 with your organization, such as { "ok": true, "org": { "id": 1, "name": "Acme" } }. /ping needs no scope. A 401 means Siren Cloud doesn’t know the key, or it has expired or been revoked.
3. Record a visit
Open the collaborator under Collaborators. Their id is the number at the end of the address, such as /collaborators/42. Send a visit for them:
curl https://api.sirenaffiliates.com/siren/v1/event/site-visited \
-H "Authorization: Bearer $SIREN_KEY" \
-H "Content-Type: application/json" \
-d '{ "collaboratorId": 42 }'
The answer carries opportunityId, the visit’s id, which the sale needs. status is attributed when one of the collaborator’s programs rewards the visit and recorded when none does. Either way, keep the opportunityId. not_attributed means Siren Cloud wrote nothing, and reason says why, such as collaborator_not_found.
4. Send a test sale
Put the opportunityId in trackingId:
curl https://api.sirenaffiliates.com/siren/v1/event/sale \
-H "Authorization: Bearer $SIREN_KEY" \
-H "Content-Type: application/json" \
-d '{ "source": "test", "externalId": "test-1001", "trackingId": 4218, "total": 10.00 }'
The answer’s status is created when a program awarded the collaborator a conversion, and recorded when Siren Cloud saved the sale and it earned nothing, with a reason that says why. Sending the same source and externalId again answers duplicate and records nothing, so change externalId to send another. Report a Sale covers every field and answer.
5. Find the sale in Siren Cloud
Open Transactions in the sidebar. It lists the newest first, so the test sale is at the top, for 10.00 in your organization’s default currency. When the answer said created, Conversions lists the collaborator’s new conversion too.
When your real code is ready, create a key with only the scopes it needs, and revoke the test key.
Create a key
Open Developer, then API keys, and click "Create Key"
Name it
"Label (optional)" is for you, such as "Production integration".
Choose its scopes
Under "Events this key can send", tick "All events" or search for single events. Under "Records this key can read and manage", tick the scopes the key needs, grouped as Ledger, Webhooks, Products, Coupons, and the other records. The key needs at least one scope.
Choose a Property
When your organization has Properties, "Property" offers "Every property" or one Property. A key bound to a Property records what it sends for that Property.
Choose when it expires
"Expiration" is Never, 30 days, 90 days, or 1 year.
Click "Create Key" and copy the key
The "API Key Created" dialog shows the key with a copy button. Save it now, because Siren Cloud can't show it again.
The “JSON Manifest” tab creates a key from JSON instead, such as { "label": "Production integration", "scopes": ["event:sale", "ledger:conversions:read"], "expiresIn": "90d" }. expiresIn is never, 30d, 90d, or 365d. A key made this way is always for every Property, so use the Form tab to bind a key to a Property. The download icon on a key’s row, “Export manifest”, shows the key’s manifest to copy, without its Property and with its expiry rounded up to 30d, 90d, or 365d.
An organization can have 250 active keys. Revoked keys don’t count, but expired keys do until you revoke them.
Scopes
A scope names what a key may do. A key can do only what its scopes allow.
| Scope | In the form | Allows |
|---|---|---|
event:* | All events | Send every core and custom event type, including types added later |
event:sale, event:site-visited, event:refund | The event’s name, such as “Sale” | Send that one event |
event:{slug} for a custom event | The custom event’s name | Send that custom event |
ledger:engagements:read | Read engagements | GET /engagements, GET /engagements/{id}, and the engagement type and calculation lists |
ledger:opportunities:read | Read opportunities | GET /opportunities and GET /opportunities/{id} |
ledger:conversions:read | Read conversions | GET /conversions and GET /conversions/{id} |
ledger:transactions:read | Read transactions | GET /transactions and GET /transactions/{id} |
ledger:obligations:read | Read obligations | GET /obligations and GET /obligations/{id} |
ledger:fulfillments:read | Read fulfillments | GET /fulfillments and GET /fulfillments/{id} |
ledger:payouts:read | Read payouts | GET /payouts and GET /payouts/{id} |
webhook-subscriptions:read | Read webhooks and their deliveries | List and read webhooks, the event catalog, and delivery history |
webhook-subscriptions:manage | Create, change, delete and test webhooks | Everything the read scope allows, and creating, changing, deleting, and testing webhooks |
records:products:read, records:products:manage | Products | Read products, their store listings, and match suggestions. Manage also adds, renames, merges, and splits products and sets their owners |
records:coupons:read, records:coupons:manage | Coupons | Read coupons and their store listings. Manage also adds, links, renames, merges, splits, and removes coupons |
records:collaborators:read, records:collaborators:manage | Collaborators | Read collaborators and their program enrollments. Manage also adds, changes, and deletes collaborators and enrolls them in programs |
records:collaborator-groups:read, records:collaborator-groups:manage | Collaborator groups | Read collaborator groups and their members. Manage also adds, changes, and deletes them and their members |
records:programs:read, records:programs:manage | Programs | Read programs. Manage also adds, changes, and deletes them |
records:program-groups:read, records:program-groups:manage | Program groups | Read program groups. Manage also adds, changes, and deletes them |
records:distributors:read, records:distributors:manage | Distributors | Read distributors and their distributions. Manage also adds, changes, and deletes distributors |
records:application-forms:read, records:application-forms:manage | Application forms | Read application forms. Manage also adds, changes, and deletes them |
records:applications:read, records:applications:manage | Applications | Read applications and their answers. Manage also approves and declines them |
records:notification-rules:read, records:notification-rules:manage | Notification rules | Read notification rules. Manage also adds, changes, and deletes them |
records:properties:read | Properties | Read Properties and what each is connected to |
A manage scope also allows everything its read scope allows. These scopes count only by their exact name, so “All events”, *, and wildcards such as records:* grant none of them.
On these routes a key acts as an Admin would, across every collaborator, and takes the same filters, fields, and bodies the Resource Reference describes. A route your plan doesn’t include refuses a key too. No scope reaches API keys, members, invitations, billing, your organization’s settings, connected sites, payout credentials and destinations, customers, or store credit codes. No scope approves or changes conversions and obligations, makes fulfillments or payouts, or sends a test notification. Those stay with a signed-in Admin.
The scope search also lists the events the Siren Cloud Connector sends for a connected WordPress site, such as “Coupon Created” and event:sale-triggered. Those take the connector’s own format, and some of them approve conversions and spend store credit, so “All events” leaves them out. Your own keys shouldn’t hold them.
Keys bound to a Property
A key bound to a Property reads only that Property’s engagements, conversions, transactions, and obligations, and a read of another Property’s record by id answers 404. It sees products and coupons with a listing at its Property, adds them only there, and changes one only when no other Property sells it, or gets 403. GET /properties lists only its Property. Every other record belongs to the whole organization, so a key bound to a Property gets 403 with the code store_key_not_allowed there. A key for every Property reads everything, and can narrow a read to one Property with ?propertyId= or the X-Siren-Property header. Events it sends belong to no Property, so use a key bound to a Property to record a store’s sales for that store.
Expire, revoke, and replace a key
After its expiry date, a key gets 401 “API key has expired.” The list still shows its status as “Active”, with “(expired)” in the Expires column.
To revoke a key, click “Revoke” on the key’s row, then “Revoke Key”. Anything using the key stops working at once, with 401 “API key has been revoked.” Revoking can’t be undone. While your organization has no plan, nobody can revoke a key from the dashboard, as When your plan lapses explains.
Keys can’t be rotated or edited. Create a new key with the same scopes, switch your code to it, then revoke the old one.
“Last Used” shows when each key last sent an event or read or changed a record.
Errors
| Answer | Meaning |
|---|---|
401 “Missing or invalid Authorization header.” | The request has no Authorization: Bearer header |
401 “Invalid API key.” | Siren Cloud doesn’t know the key |
401 “API key has expired.” or “API key has been revoked.” | The key has expired or been revoked |
401 with code api_key_not_accepted | The route doesn’t take API keys |
403 with code missing_scope or not_permitted | The key lacks the scope for this event or route. On a record route, error.context.anyOf lists every scope that opens it |
403 with code store_key_not_allowed | A key bound to a Property asked for records that belong to the whole organization |
429 | Too many requests. Wait for the seconds in Retry-After |