Skip to content
Docs menu Servers

HTTP API

Send events from any language or platform with a single HTTP request. No library needed

On this page

Base URL and keys#

  • Base URL: https://events.sfere.io
  • Key: a server key for backend code. See Write keys.

Authenticate with Basic auth: the key is the username and the password is empty. In curl that is -u 'keyId:secret:'. You can also send the key in an X-Write-Key header.

Send one event#

POST /api/s/s2s/{type}, where {type} is track, page, screen, identify, group or alias.

Shell
curl https://events.sfere.io/api/s/s2s/track \
  -u 'YOUR_SERVER_KEY:' \
  -H 'Content-Type: application/json' \
  -d '{
    "messageId": "order-98765-purchase",
    "userId": "user_1234",
    "event": "purchase",
    "timestamp": "2026-10-21T10:00:00.000Z",
    "properties": {
      "transaction_id": "order_98765",
      "currency": "USD",
      "value": 313,
      "items": [{ "item_id": "sku_221", "item_name": "Linen Shirt", "price": 149, "quantity": 1 }],
      "sfere_dedup_id": "order-98765-purchase"
    },
    "context": {
      "ip": "203.0.113.7",
      "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X)",
      "traits": { "email": "customer@example.com", "phone": "+15555550123" },
      "page": { "url": "https://shop.example.com/checkout/thanks" }
    }
  }'

Replace YOUR_SERVER_KEY with the full keyId:secret value. The trailing colon is the empty password.

Identify a customer:

Shell
curl https://events.sfere.io/api/s/s2s/identify -u 'YOUR_SERVER_KEY:' -H 'Content-Type: application/json' \
  -d '{ "userId": "user_1234", "traits": { "email": "customer@example.com", "first_name": "Sara" } }'

Send a batch#

POST /v1/batch takes many events in one request. Each item needs a type, and a top-level context applies to every item. Keep each event under 1 MB.

Shell
curl https://events.sfere.io/v1/batch -u 'YOUR_SERVER_KEY:' -H 'Content-Type: application/json' \
  -d '{
    "batch": [
      { "type": "identify", "messageId": "m-1", "userId": "user_1234", "traits": { "email": "customer@example.com" } },
      { "type": "track", "messageId": "m-2", "userId": "user_1234", "event": "add_to_cart",
        "properties": { "currency": "USD", "value": 149, "items": [{ "item_id": "sku_221", "price": 149, "quantity": 1 }] } }
    ],
    "context": { "ip": "203.0.113.7", "userAgent": "Mozilla/5.0" }
  }'

Fields#

Field Required Notes
type Batch only On /api/s/s2s/{type} the path sets it.
userId or anonymousId One of them Use anonymousId for visitors who have not signed in.
messageId Recommended Unique per event: letters, digits, ., _ and -, up to 64 characters. Make it stable, such as order-98765-purchase, so a retried request is not counted twice.
event For track A GA4 name such as purchase, up to 128 characters. See Track events.
timestamp No ISO 8601. Defaults to when Sfere received the event.
properties, traits No Plain values. Do not hash email or phone.
context.ip, context.userAgent Yes, from a backend The customer’s, taken from their original request. Sfere cannot fill these in for server events, and ad platforms need them to match conversions.
context.clientIds Recommended Ad identifiers from the customer’s cookies and landing URL, such as fbp, fbc, ttp and gclid.
properties.sfere_dedup_id When the browser sends the same event Use the same value on both sides so destinations count the conversion once.

Every distinct property name becomes a column in your warehouse, so keep payloads flat and consistent.

Responses#

Endpoint Success Failure
/v1/batch 200 {"ok":true,"receivedEvents":2,"okEvents":2} 401 for an invalid key. okEvents lower than receivedEvents means some events were rejected.
/api/s/s2s/{type} 200 A wrong or missing key also returns 200, with the reason in the body. Read the body, or use /v1/batch when you need a clear error.

Retry only on 429 and 5xx, with backoff. Events over 1 MB are rejected.