API reference
Send server events over HTTP from any language.
Use the HTTP API to send server events from a backend that can't use the Node.js SDK. It records the same events as the SDK's capture().
Identify in the browser too
A server event only counts for a user your site has identified with the browser SDK. Pass the same user ID in both places. Wallet addresses are the exception: they count from the server on their own.
Endpoint
POST https://spfsrv.com/v1/eventsAuthentication
| Header | Value | Required |
|---|---|---|
Content-Type | application/json | Yes |
x-api-key | Your advertiser key, which starts with sak_ | Yes |
Request
Body
{
"source": "server",
"identity": "user_8f3a2c",
"events": [
{
"name": "purchase",
"dedupeKey": "order_1042"
}
]
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
source | string | Yes | Always "server" |
identity | string | Yes | The user ID your site passes to identify(), or a wallet address |
events | object[] | Yes | 1 to 50 events for this identity |
events[].name | string | Yes | The event name, such as purchase |
events[].dedupeKey | string | No | Your own ID for this event, such as an order ID, up to 256 characters. Send one with every event |
events[].url | string | No | The page where the event happened, as an absolute URL |
Specify rejects a body with any other field, and a body larger than 16 KiB.
Identity
- A wallet address is
0xfollowed by 40 hexadecimal characters, in any case. - A user ID can't be blank, contain
@, start with0x, or be longer than 256 bytes. Use the ID your app gives the user, not their email address.
Response
Every response has an empty body.
| Code | Meaning | What to do |
|---|---|---|
200 | Recorded | Nothing |
400 | Invalid body | Check it against the parameters. Don't retry |
401 | Invalid, revoked or unknown advertiser key | Check the key. Don't retry |
429 | Too many events at once | Retry |
503 | Specify is temporarily unavailable | Retry |
Avoid double counting
Send a dedupeKey with every event. Events with the same name and dedupeKey count once, so retries and repeated webhooks are safe. Without one, every request counts, including a retry of a request Specify already recorded.
For an event that happens once per user, such as passing KYC, the user ID works as the dedupeKey.
Retries
Give each request a 5 second timeout. After a timeout, a network error, a 429 or a 5xx, retry twice: after 1 second, then after 2 seconds.
If the event still isn't recorded, log it and continue, so a problem on Specify's side can't break your handler.
Examples
Each example sends one event, retries as above, and logs a failure without raising it.
curl -X POST https://spfsrv.com/v1/events \
-H "Content-Type: application/json" \
-H "x-api-key: $SPECIFY_ADVERTISER_KEY" \
-w "%{http_code}\n" \
-d '{
"source": "server",
"identity": "user_8f3a2c",
"events": [{ "name": "purchase", "dedupeKey": "order_1042" }]
}'Check it works
Send an event with a development key. A 200 means Specify accepted it, and the event appears in the event log on the Integration page within a few seconds. Development events never count towards your results.
When you're ready to go live, replace the development key with a production key.