API reference
The Events API accepts events from your product, one per request. An ingest key sends events and never reads data back; reading from your own code uses a key with the role analyst.
Overview
| Setting | Value |
|---|---|
| Base URL | https://api.tuumo.fi |
| Endpoint | POST /v1/events, one event per request |
| Format | JSON over HTTPS, UTF-8 |
| Version | In the path: /v1 |
| Body limit | 256 KiB |
Authentication
Send your API key as a bearer token on every request. Create keys under API keys, one per app or environment. A key looks like tm_ followed by 43 characters, and the app shows it once.
Authorization: Bearer $TUUMO_KEY
A key sends events when its role is ingest (or admin), and a key belongs to one product: its events are filed under that product. A key with any other role, an unknown key, a missing or malformed header, a revoked or expired key and a key of an archived product all get the same answer, 401. A revoked key stops working within a minute; events already received are kept.
A client application that sends events embeds an ingest key only: it cannot read data back.
Send an event
POST /v1/events accepts one event per request and answers 202 Accepted with the id of the event. The body is a JSON object:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Event name, 1 to 128 characters, no control characters. Use object_action in snake_case, for example signup_completed. |
timestamp |
string | No | When the event happened: RFC 3339 with an offset, for example 2026-10-21T09:15:02Z. Without it, the time Tuumo received the request. |
user_id |
string | No | The person the event belongs to, the same id on every platform. |
session_id |
string | No | Id of the session the event belongs to. Events with the same id are grouped together. Optional, and recommended. |
properties |
object | No | Any JSON object with the detail of the event. Arrays, strings, numbers and booleans are refused. Without it, {}. |
A field sent as null counts as absent, except name. A field that is not in the table, a repeated field, invalid JSON and an empty body are 400.
curl https://api.tuumo.fi/v1/events \
-H "Authorization: Bearer $TUUMO_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "report_exported", "timestamp": "2026-10-21T09:15:02Z", "user_id": "u_1842", "session_id": "s_8f2c41", "properties": {"format": "csv", "duration_ms": 412}}'
Response
{ "event_id": "0192f3a0-7c1e-7b2a-8d4e-5f6a7b8c9d0e" }
202 means Tuumo has the event; it appears in queries a short while later. Tuumo does not remove duplicates: if you send a request again because you never saw its answer, the event is stored twice, each with its own event_id.
Errors
Every error answer is JSON, {"error": "<code>", "detail": "…"}; detail is there for a 400 and says what is wrong.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_event |
The body is not valid JSON, a field has the wrong type or a required field is missing | Fix the event; do not retry as is |
| 401 | unauthorized |
The key is missing, malformed, revoked, expired or not allowed to send events | Check the key and its role under API keys |
| 402 | quota_exceeded |
The workspace has used its monthly event quota; the event was not stored | Stop sending until the month turns (UTC) or the quota grows; do not retry in a loop. There is no Retry-After |
| 408 | request_timeout |
The request did not arrive in time | Retry |
| 413 | payload_too_large |
The body is over 256 KiB | Send a smaller event; do not retry as is |
| 429 | overloaded |
Too many events are being received; slow down | Wait for Retry-After seconds, with some jitter, then retry |
| 503 | no_writers |
Tuumo cannot store events right now | Wait for Retry-After seconds, with backoff, then retry |
Any other path is 404 and any other method on /v1/events is 405. See Plans and billing for the monthly event quota.
Reading data
Most reading happens in an AI tool through the Tuumo MCP server, see Connect AI tools. To query from your own code, for example for a dashboard, create a key with the role analyst under API keys and send it as a bearer token to the MCP server:
https://mcp.tuumo.fi/mcp
An analyst key can read and query data but cannot send events. Keep it, and any admin key, on your server; never ship it in a client application. Its queries use the query credits and the plan of the member who created the key.