IngestionHTTP Endpoints

HTTP Endpoints

Datafly Signal exposes four browser-facing endpoints consumed by the Datafly.js SDK. All four accept POST requests with a JSON body and are authenticated via a pipeline key.

Endpoints

EndpointMethodDescription
/v1/tPOSTTrack a custom event
/v1/pPOSTTrack a page view
/v1/iPOSTIdentify a user
/v1/gPOSTAssociate a user with a group

Authentication

Browser requests authenticate using a pipeline key (a UUID, one per pipeline). The key can be provided in two ways:

  1. Authorization header (preferred for programmatic use):
Authorization: Bearer 3f2a9c1e-7b4d-4e8a-9c6f-1d2e3f4a5b6c
  1. pipeline_key query parameter (used by Datafly.js for its sendBeacon flush to /v1/batch, which cannot set headers):
POST /v1/batch?pipeline_key=3f2a9c1e-7b4d-4e8a-9c6f-1d2e3f4a5b6c

Datafly.js sends the header for you. The pipeline key is baked into the collector build served for your pipeline, so the script tag needs no attributes.

Datafly Signal validates the pipeline key on every request. If the key is missing, invalid, or revoked, Datafly Signal returns a 401 Unauthorized response.

Track Event — POST /v1/t

Tracks a named event with optional properties.

Request

{
  "type": "track",
  "event": "add_to_cart",
  "properties": {
    "currency": "USD",
    "value": 79.99,
    "items": [
      { "item_id": "SKU-1234", "item_name": "Wireless Headphones", "price": 79.99, "quantity": 1 }
    ]
  },
  "context": {
    "page": {
      "url": "https://shop.example.com/products/headphones",
      "title": "Wireless Headphones | Shop",
      "referrer": "https://shop.example.com/category/audio"
    },
    "user_agent": "Mozilla/5.0 ...",
    "locale": "en-US",
    "timezone": "America/New_York"
  },
  "timestamp": "2026-02-25T14:30:00.000Z",
  "messageId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Response

{
  "success": true
}

Status codes: 200 on success, 400 for invalid payload, 401 for invalid pipeline key, 429 if rate-limited.

Page Event — POST /v1/p

Records a page view. Datafly.js sends this automatically on every page load and client-side navigation.

Request

{
  "type": "page",
  "event": "page",
  "context": {
    "page": {
      "url": "https://shop.example.com/products/headphones?color=black",
      "title": "Wireless Headphones | Shop",
      "referrer": "https://shop.example.com/category/audio",
      "path": "/products/headphones",
      "search": "?color=black"
    },
    "user_agent": "Mozilla/5.0 ...",
    "locale": "en-US"
  },
  "timestamp": "2026-02-25T14:30:00.000Z",
  "messageId": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
}

Response

{
  "success": true
}

Identify Event — POST /v1/i

Associates the current anonymous visitor with a known user identity.

Request

{
  "type": "identify",
  "userId": "user_98765",
  "traits": {
    "email": "jane@example.com",
    "name": "Jane Smith",
    "plan": "premium",
    "created_at": "2025-03-15T10:00:00.000Z"
  },
  "context": {
    "user_agent": "Mozilla/5.0 ...",
    "locale": "en-US"
  },
  "timestamp": "2026-02-25T14:30:00.000Z",
  "messageId": "c3d4e5f6-a7b8-9012-cdef-123456789012"
}

Response

{
  "success": true
}

After an identify call, Datafly Signal links the anonymous identifier to the provided userId. All subsequent events from this visitor will carry both identifiers.

Group Event — POST /v1/g

Associates a user with a group such as a company, team, or account.

Request

{
  "type": "group",
  "groupId": "org_555",
  "traits": {
    "name": "Acme Corp",
    "industry": "Technology",
    "employees": 250,
    "plan": "enterprise"
  },
  "context": {
    "user_agent": "Mozilla/5.0 ...",
    "locale": "en-US"
  },
  "timestamp": "2026-02-25T14:30:00.000Z",
  "messageId": "d4e5f6a7-b8c9-0123-defa-234567890123"
}

Response

{
  "success": true
}

Common Request Fields

Every event sent to these endpoints includes the following fields:

FieldTypeRequiredDescription
typestringYesEvent type: track, page, identify, or group
eventstringTrack onlyName of the event (e.g. "purchase")
namestringPage onlyName of the page (e.g. "Checkout")
userIdstringNoKnown user ID (required for identify)
groupIdstringGroup onlyGroup identifier
propertiesobjectNoEvent-specific data
traitsobjectNoUser or group attributes (identify/group events)
contextobjectNoContextual data (page, user agent, locale, etc.)
timestampstringNoISO 8601 timestamp; defaults to server receipt time
messageIdstringNoClient-generated UUID. An event sent again with the same messageId within 24 hours is acknowledged and not delivered twice

Common Response Headers

All endpoints return the following headers:

HeaderValue
Content-Typeapplication/json
Access-Control-Allow-OriginConfigured origin(s) for the source
Access-Control-Allow-MethodsPOST, OPTIONS
Access-Control-Allow-HeadersContent-Type, Authorization
Access-Control-Allow-Credentialstrue

CORS

Datafly Signal handles OPTIONS preflight requests automatically. Allowed origins are derived from the source configuration associated with the pipeline key. If the Origin header does not match any configured origin, the request is rejected with a 403 Forbidden response.

⚠️

In development mode, localhost origins are allowed by default. In production, you must explicitly configure allowed origins in the source settings via the Management UI.

Rate Limiting

Browser endpoints are rate-limited per pipeline key. The default limit is 1,000 requests per second per source. When the limit is exceeded, Datafly Signal returns a 429 Too Many Requests response with a Retry-After header.

Error Responses

All endpoints return JSON error bodies in a consistent shape:

{
  "error": "invalid_pipeline_key",
  "message": "The supplied pipeline key was not recognised."
}
StatusWhenRetry behaviour
200Event accepted—
400Malformed JSON, missing required field, or schema validation failedDon’t retry — fix the payload
401Invalid or missing pipeline keyDon’t retry — check the key
403Origin not in source allowlist (browser endpoints), or IP-allowlist mismatch (server endpoints)Don’t retry — fix configuration
413Payload exceeded the request size limit (typically 1 MB)Don’t retry — split into smaller batches
429Rate limit exceeded for this pipeline keyRetry after the Retry-After header value
500Unexpected server-side errorRetry with exponential backoff
502 / 504Gateway is briefly unavailable (rolling deploy, upstream timeout)Retry with exponential backoff
503Backpressure — Datafly Signal is overloaded and is shedding load to protect downstream, or an earlier request is still processing an event with the same messageIdRetry with exponential backoff; honour Retry-After if present

For server-side integrations, we recommend retrying 5xx responses with exponential backoff starting at 1 second, doubling up to 60 seconds, with jitter. Treat any 4xx response other than 429 as a permanent failure for that event — log it and move on.

The official Datafly server-side libraries handle this retry logic for you.