Base path: /api/sdk. Authenticate with an SDK-type project key.
Create or identify a user
http
POST /api/sdk/users
Authorization: Bearer ek_client_...
Content-Type: application/json
{
"external_id": "user-123",
"tags": { "plan": "pro" },
"identity_hash": "optional-hmac-when-verification-enabled"
}Register a subscription
http
POST /api/sdk/users/user-123/subscriptions
Authorization: Bearer ek_client_...
{
"type": "IOS_PUSH",
"token": "apns-device-token",
"device_model": "iPhone15,2",
"device_os": "iOS 17.4",
"app_version": "1.2.0"
}Supported type values: IOS_PUSH, ANDROID_PUSH, EMAIL, SMS, WEB_PUSH.
Update tags
http
PUT /api/sdk/users/user-123/tags
Authorization: Bearer ek_client_...
{ "plan": "enterprise", "country": "PK" }Track an event
http
POST /api/sdk/events
Authorization: Bearer ek_client_...
{
"external_id": "user-123",
"name": "purchase_completed",
"properties": { "sku": "sku_123", "amount": 49.99 }
}Opt out
http
POST /api/sdk/opt-out
Authorization: Bearer ek_client_...
{ "external_id": "user-123", "subscription_type": "IOS_PUSH" }Buffering & idempotency
Identify, subscription, tag, event, and receipt calls are buffered: they return { "accepted": true } immediately and are applied by a worker, so a brief database blip never surfaces as an error. opt-out is processed synchronously so consent is confirmed.
For events, send a stable idempotency_key (e.g. a UUID per logical action). A retried request with the same key is applied exactly once; without one, a network retry would record a duplicate event.
