REST API overview
The TOVR REST API is a narrow, OAuth2-authenticated surface over tovr.eu/api/v1: ingest and read shipments, read chains, vehicles, matches, quotes and outreach, follow what changes, price lanes, and authenticate.
The TOVR REST API lets external systems push freight into TOVR and read it back. It is
deliberately narrow: mostly reads, versioned under /api/v1. Shared conventions (bearer
format, error envelope, rate limits, versioning) are in API conventions.
Base URL
| Environment | Base URL |
|---|---|
| Production | https://tovr.eu/api/v1 |
| Staging | https://staging.tovr.eu/api/v1 |
Authentication
Every endpoint (except the token endpoint itself) requires a bearer token obtained via the OAuth 2.0 client-credentials flow:
- Create a client application in the dashboard to get a
client_idandclient_secret. - Exchange them for an access token at the token endpoint
(
expires_inis 3,600 seconds, one hour). - Send
Authorization: Bearer <token>on each request.
The platform validates the token and injects your organization and client context — so request bodies never carry an org identifier; it is inferred from the token.
Resources
This is every endpoint under /api/v1. Every endpoint other than the token endpoint
requires the scope shown; a client application is granted scopes when it is created.
| Resource | Endpoints | Scope |
|---|---|---|
| Shipments | GET /shipments · GET /shipments/{id} | shipments:read |
POST /shipments · PATCH /shipments/{id} | shipments:write | |
| Invoices | GET /invoices · GET /invoices/{id} | invoices:read |
| Freight chains | GET /chains · GET /chains/{id} | chains:read |
| Vehicles | GET /vehicles · GET /vehicles/{id} · GET /vehicles/{id}/availabilities | vehicles:read |
| Matches | GET /matches · GET /matches/{id} | matches:read |
| Quotes (carrier bids) | GET /quotes · GET /quotes/{id} | quotes:read |
| Outreach timeline | GET /outreach · GET /outreach/{id} | outreach:read |
| Change feed | GET /events | events:read |
GET /events/stream (server-sent events) | events:stream | |
| Webhooks | GET /webhook_endpoints · GET /webhook_endpoints/{id} | webhooks:read |
POST /webhook_endpoints · PATCH/DELETE /webhook_endpoints/{id} · POST /webhook_endpoints/{id}/rotate_secret | webhooks:write | |
| Pricing | POST /estimate · POST /estimate/batch | estimate |
| Market | GET /market/overview | market |
| Token | POST /oauth2/token | none |
Everything except shipments and webhook endpoints is read-only: there is no API to create or change a chain, vehicle, match, quote or outreach entry. A few notes on what the read-only resources return:
- Vehicles lists your own fleet plus trucks published on the exchange;
ownershipon each row says which./availabilitiesis a live contract that currently returns an empty list, because no connected telematics provider reports availability windows yet. - Matches and quotes are visible to both sides.
own_side(matches) andown_role(quotes) say which side you are. A match carries shipment ids, not freight; fetch the freight throughGET /shipments/{id}. - Chains in a list omit
shipment_idsandstops(they arenull). Fetch one chain by id to get them. - Outreach is the timeline of interactions (when, which channel, which direction, what
kind). It does not include message content or names.
?chain_id=narrows it to one chain. - Invoices are records of invoices your ERP issued, not invoices TOVR issues — no PDF, no due
date, no payment state.
invoices:readis deliberately separate fromshipments:read, so an organization can let a factoring integration read what it billed without handing over the whole shipment book.
Client applications are created and rotated in the TOVR dashboard, under
Settings → Developer, not over the API. The /oauth2/client_applications
endpoints that used to be documented here were authenticated by a browser session
rather than by a bearer token — so they were never callable by an API client in
the first place — and they scoped by creator rather than by organization, which
is not what this page claimed.
There are no carrier or shipper directory endpoints. The table above is the whole API.
The pricing and market endpoints changed on 2026-08-25. They used to run on an older
request path with their own error bodies and, because rate limiting lives on the shared path,
with no rate limit or monthly quota at all. They now behave like every other endpoint: the
shared error envelope, X-Request-Id on every response, the
RateLimit-* headers, and an entry in the generated OpenAPI document.
This is a breaking change to the errors — validation failures moved from 400 to 422,
scope denials changed body shape, and 429/402 are newly reachable. Every 2xx body is
unchanged. Read
2026-08-25-apex-pricing-and-market-routes
before upgrading a client.
They still do not honour Idempotency-Key: all three are reads that write nothing, so a key
on one would be a cache with no invalidation.
Staying in sync
GET /shipments answers what is true now. To keep a mirror current without re-reading the whole
book, use the change feed — poll GET /events with a cursor, or receive
the same events as webhooks. Both carry an id and a type rather than a
row, so there is exactly one place that decides what your organization may read.
Data model
A shipment payload is a nested tree — stops, cargo, costs, identifiers. Its shape is described in the domain-model reference; what the entities mean is in TOVR › Concepts › Domain model.
/loads has been removed. It was an API-only second model of the same freight: nothing in the
product read it, and everything it expressed is already expressible as cargo on the shipment. Send
line items as cargo.items[] on POST /shipments instead. Consignment splitting, if you need it,
arrives additively on that same array rather than as a separate resource.
Reference
The TOVR platform's technical reference — the public REST API (shipments you can write, read-only chains, vehicles, matches, quotes and outreach, the change feed and webhooks, pricing and market analytics), the domain-model field tables, and the external integrations TOVR connects to.
Authentication
The TOVR REST API uses the OAuth 2.0 client-credentials flow. Exchange a client_id and client_secret at the token endpoint for a one-hour bearer token, then send it as an Authorization header on every request.