Pipeline API

The Pipeline API is the single entry point to Persona. Everything happens under /api/v2/pipeline: you POST events to ingest them, GET your runtime config, and hold an open GET to receive live segment changes. All requests and responses are JSON unless noted, and every endpoint shares the same bearer authentication.

Base URL for this project:

base url
https://org.persona-tech.xyz/api/v2/pipeline

Quickstart

Send your first event with the browser SDK, then open a stream to watch it flow through.

quickstart.html
<script src="/assets/sdk.js"></script>
<script>
  persona.init("pk_live_8Q2f…");
  persona.track("page_viewed", { path: location.pathname });
</script>

Authentication

Authenticate every request with a project key in the Authorization header. Use a publishable key (pk_live_…) from the browser and a secret key (sk_live_…) server-side. Keys are scoped per project and can be rotated at any time.

header
Authorization: Bearer pk_live_8Q2f…
Publishable keys are write-only for ingestion. Reading config or opening a stream from the browser is scoped to the originating project only.

POST /api/v2/pipeline/ingest

Submit a batch of one or more events. Batches are accepted optimistically and processed asynchronously; the response confirms receipt, not downstream delivery. Clients typically flush on an interval or when a batch fills, so a busy page sends many small POSTs in sequence.

FieldTypeDescription
batch requiredarrayArray of event objects. Up to 256 events per request.
sentAtstringISO-8601 client timestamp, used for clock-skew correction.
contextobjectOptional device, page, and library metadata.
request
POST /api/v2/pipeline/ingest
Content-Type: application/json

{
  "batch": [
    { "type": "track", "event": "checkout_completed",
      "properties": { "value": 4900 } }
  ],
  "sentAt": "2026-06-09T10:14:05Z"
}
202 Accepted
{ "accepted": 1, "batchId": "b_3kPq…" }

GET /api/v2/pipeline/config

Fetch the runtime configuration for your project: sampling rules, enabled destinations, and feature flags. SDKs poll this on a short interval so changes roll out without a redeploy.

200 OK
{
  "flags": { "streaming": true, "sampleRate": 1.0 },
  "flushIntervalMs": 15000,
  "refreshAfter": 45
}

GET /api/v2/pipeline/stream

Open a long-lived connection to receive segment changes as they happen. The response is an text/event-stream that stays open; the server pushes a frame whenever a profile enters or leaves one of your personas. Keep one connection per client and reconnect with Last-Event-ID to resume.

ParameterInDescription
personaqueryFilter to one or more persona ids. Repeatable.
Last-Event-IDheaderResume the stream after the given event id.
stream
GET /api/v2/pipeline/stream?persona=high_intent
Accept: text/event-stream

id: 1487
event: segment.updated
data: {"profile":"u_9af…","persona":"high_intent","op":"enter"}

id: 1488
event: heartbeat
data: {}
Streams are kept alive with periodic heartbeat frames. Connections idle for longer than 15 minutes are closed; clients should reconnect automatically.

Errors & limits

The API uses conventional status codes. Ingestion is rate-limited per key with a generous burst allowance; exceeding it returns 429 with a Retry-After header.

CodeMeaning
202Batch accepted for processing.
400Malformed payload or batch too large.
401Missing or invalid project key.
429Rate limited; retry after the given delay.

SDKs

Official libraries wrap batching, retries, and reconnection so you only call track() and subscribe().

LibraryInstall
Browser<script src="/assets/sdk.js">
Nodenpm i @persona/node
Gogo get persona.dev/go