Server-side

Server events (API)

Report conversions from your backend — immune to ad-blockers, reflecting server truth (payment captured, not just a thank-you page). Server events flow straight into Goals & Funnels.

Authentication

Create an API key in the dashboard under API keys, then send it as a Bearer token. Keep it server-side only — never ship it to the browser.

Authorization: Bearer servoki_xxxxxxxxxxxxxxxx

Endpoint

POST https://servoki.com/api/events/server

Request body

{
  "site": "{{site}}",          // domain or numeric site code
  "event_type": "purchase",       // required
  "vid": "anon-abc123",           // optional: visitor id to stitch to the browser
  "value": 49.90,                 // optional: summed as revenue
  "currency": "EUR",              // optional: 3-letter ISO code
  "event_id": "order_8841",       // optional: dedup / idempotency key
  "occurred_at": "2026-06-12T10:00:00Z", // optional: defaults to now
  "props": { "plan": "pro" },     // optional: grouping properties
  "consent": true                 // optional: required to forward to ad platforms
}

Only site and event_type are required. The site value accepts either your domain or the site's numeric code.

Deduplication

Pass a stable event_id (your order id works well). Servoki treats repeated events with the same id as one — so retries are safe, and a server purchase won't double-count against a browser purchase carrying the same id.

cURL

curl -X POST https://servoki.com/api/events/server \
  -H "authorization: Bearer $SERVOKI_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "site": "{{site}}",
    "event_type": "purchase",
    "value": 49.90,
    "currency": "EUR",
    "event_id": "order_8841",
    "vid": "anon-abc123"
  }'

Node.js

await fetch('https://servoki.com/api/events/server', {
  method: 'POST',
  headers: {
    'authorization': `Bearer ${process.env.SERVOKI_API_KEY}`,
    'content-type': 'application/json',
  },
  body: JSON.stringify({
    site: '{{site}}',
    event_type: 'purchase',
    value: order.total,
    currency: order.currency,
    event_id: order.id,        // idempotency key — safe to retry
    vid: order.visitorId,      // same id set in the browser
    props: { plan: order.plan },
  }),
});

Responses

  • 202 — accepted.
  • 400 — invalid body (missing event_type, bad currency, etc.).
  • 401 — missing or invalid API key.
  • 404 — unknown site.

Rate limit: 600 requests/minute per IP by default. Batch high-volume backends behind a queue if you approach it.