Authentication
Every call to the sinio.ai API is authenticated with a machine key. A key is not just a password: it carries identity. It resolves the organization, the project, the source, and the scopes the caller is allowed to use — which is why so few fields need to be repeated in each request.
Bearer token
The normal surface. Send the key in the Authorization header:
Authenticated request
curl https://api.sinio.ai/v1/events \
-H "Authorization: Bearer $SINIO_API_KEY" \
-H "Content-Type: application/json" \
-d @batch.json
A missing or malformed header, and a key that is unknown or revoked, both return 401. There is nothing to retry on a 401: the key will not become valid on its own.
Keys are created from your project's settings in the sinio.ai console, one source at a time. The raw key is displayed once, at creation — only a SHA-256 hash is stored, so a lost key is replaced, never recovered.
What a key resolves
- Name
organization- Type
- always
- Description
The organization the key belongs to. Everything the key writes lands under it, and it is what your usage is billed against.
- Name
project- Type
- always
- Description
The project the key is bound to. Every key the console creates belongs to exactly one project, so no request needs to name it.
- Name
source- Type
- always
- Description
The source the key feeds — see Naming the source.
- Name
scopes- Type
- always
- Description
What the key is allowed to do:
ingestfor an API key,ingest:webhookfor a webhook token — see Scopes.
The key already names the project, so a request body never carries one:
Request body
{
"events": [
{
"source_event_id": "evt_88213",
"type": "badge_in",
"occurred_at": "2026-08-28T07:58:12+02:00",
"payload": { "badge": "04A2B9C1" }
}
]
}
Naming the source
A source is one of your tools: your access-control system, your maintenance software, your CRM. Sources are created in the project (during onboarding or in the project settings), and every key belongs to exactly one. Whatever channel uses the key — the API, an SDK or a webhook URL — its data lands in that source, with no header to send.
It matters more than a label. Identifiers are scoped by source: badge 2 in your access-control system and asset 2 in your maintenance tool are two different things, and so are two event types that share a raw code (closed, say). sinio.ai keeps them apart.
Sources are never created on the fly, and archiving a source in the console revokes its keys: from then on they return 401, like any revoked key. To feed a new source, create it in the project settings and create a key for it.
Webhook keys
Some systems can only be pointed at a URL — no custom headers, no auth configuration. For those, a source issues a webhook token, which authenticates in the path:
Token in the URL
curl https://api.sinio.ai/v1/webhooks/$SINIO_WEBHOOK_KEY \
-H "Content-Type: application/json" \
-d @batch.json
A webhook token is not an API key: it opens this URL and nothing else, and an API key does not work in a URL. Like a project key, it belongs to one source, so no header is needed. The body is exactly the one POST /v1/events expects, mode included: this is not a generic receiver that normalises an arbitrary third-party payload.
Test mode
A key created while connecting a tool from the console starts in test mode, for one hour at most. During that time, what it sends is checked exactly like live traffic — same validation, same rejections, same counters — then kept aside for you to review: nothing is derived from it, nothing is billed, and every response carries "test_mode": true.
The test ends when you decide in the console: keep the events, and they are ingested for real, or drop them. Once the test ends — or the hour runs out — the key ingests live traffic like any other, and test_mode is false.
Scopes
- Name
ingest- Type
- scope
- Description
Push events, and upsert entities, locations and assignments, with the key in the
Authorizationheader. This is what an API key is created with.
- Name
ingest:webhook- Type
- scope
- Description
Push events through a webhook URL, and nothing else. This is what a webhook token is created with: it is refused as a Bearer key everywhere.
A call missing the required scope returns 403 with the scope it wanted. Like a 401, it is not retryable: fix the key, not the request.
Keeping keys safe
- Keys are server-side credentials. Never ship one in a browser, a mobile app, or anything a customer can read.
- Store them the way you store database passwords — a secret manager or an environment variable, not your repository.
- Use one key per integration. Revoking a leaked key should not take down four systems at once.
- Rotate by creating the new key, deploying it, and revoking the old one — both are valid in between, so there is no gap.