Privacy and data exposure
This page exists because "share your fleet data with a network" is a sentence that ends most evaluations. Here is exactly what leaves your building and what does not.
Relay stores no trajectories
A road event is a point observation with an expiry. No published event carries a vehicle identifier, a session, a sequence or a path. Nothing in the contract can express "this vehicle then went there".
- A published event carries
lat/lon— a single reference point. - A
geometrydescribes the extent of the hazard (a 40 km queue, a stretch of black ice), never the movement of a vehicle. - Reporter positions on a confirmation (
lat/lonin a signal) are a single point, optional, and never published — they are internal evidence for a future trust weighting.
No published event has a field for a vehicle id, a driver, a plate, a VIN, a device id
or a user. The inbound wire accepts exactly one vehicle-shaped field, and it stops at
our door: reporter_token, your own opaque name for the vehicle that saw or confirmed an
event, which is what the trust quorum counts. It is salted with your organisation id on
arrival; the raw value is never stored, and neither the salted id nor anything derived
from it appears in any API response — only counts are public. See
Trust, and Retention below for what the salted id is
kept on. Adding a published identifier would be an additive wire change and it is not
planned; if it ever happened it would be a documented change to this page, not a quiet
one.
Coordinates are rounded to 5 decimals (~1 m) on write. That is key-space normalisation, not a privacy measure — do not present it as one. The privacy property is the absence of trajectories, not coordinate fuzzing.
Your organisation id never leaves, and neither does a stand-in for it
Published events carry no publisher identity at all:
stored internally org_id = "org_acme"
published on the wire (nothing)There was an intermediate design, and it is worth knowing why it went. publisher_id was
a pseudonym derived from your org_id and stable forever, so consumers could group events
by source. Stable forever is exactly the problem: a pseudonym that never changes is a map
of your fleet's coverage missing only its label, and one publicly known incident of yours
attaches the label. Grouping by it over an 8 km radius gave relative fleet density per
operator, for free, to anyone with a key. It was removed in schema_version 2, before the
first integration, which was the last moment removing a published field was possible.
What this does not fix, stated plainly. Your publishing behaviour is still yours:
cadence, the areas you cover, which event types you emit, how long your geometries run.
Somebody with those events and a data team can cluster them into sources without any
identifier from us. The precise claim is that correlation now costs real work and yields a
hypothesis, where before it was a labelled map served on request. If your client_event_id
values are guessable (1, 2, incident-42), note that event_id is derived from them
and your org_id — use opaque ones and that path closes too.
org_id is in our datastore and our analytics warehouse — the trust model, the signal
keys and contribution metering all need the real identity. It is in no API response.
There is no field, no header, no query parameter, no debug mode that returns it.
What this prevents. GET /v1/events used to hand every consumer a real-time,
machine-readable map of a named telematics editor's fleet coverage — readable by that
editor's direct competitor, at scale, for free. source_kind and feed_id already tell a
consumer what it legitimately needs (a network event versus an ingested public feed); a
nominative id at event granularity delivered something else entirely.
This change was made before the first integration, which was the last moment it was
possible: removing a published field otherwise breaks the additive rule. Nothing of the
kind will happen inside /v1 again.
The three sentences for your legal review
Not a marketing summary. Bring these to counsel exactly as written, because "no identifier" invites the wrong paraphrase into "anonymous".
- No published field identifies your organisation — not
org_id, and, sinceschema_version2, no pseudonym either.publisher_idwas the intermediate design described above, and it is gone. - We can identify you internally, and nobody else on the network can — Datastore and
BigQuery keep the real
org_id, and it is in no API response, header, query parameter or debug mode. - This is correlation friction reduced to zero identifiers, not anonymity —
behavioural fingerprinting and a guessable
client_event_idstill let a third party cluster your events into a source, at the cost described above ("What this does not fix"). Say "no identifier"; never say "anonymous" — that word claims something we do not deliver.
What is public about your events
Everything in the event object is visible to every authenticated consumer. Concretely, a consumer reading an area you publish into learns:
- what kind of hazard, where, when, in which direction, how severe, and your free-text
description; - that it came from a network participant rather than a public feed;
- how many reporters — vehicles, not organisations, since
schema_version2 — have confirmed or denied it.
It does not learn your name, your org_id, your client_event_id, how many vehicles you
run, where else you are publishing at that moment, or anything about a vehicle.
description is free text you control. It is published verbatim, capped at 280
characters. Do not put an internal reference, a driver name, a plate or a customer
identifier in it — nothing strips them, and the field is not the place for data you did not
mean to publish.
Attribution, if you want it
A partner who wants the credit — "powered by X" — is a real and good case. It comes back later as an additive, opt-in field, never as a reversal of the no-publisher-identity decision above.
It needs a claimed, unique, moderated namespace, which means a registry; the field does not exist on the wire, and it arrives as a designed addition, never a side effect. A publisher-chosen public handle was rejected outright: an organisation that can set the string consumers read as who published this can set it to a competitor's name, which plants an impersonation vector in the one layer whose entire job is anti-poisoning.
Retention
- Operational store — the live event set. Events are deleted after expiry; physical cleanup is best-effort and typically completes within 24 hours of the TTL. Expired events stop being served immediately regardless.
- Analytics — one row per event state change, and one row per confirmation or denial,
are mirrored to a warehouse, both keyed on the real
org_idof the organisation that acted, and retained. A signal row also carries the salted reporter id — never the rawreporter_token— with the action, the reporter's optional position and the timestamp: it is the record that lets a minted fleet be told apart from a real one. Neither table is ever on the read path or exposed by any API route. They exist for contribution metering — publishing and confirming both count. - API keys — stored as a SHA-256 hash. The plaintext is never persisted anywhere.
- Stream tickets — one row with an expiry, physically cleaned up on the same best-effort TTL.
There is no data-deletion API in v1. Events age out on their own; anything else is an operator action.
For your compliance review
- DPAs, retention commitments and certifications are handled per agreement. Raise them in the contract conversation rather than inferring them from this page.
- The wire has no publication-history query. The Console gives each organisation an append-only audit log of its own account actions — key issuance, revocations, membership changes, named by actor. The wire itself is not covered: what you published is retained on our side (see Retention above) and is not queryable back through any API.