Ingestion API overview
Last updated
The Whisperr ingestion API takes your product events, user identities and consent records, and answers data requests about a user. Use this page when you call the API directly. If an SDK exists for your stack, use the SDK: it does the batching, retries and idempotency for you.
Base URL
Section titled “Base URL”https://api.whisperr.netAll paths on this page start with /v1/.
Endpoints
Section titled “Endpoints”| Endpoint | Key | Purpose |
|---|---|---|
POST /v1/events/batch | publishable or server | Send up to 500 events. See Track events. |
POST /v1/events/track | publishable or server | Send one event. See Track events. |
POST /v1/identify | publishable or server | Set a user’s traits and contact channels. See Identify users. |
POST /v1/consent/assertions | server only | Record proof of a consent choice. See Contact consent. |
GET /v1/users/{external_id}/export | server only | Export everything Whisperr stores about a user. See Export and erase a user. |
DELETE /v1/users/{external_id} | server only | Erase a user. See Export and erase a user. |
Use /v1/events/batch for anything that sends more than one event. All SDKs
use it. /v1/events/track is for one-off calls such as scripts and webhooks.
Which API key do I use?
Section titled “Which API key do I use?”Whisperr has two kinds of ingestion key. Create them in the dashboard under Settings → API keys. Every workspace can create keys, also before the trial starts.
| Dashboard label | Prefix | Where it runs | What it can do |
|---|---|---|---|
| App | wpk_… | Apps and browsers | Send events and identify calls. It ships inside your app, so anyone can read it. |
| Server | wrk_… | Your backend only | Everything the app key can do. It can also always opt a contact in, change a user’s existing email address, record consent proof, and export or erase a user. |
Keep the server key in your backend’s secrets. Never put it in client code. See Contact consent for when the app key can opt a contact in, and what only the server key can do. See API keys to create, replace or revoke a key.
How do I authenticate a request?
Section titled “How do I authenticate a request?”Send the key in one of these two headers. Both work on every endpoint.
X-API-Key: wrk_your_server_keyAuthorization: Bearer wrk_your_server_keyA request without a key gets 401 missing_api_key. A wrong or revoked key
gets 401 invalid_api_key.
Send a first event
Section titled “Send a first event”Put your server key in an environment variable, then send one event. The
occurred_at and $message_id values are generated by the shell, so you can
run the command more than once.
export WHISPERR_SERVER_KEY=wrk_your_server_key
curl https://api.whisperr.net/v1/events/track \ -H "X-API-Key: $WHISPERR_SERVER_KEY" \ -H "Content-Type: application/json" \ -d @- <<EOF{ "external_user_id": "user_8842", "event_type": "payment_failed", "occurred_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", "properties": { "amount_cents": 4900 }, "context": { "\$message_id": "$(uuidgen)" }}EOFThe answer is 202 Accepted:
{ "event": { "mapping_status": "pending" }, "processing": "queued" }202 means Whisperr stored the request. It processes the event right after.
See Accepted, then processed.
Can I call the API from a browser?
Section titled “Can I call the API from a browser?”Yes, for the three ingestion endpoints. POST /v1/events/batch,
POST /v1/events/track and POST /v1/identify allow cross-origin requests
from any origin, with the publishable key. The consent, export and erase
endpoints need the server key and do not allow cross-origin requests.
How strict is validation?
Section titled “How strict is validation?”The Whisperr API rejects unknown fields. A misspelled field name fails with
400 instead of being ignored. This keeps every SDK on the same contract.
In a batch, only the event with the problem is rejected. See
Response handling.
What are the size limits?
Section titled “What are the size limits?”| Limit | Value |
|---|---|
Body of POST /v1/events/track or POST /v1/identify | 1 MiB |
Body of POST /v1/events/batch | 10 MiB |
| Events per batch | 1 to 500 |
properties of one event, as JSON | 50 KB |
traits of one identify, as JSON | 50 KB |
channels per identify or event | 10 |
anonymous_id | 1 to 128 printable characters |
$message_id | 200 bytes. A longer value is ignored, so the event is not deduplicated. |
A body over its limit gets 413 payload_too_large.
What are the rate limits?
Section titled “What are the rate limits?”Whisperr counts requests per API key in fixed one-minute windows. Every counted response carries these headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests this key may make in one window. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | End of the current window, in Unix seconds. |
Over the limit, the answer is 429 rate_limited with a Retry-After header in
seconds. Wait that long, then retry. All browsers of one app share the
publishable key, so they share its budget.
What does an error look like?
Section titled “What does an error look like?”Every error from the Whisperr API has the same JSON shape:
{ "error": { "code": "invalid_request", "message": "event_type must be snake_case", "request_id": "8d2f6a0c1b3e4f5a" }}Match on code. message is for people and can change.
| Status | code | Meaning |
|---|---|---|
400 | invalid_json | The body is not one JSON object, or it has an unknown field. |
400 | invalid_request | A field failed validation. message names it. |
401 | missing_api_key | No key in X-API-Key or Authorization. |
401 | invalid_api_key | The key is wrong or revoked. |
403 | server_key_required | Export and erase need the server key. |
404 | user_not_found | Export found no user with this id. |
404 | route_not_implemented | The path does not exist. |
413 | payload_too_large | The body is over its size limit. |
429 | rate_limited | The key is over its rate limit. |
500 | internal_error | A fault on the Whisperr side. Retry. |
502, 504 | upstream_unavailable | The Whisperr API did not answer. Retry. |
POST /v1/consent/assertions uses a shorter error body. See
Contact consent.
Every response carries an X-Request-Id header with the same value as
error.request_id. To use your own id, send an X-Request-ID header.
Common questions
Can I call the Whisperr ingestion API from a browser?
Yes, for POST /v1/events/batch, POST /v1/events/track and POST /v1/identify with the publishable key (wpk_…). These three endpoints allow cross-origin requests from any origin. The other endpoints need the server key and do not answer browser preflight requests.
Does the Whisperr API need a Content-Type header?
The ingestion endpoints read the body as JSON whatever the Content-Type is. Send Content-Type: application/json anyway, as every Whisperr SDK does.
What happens when I send a field the Whisperr API does not know?
The request fails with 400 invalid_json. Whisperr rejects unknown fields so that a misspelled field name is never silently ignored. In a batch, only the event with the unknown field is rejected.
How do I trace a failed request with Whisperr support?
Every response carries an X-Request-Id header, and every error body carries the same value as error.request_id. Quote it when you report a problem.