Changelog
API and webhook changes by date. Backwards-compatible by default — breaking changes get a version bump.
The Tourical API follows a few rules around change:
- We never rename a field, scope, event type, or webhook header once shipped. Deprecated names continue to work through at least one major release window.
- Additive changes (new field, new endpoint, new event type) ship without a version bump. Verifiers must ignore unknown fields.
- Breaking changes ship under a new path version (
/v2/) and run in parallel with the previous version for at least six months. - Every change shows up here. If something visibly changes and we forgot to log it, that's a bug — write to us.
Deprecation and sunset policy
When an endpoint, field, or event is deprecated:
- It is marked deprecated here and in
/openapi.json(deprecated: true) on the day the replacement ships. - Responses from a deprecated route carry
Deprecation: true, aSunsetheader with the removal date (RFC 8594), and aLink: <…>; rel="successor-version"header pointing at the replacement. - The sunset date is at least six months after the deprecation notice for
/v1/*. - We measure traffic to deprecated routes and contact integrators who are still calling them before the sunset date.
Currently deprecated:
| Route | Replacement | Sunset |
|---|---|---|
/client/quotes/*, /client/bookings/* (legacy recipient pages) | /dossier/*, /dossier/bookings/* | 2026-10-31 |
/api/client/quotes/*, /api/client/bookings/* | /api/dossier/*, /api/dossier/bookings/* | 2026-10-31 |
These legacy recipient routes were never part of the /v1/* contract; they answer with a redirect plus the headers above until the sunset date, then 404.
2026-09-05 — v1.1: contracts, delivery inspection, idempotency
Endpoints
GET /v1/me— token introspection.POST /v1/webhooks/{id}/rotate-key— signing-key rotation with a 24h dual-key overlap.GET /v1/webhooks/{id}/deliveries— delivery history, cursor-paginated, filter by status.POST /v1/webhooks/{id}/deliveries/{deliveryId}/redeliver— queue a fresh delivery of the same event (sameTourical-Event-Id).GET /v1/openapi.json— the OpenAPI 3.1 document, generated from the runtime; a contract test keeps the two in step.
Webhooks
- Every event in the catalog now has an emitter.
booking.cancelled,booking.refunded,dispute.closed,trip.published,trip.unpublishedandclient.created(from the dashboard, the API, checkout, and date requests) fire in production. - Payloads are validated against the published JSON Schema at emit time; the examples in the event catalog are generated from the same schema.
- New headers on every delivery:
Tourical-Request-Id(<deliveryId>.<attempt>) andTourical-Delivery-Attempt. - Retry cascade starts at 1 minute (6 attempts total) as documented; the first retry had previously waited 5 minutes.
- Auto-pause keeps queued deliveries in
pending(nothing is dead-lettered by a pause) and notifies the tenant's owners/admins. POST /v1/webhooks/testno longer requireswebhook.testin a subscription'seventslist and no longer modifies the subscription;subscriptionIdoutside your tenant returns404.- Deleting a subscription in the dashboard is now a soft delete, like the API: delivery history is kept.
Idempotency
Idempotency-Keyis honoured on every/v1/*write; 24h window, tenant-scoped,409on body mismatch or in-flight replay. 5xx responses are never cached.
Rate limits
- The pre-authentication per-IP guard is now 2,000 requests/minute (was 120) and answers
429withX-RateLimit-Scope: ip. Per-token quotas are unchanged.
Removed
- Two never-documented internal routes (
/api/exchange-rates,/api/ratehawk/search) were deleted. They were not part of/v1/*.
2026-05-26 — v1 public launch
Initial public release of the v1 API and webhook system.
Endpoints
GET / POST / PATCH /v1/tripsGET /v1/bookings,POST /v1/bookings(501 — checkout via storefront)GET / POST /v1/clientsGET /v1/paymentsGET /v1/libraries/{hotels,activities,vehicles,guides}GET / POST / DELETE /v1/webhooks,POST /v1/webhooks/test
Webhook events
booking.confirmed, booking.cancelled, booking.refunded, payment.succeeded, payment.failed, dispute.opened, dispute.closed, trip.published, trip.unpublished, client.created, webhook.test.
Auth
Bearer tokens, format tk_<live|test>_<26 chars>. Ten scopes covering reads and writes per resource.
Rate limits
60 req/sec burst, 600 req/min sustained, per token.
Roadmap
These are planned but not yet shipped. Subscribe to the changelog (or watch this page) — we won't surprise-ship anything that breaks an integrator.
- Postman collection and generated client SDKs for Node and Python, built from
/openapi.json. POST /v1/bookings(today501; checkout runs through the storefront).

