Skip to main content

Developers

Network API

Sell transfers across the network without contracting operator by operator. Sign up, test with your key this afternoon and go live after a review.

Integrate in a day

Everything you need to test comes with the sign-up. Nobody has to give you access to the test key.

  1. Sign up in the portal. You get a tmc_test_ key on the spot: keep it, it is only shown once.
  2. Quote and book with it. No real fleet is involved, nothing is charged and nobody is notified.
  3. Add your webhook URL in the portal and keep the secret, shown only once.
  4. Play the scenarios and check your system receives each event.
  5. Your account waits for review. A person approves it and issues your production key.
Create a partner account
curl https://api.transfersmanager.ai/api/v1/channel-api/me \
  -H "X-API-Key: tmc_test_..."

curl -X POST https://api.transfersmanager.ai/api/v1/channel-api/quotes \
  -H "X-API-Key: tmc_test_..." -H "Content-Type: application/json" \
  -d '{"origin_lat":36.68,"origin_lng":-4.49,"destination_lat":36.51,"destination_lng":-4.88,
       "pickup_datetime":"2027-03-14T10:30:00+01:00","passengers":2}'

With a production key, a booking returns a payment link and enters the network once paid. Quotes only exist where verified fleets offer real supply: check /coverage first. Where there is none, /quotes answers 503 no_operators.

Endpoints

Base: /api/v1/channel-api. Authenticate with the X-API-Key header or Authorization: Bearer. A reference that is not yours answers 404, like one that does not exist.

GET /me
Who this key is and whether it is a test key.
GET /coverage
Where there is real supply: approximate zones, or the exact answer for a point with lat and lng. It names no fleet.
POST /quotes
Price with net, commission and total. A quote lives five minutes and books once.
POST /bookings
Idempotent booking by external_ref. Repeating it returns the same booking.
GET /bookings/{ref}
One booking by external_ref or booking_id.
POST /bookings/{ref}/cancel
Cancel. Unpaid, it closes the link. Paid, it refunds by the operator's cancellation ladder.
GET /bookings/{ref}/voucher
Booking data for your own voucher. There is no pass or PDF: those documents name the operator.
GET /flights/{number}?date=YYYY-MM-DD
A flight by number and date. 404 flight_not_found when it does not exist and 503 flight_status_unavailable with Retry-After when it cannot be told.
POST /pickup-suggestion
When to book the pickup for a flight. It books nothing and holds no price.
POST /test/bookings/{ref}/scenario
Test keys only: play a scenario.
GET /test/bookings/{ref}/events
Test keys only: what happened to a test booking.

Test keys

A tmc_test_ key answers the same contract from an isolated world: the booking is not a real service and no fleet sees it. The price is a straight-line estimate, flagged is_approximate. The booking is confirmed at once with no payment link. Flights and pickups are invented. driver_assigned first; then the rest.

driver_assigned
A driver is assigned.
driver_delayed
A delay notice, with delay_minutes. It only exists in the test world: production does not emit this event today.
driver_position
An invented car position.
no_show
The driver arrives and the passenger does not show up.
completed
The service runs to the end.
curl -X POST https://api.transfersmanager.ai/api/v1/channel-api/test/bookings/my-ref-1/scenario \
  -H "X-API-Key: tmc_test_..." -H "Content-Type: application/json" \
  -d '{"scenario":"driver_assigned"}'

Webhooks

One URL per account, set in the portal. Each delivery is signed with your secret, as in the Partner API, and test keys receive them too.

  • Verify the signature over the raw body, before parsing the JSON.
  • Retries back off from 30 seconds up to one hour, 12 attempts in all. While an attempt fails, your account's next events are held for that pass.
  • The portal shows your last 50 events and can resend any of them. The delivery id is kept so you can spot duplicates. They are stored for 30 days.
  • Live position: booking.driver_position is optional and off by default. Switch it on in the portal. It is only sent with the car on its way, at the pickup or with the passenger on board, at most every 30 seconds, and it carries only booking ids and coordinates. A position is never retried or resent. A receiver that fails or takes 1.5 seconds or more is paused for 5 minutes.
import crypto from 'node:crypto';

// rawBody: the request body as a string or Buffer, BEFORE JSON.parse.
export function verifyTmSignature(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // older than 5 minutes

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex');

  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1 ?? '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Rules

  • Minimum notice: checked at quote and at booking, with the autonomous community of the pickup coordinates. If it cannot be told, or the address contradicts them, the strictest minimum applies. It answers 422 lead_time_too_short with the figure and its legal basis. Test keys always apply the strictest.
  • An immediate booking (immediate: true) needs a pickup within 24 hours and, with no agreed fleet, at least 60 minutes ahead.
  • The contract does not disclose the fleet: not in quotes, not in coverage, not in the voucher.
{
  "detail": {
    "error": "lead_time_too_short",
    "message": "Pickups in Cataluña must be booked at least 15 minutes ahead.",
    "minimum_minutes": 15,
    "community": "ES-CT",
    "community_name": "Cataluña",
    "legal_basis": "Decreto-ley 9/2022, ..."
  }
}

Limits

Requests
120 per minute per key by default; 429 beyond it. Test keys share one limit per account.
Test keys
3 active per account.
Test bookings
1,000 per account and 50 events per booking.
Sign-ups
5 a day per IP.
Quote
Lives 5 minutes.
/coverage
Up to 1,500 zones of 0.5 degrees; cacheable for 5 minutes.
Webhook
5 seconds per delivery; 3 for a position.

Resources

Working with a single operator?

See the Partner API

The newsletter for operators

Blog articles, analysis of the transfer and VTC market, regulation (RVTC, Verifactu) and product news. No filler, one-click unsubscribe.