HTTP API for ingestion and export.
Two endpoints right now: POST /v1/ingest for the Unity SDK to push events, and GET /v1/export for Pro/Studio tier customers to pull their data back out. Both authenticate via X-API-Key — no JWT.
Base URL
https://<your-supabase-project>.supabase.co/functions/v1/The dashboard's quickstart covers SDK configuration. The URL is set in TracedConfig.IngestUrl on the Unity side.
Auth
Every request must include an X-API-Key header. Keys are scoped to a single project. Keys with the sp_test_ prefix are for development and don't count toward your monthly quota; sp_live_ keys go in shipped builds.
POST /v1/ingest
Used by the SDK. You almost never call this directly — the SDK batches, gzips, and retries automatically. Spec is documented here for SDK developers and self-host integrators.
Headers
X-API-Key: sp_live_…(required)Content-Type: application/jsonContent-Encoding: gzip(optional; SDK uses it by default)
Body (JSON, gzipped or plain)
{
"project_id": "uuid",
"session_id": "string",
"sdk_version": "0.2.0",
"sent_at_ms": 1700000000000,
"session_context": { "map": "arena_01", "mode": "deathmatch" },
"events": [
{
"shape": "point|oriented|pair|volume|frustum|point_with_trail",
"event_id": "death",
"ts": 1700000000000,
"player_id": "p_42",
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 90, "z": 0 },
"from": { "x": 0, "y": 0, "z": 0 },
"to": { "x": 0, "y": 0, "z": 0 },
"center": { "x": 0, "y": 0, "z": 0 }, "radius": 1.5,
"fov": 90, "range": 25,
"metadata": { "weapon": "sniper" }
}
],
"position_samples": [
{ "ts": 1700000000000, "player_id": "p_42",
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0 },
"velocity": { "x": 0, "y": 0, "z": 0 } }
]
}Responses
- 202 Accepted — events ingested. Body:
{ ok, events, positions, session }. - 400 — invalid body / missing session_id.
- 401 — bad / missing API key.
- 403 —
project_id_mismatchorposition_streams_require_pro. - 500 — backend error. Retry; the SDK will queue on disk and retry automatically.
GET /v1/export
Read-only bulk export of events and (optionally) position samples for a single project. Pro / Studio tier only — Free returns 403. Use this for compliance audits, custom dashboards, or feeding event data into ML pipelines.
Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
since | ISO 8601 | none | Lower bound (inclusive) on timestamp. |
until | ISO 8601 | none | Upper bound (inclusive). |
event_id | string | any | Filter to a single event_id. |
shape | string | any | One of point / oriented / pair / volume / frustum / point_with_trail. |
session_id | string | any | Filter to a single session. |
limit | int | tier cap | Max rows. Capped to 50,000 (Pro) or 250,000 (Studio). |
format | json / ndjson | json | NDJSON streams; recommended for > 10k rows. |
include_positions | bool | false | Also export position_samples (same filters). |
Example
# Last week's death events as NDJSON
curl -H "X-API-Key: sp_live_..." \
"https://<project>.supabase.co/functions/v1/export?event_id=death&since=2026-05-08T00:00:00Z&format=ndjson"Pagination
For datasets larger than your tier cap, walk forward by passing the last response's most-recent timestamp as the next request's since. NDJSON responses include an x-spatialpulse-event-count header.
Coming soon
POST /v1/projects— programmatic project creation (Studio tier).POST /v1/event-styles— bulk style overrides via API.- Webhooks — fire on aggregate events (e.g., death cluster threshold exceeded).
For self-hosted deployments, all functions live in backend/functions/ in the monorepo. Deploy via supabase functions deploy <name>.