Skip to main content

API Reference

Base URL: http(s)://<server-host>:<port>

All endpoints except GET /v1/health and POST /v1/admin/keys (bootstrap only) require:

Authorization: Bearer <api-key>

Responses are JSON. Errors follow the shape:

{ "error": "description of what went wrong" }

Health

GET /v1/health

Returns server status and uptime. No authentication required.

Response 200

{ "status": "ok", "uptime": "3h42m10s" }

Event specs

GET /v1/events

List all published event specs. Requires viewer.

Query parameters

ParameterDescription
namespaceFilter by namespace
statusFilter by status: active, deprecated, deleted

Response 200 — array of event spec objects.


GET /v1/events/{namespace}/{name}

Get the latest version of an event spec. Requires viewer.

Response 200 — event spec object. 404 if not found.


GET /v1/events/{namespace}/{name}/{version}

Get a specific version of an event spec. Requires viewer.

Version format: MAJOR-MINOR-PATCH (e.g. 1-0-0).

Response 200 — event spec object. 404 if not found.


POST /v1/events

Publish a new event spec version. Requires publisher.

Request body — event spec YAML/JSON object.

Response 201 on success.


GET /v1/diff/{namespace}/{name}/{from}/{to}

Diff two event spec versions and return a list of changes. Requires viewer.

Response 200

[
{ "kind": "MAJOR", "field": "properties", "description": "required property 'price' removed" }
]

Analytics relay

All relay endpoints require viewer role and return 202 Accepted on success. The source field in every request body identifies which app is sending the event; the server resolves its configured destinations and routes accordingly.

See Analytics Relay for setup, routing, and server-side hook details.

POST /v1/track

Track a named event for a user or anonymous session.

Request body

{
"source": "web-app",
"event_name": "product_viewed",
"properties": { "product_id": "SKU-123" },
"context": {
"user_id": "user-456",
"anonymous_id": "anon-789",
"attributes": { "app_version": "2.1.0" }
},
"timestamp": "2024-01-15T12:00:00Z"
}
FieldRequiredDescription
sourceYesRegistered source name
event_nameYesEvent name matching a spec
propertiesNoEvent properties
contextNoUser identity and attributes
timestampNoEvent time (defaults to server receipt time)

Response 202 Accepted


POST /v1/identify

Associate a user ID with a set of traits.

Request body

{
"source": "web-app",
"user_id": "user-456",
"traits": { "email": "user@example.com", "plan": "pro" },
"context": { "anonymous_id": "anon-789" }
}
FieldRequiredDescription
sourceYesRegistered source name
user_idNoAuthenticated user identifier
traitsNoUser attributes to associate
contextNoAdditional identity context

Response 202 Accepted


POST /v1/group

Associate a user with a group (account, organisation, etc.).

Request body

{
"source": "web-app",
"group_id": "acme-corp",
"traits": { "name": "Acme Corp", "industry": "retail" },
"context": { "user_id": "user-456" }
}
FieldRequiredDescription
sourceYesRegistered source name
group_idYesGroup identifier
traitsNoGroup attributes
contextNoUser identity context

Response 202 Accepted


POST /v1/page

Record a page or screen view.

Request body

{
"source": "web-app",
"name": "Product Detail",
"properties": { "url": "/products/SKU-123", "referrer": "/search" },
"context": { "user_id": "user-456" }
}
FieldRequiredDescription
sourceYesRegistered source name
nameYesPage or screen name
propertiesNoPage properties
contextNoUser identity context

Response 202 Accepted


POST /v1/alias

Merge two user identities (e.g. anonymous → authenticated).

Request body

{
"source": "web-app",
"user_id": "user-456",
"previous_id": "anon-789"
}
FieldRequiredDescription
sourceYesRegistered source name
user_idYesThe new (canonical) user ID
previous_idYesThe ID to merge into user_id

Response 202 Accepted


POST /v1/batch

Send a mix of event types in a single request. The top-level context provides default identity for all items; per-item context overrides it field by field.

Request body

{
"source": "web-app",
"context": { "user_id": "user-456" },
"events": [
{
"type": "track",
"event_name": "checkout_started",
"properties": { "cart_total": 99.00 }
},
{
"type": "identify",
"user_id": "user-456",
"traits": { "ltv": 99.00 }
}
]
}
FieldRequiredDescription
sourceYesRegistered source name
contextNoDefault identity applied to all items
eventsYesArray of batch items

Batch item fields

FieldDescription
typeRequired. One of: track, identify, group, page, alias
event_nameEvent name (track only)
propertiesEvent or page properties (track, page)
traitsUser or group traits (identify, group)
user_idUser identifier (identify, alias)
previous_idPrevious user ID (alias)
group_idGroup identifier (group)
namePage name (page)
contextPer-item identity override
timestampPer-item event time

Response 202 Accepted


POST /v1/flush

Force delivery of any buffered events for a source. Omit source to flush all sources.

Request body

{ "source": "web-app" }
FieldRequiredDescription
sourceNoSource to flush. Omit to flush all.

Response 202 Accepted


API keys

POST /v1/admin/keys

Create an API key. No auth required when the server has zero keys (bootstrap); requires admin otherwise.

Request body

{
"role": "publisher",
"name": "web-app-prod",
"expires_in": "90d"
}
FieldRequiredDescription
roleYesviewer, publisher, or admin
nameNoHuman-readable label
expires_inNoDuration: 24h, 7d, 90d, 1y

Response 201

{ "id": 1, "key": "a3f8c2...", "role": "publisher" }

The raw key is returned once and never stored.


GET /v1/admin/keys

List all API keys. Requires admin. Raw key values are never returned.


DELETE /v1/admin/keys/{id}

Revoke an API key immediately. Requires admin. Returns 204 No Content.


Sources (apps)

GET /v1/admin/sources

List all registered sources. Requires admin.


POST /v1/admin/sources

Create a source. Requires admin.

Request body — source definition object:

{
"name": "web-app",
"platform": "web",
"language": "typescript",
"events": ["ecommerce/**"],
"destinations": ["amplitude-prod"]
}

Response 201 on success.


GET /v1/admin/sources/{name}

Get a source by name. Requires admin. Returns 404 if not found.


PUT /v1/admin/sources/{name}

Update a source. Requires admin. Full replacement — supply all fields.


DELETE /v1/admin/sources/{name}

Delete a source. Requires admin. Returns 204 No Content.


Destinations

GET /v1/admin/destinations

List all registered destinations. Requires admin.


POST /v1/admin/destinations

Create a destination. Requires admin.

Request body — destination definition object:

{
"name": "amplitude-prod",
"provider": "amplitude",
"config": { "api_key": "amp-key-here" }
}

Response 201 on success.


GET /v1/admin/destinations/{name}

Get a destination by name. Requires admin. Returns 404 if not found.


PUT /v1/admin/destinations/{name}

Update a destination. Requires admin. Full replacement — supply all fields.


DELETE /v1/admin/destinations/{name}

Delete a destination. Requires admin. Returns 204 No Content.


Audit log

GET /v1/audit

Query the server audit log. Requires admin.

Query parameters

ParameterDescription
sinceRFC3339 start time
untilRFC3339 end time
entityFilter by entity type: event, source, destination
userFilter by user/key ID
limitMax entries to return (default 50)

Webhooks

POST /v1/webhooks

Register a webhook URL. Requires admin.

Request body

{ "url": "https://hooks.example.com/event-spec" }

Response 201 on success. The server will POST a JSON payload to this URL whenever an event spec is published.


GET /v1/webhooks

List registered webhooks. Requires admin.


DELETE /v1/webhooks/{id}

Remove a webhook. Requires admin. Returns 204 No Content.


Configuration

GET /v1/admin/config

Get all server configuration settings. Requires admin.


PUT /v1/admin/config/{key}

Set a configuration value. Requires admin. Changes take effect immediately without a restart.

Request body

{ "value": "false" }

See Configuration for supported keys.


Source pull

GET /v1/sources/{name}/pull

Fetch a source's full event spec bundle for local caching (used by event-spec pull in server mode). Requires viewer.