Ingest API

The SDKs talk to a regional collector over plain HTTPS and JSON. This page documents that contract so you can inspect traffic, write a client for a platform we do not ship an SDK for, or allow the endpoints in a network policy.

Collector host

Every project is assigned a collector in its home region. The host is shown in the console under project settings and delivered to the SDK during the first upload handshake. Collector hosts are stable for the lifetime of a project; if we ever need to move a project, the previous host keeps accepting traffic for at least 90 days and answers with a Gatepost-Collector header naming the new one.

All endpoints below are relative to https://<collector-host>. Collectors accept TLS 1.2 and 1.3 with HTTP/1.1 and HTTP/2. Plain HTTP is redirected to HTTPS and never accepts data.

Authentication

The project key is part of the path, not a header, so the same URL works from any HTTP client and shows up cleanly in network inspectors. Keys are write-only: a request with a valid key can add telemetry to the project and nothing else. There is no endpoint on a collector that returns customer data.

RequestResponse
POST /v1/rum without a key401 {"error":"missing project key"}
POST /v1/rum/<unknown-key>401 {"error":"invalid project key"}
POST /v1/rum/<PROJECT_KEY> with a valid batch202 {"accepted":128}

Endpoints

POST/v1/rum/<PROJECT_KEY>

Upload a batch of session events: app start phases, screens, frames, HTTP requests, crashes, custom events. One batch belongs to one session. The SDK sends a batch every 30 seconds in the foreground, when the session ends, or when the pending batch reaches 256 KB compressed.

POST/v1/traces/<PROJECT_KEY>

Upload spans from custom traces and automatic traces. Spans reference the session they belong to. They are sent on the same schedule as events but through a separate endpoint so trace-heavy apps can be rate limited independently.

GET/health

Liveness check. Returns 200 with the collector's region and no caching. Use it from uptime monitors or a network policy validator. It does not require a key and does not count towards any limit.

{"status":"ok","region":"eu-central"}

GET/diagnostics

A human-readable page that runs a reachability and throughput check from the browser it is opened in: latency to the collector, download and upload rates, and the region answering. Open it on a device when sessions are not arriving and you suspect the network. It is a browser page, not an API, and the checks run only when you press the button.

Request format

  • Content-Type: application/json. Batches larger than 1 KB should be sent with Content-Encoding: gzip; the SDKs always compress.
  • Maximum body size: 256 KB after compression, 4 MB before. Larger requests are rejected with 413.
  • Timestamps are Unix milliseconds. The batch carries the device clock at send time, so the collector can correct clock skew.
  • Every batch carries a batch_id (UUID v4). A batch retried with the same ID is accepted once.
POST /v1/rum/4f9c2e1b8a7d63e0 HTTP/1.1
Host: <collector-host>
Content-Type: application/json
Content-Encoding: gzip
User-Agent: gatepost-android/2.9.0

{
  "batch_id": "0d0f1c9a-5b0e-4a1e-9b8c-2a5e2f4d7c31",
  "sent_at": 1757520091123,
  "sdk":     { "name": "gatepost-android", "version": "2.9.0" },
  "app":     { "id": "com.example.shop", "release": "4.12.0",
               "build": "41200", "env": "production" },
  "device":  { "os": "android", "os_version": "15", "model": "SM-A556B",
               "locale": "ru-RU", "network": "cellular", "memory_class": "mid" },
  "session": { "id": "8f3c41d0-3d2e-4b8c-9a1f-6e2b7c0d5a94",
               "started_at": 1757520040000, "sample_rate": 1.0 },
  "events": [
    { "type": "app_start", "ts": 1757520040000, "kind": "cold", "duration_ms": 812,
      "phases": { "process": 210, "framework": 315, "first_frame": 287 } },
    { "type": "screen", "ts": 1757520040905, "name": "Home", "ttfr_ms": 275 },
    { "type": "http",   "ts": 1757520040930, "method": "GET",
      "host": "api.example.com", "route": "/catalog", "status": 200,
      "duration_ms": 143, "tls_ms": 38, "ttfb_ms": 121,
      "req_bytes": 0, "res_bytes": 18422 },
    { "type": "frame",  "ts": 1757520041080, "screen": "Home", "duration_ms": 185, "frozen": false }
  ]
}

Spans posted to /v1/traces use the same envelope with a spans array instead of events. Each span has trace_id, span_id, optional parent_id, name, start, end, status and up to 64 attributes.

Response codes

CodeMeaningWhat the SDK does
202Batch accepted and queued for the storage region.Deletes the batch from the on-device buffer.
400Malformed JSON or missing required fields. The body names the first problem.Drops the batch and logs a warning. Never retried.
401Missing or invalid project key.Drops the batch and logs a warning. Sessions continue to be recorded locally in case the key is rotated.
413Body too large.Splits the batch in half and retries each part.
429Project over its ingest rate. Retry-After is set.Waits the indicated time, then retries. The buffer keeps up to 24 hours of events.
503Collector draining or overloaded. Retry-After is set.Retries with exponential backoff starting at 5 seconds, capped at 15 minutes.

Retries and offline behaviour

Batches are written to disk before they are sent. On any network error or 5xx the SDK backs off exponentially with jitter, and events keep accumulating locally for up to 24 hours or 8 MB, whichever comes first, after which the oldest are dropped. Batches are always sent in order, so a session is never delivered with a hole in the middle. Uploads are never attempted while the device reports it is in a restricted background data mode.

Rate limits

Limits are per project and generous for real traffic: 1,000 batches per second and 50 MB per minute on the Team plan, higher on Business. The intent is to protect a project from a bug that sends events in a loop, not to meter normal use. If you expect a launch to exceed the limit, write to support before the day and we raise it.

Trying it by hand

curl -sS https://<collector-host>/health

curl -sS -X POST https://<collector-host>/v1/rum/4f9c2e1b8a7d63e0 \
  -H 'Content-Type: application/json' \
  --data @batch.json

A minimal valid batch.json needs batch_id, sent_at, sdk, app, device, session and at least one event. Events posted by hand appear in the console within a minute, marked with the SDK name you provide.