Cudatus Relay
Relay is one HTTP API where any mobility actor publishes road events and any mobility actor consumes them. A fleet reports an accident; a carmaker's head unit hears about it under a second later. Same contract in both directions, same JSON, no per-partner integration.
It is infrastructure, not an application. There is no map, no routing, no navigation. You send events, you read events, you subscribe to a live stream of events.
The whole API
This is the complete surface. There is nothing else.
| Method | Path | What it does | Key? |
|---|---|---|---|
POST | /v1/events | Publish a road event | yes |
GET | /v1/events | Active events around a point | yes |
GET | /v1/events/{event_id} | One event by id | yes |
POST | /v1/events/{event_id}/signals | Confirm or deny an event | yes |
GET | /v1/stream | Live SSE feed for an area | yes |
POST | /v1/stream/tickets | Mint a browser stream credential | yes |
GET | /v1/meta/event-types | The live event-type vocabulary | no |
GET | /v1/meta/taxonomy | The two-level vocabulary, with each type's lifetime | no |
GET | /v1/meta/limits | Hard query limits | no |
GET | /health | Liveness | no |
GET | /, /docs, /openapi.json | Banner, Swagger UI, generated schema | no |
Reads are authenticated, not just writes. Consuming is the metered side of the business model, and authentication cannot be added to a public endpoint after partners have pinned integrations to it — so it is there from day one.
Base URL
The production host is https://api.cudatus.com. Issue a key from the
Console and point at it:
export RELAY=https://api.cudatus.com
export RELAY_KEY=<your key>Every example on these pages uses those two shell variables, so nothing here is tied to
one host. https://api.cudatus.com is where a partner starts; a contributor stack exists
for working on Relay itself — see
Getting started.
Four things that define the product
Events are ephemeral, and that is the point. Every event carries an expires_at.
Relay serves what is live now; it is not a history database. A
wrong_way_vehicle lives 20 minutes by default, an accident two hours.
Confirmations from other vehicles extend an event's life — with one deliberate exception,
and it is the type just named: see Trust.
Publishing is cheap, consuming is the product. There is no friction on the publish path — one POST, no negotiation, no schema registration. Consuming is where the value and the bill are.
Trust is a quorum, in both directions. Your event lands unverified and stays there
until enough other vehicles confirm it. The publishing vehicle is excluded from its own
evidence; your own fleet corroborating counts — the quorum counts reporters, not
organisations. Clearing an event is never cheaper than promoting one. See
Trust — this is the single thing publishers most often mistake for a bug.
The wire contract is forever. Fields are added, never renamed, re-typed or removed. A carmaker that integrates once ships that integration into vehicles that stay on the road for fifteen years. See Compatibility for the two obligations that places on your client.
Contract boundaries
These are properties of the contract, not omissions from it:
- No fleet simulator, by design — and your sandbox is not empty. A sandbox key reads the live network too, so you develop against real national traffic from the first request; the traffic you control is a twenty-line publish loop you own, not a product component. See The sandbox.
- No SDKs, by design. The API is REST + SSE against any HTTP library, and the docs carry complete copy-pasteable clients — nothing between your code and the wire to version or fall behind. See Streaming.
- Subscriptions are discs. An area query or subscription is a disc capped at 9 780 m; a route is covered by tiling discs along it — see Consuming.
- Each report is its own event. Two organisations reporting the same accident produce
two events.
mergedandmerged_intoare reserved in the contract for cross-report merging and arenullon every event. - Events are immutable observations. A publisher does not delete or update its own event. It expires.
- One rate limit, metered consumption. Every read, publish, signal and stream connect
is counted per organisation, per environment, per day; plan allowances are settled
commercially rather than enforced by refusal. The one
429in the API is the hourly per-organisation ceiling on signals, a guard on the trust model rather than a quota. Do not build on the absence of a limit — see Errors and limits. - No
Last-Event-IDor replay log on the stream, deliberately. Reconnecting gets a fresh snapshot instead. - No roadworks. Planned works are known weeks ahead and are out of this contract.
Where to go next
| You want to | Read |
|---|---|
| Get a key and see a real event | Getting started |
| Understand the two credential types | Authentication |
| Send your first event correctly | Publishing |
| Poll an area | Consuming |
| Subscribe to the live feed | Streaming |
| Test without a fleet | The sandbox |
Know why your event says unverified | Trust |
| Look up a field | The event object |
| Every change to the wire contract, the vocabulary and the platform, dated | Changelog |