This article explains what each API endpoint is for and what to keep in mind when using it.
For the exact request and response formats, with examples, use the full reference in the app: Settings → Integrations → Documentation.
Before you start
Every call to the API follows the same rules:
Base URL:
https://api.ezuspay.app/v1Authentication: send your API key in the
x-api-keyheader of every request. See Create and manage API keys.Permissions: each endpoint requires a permission, listed below. A key without it gets a
SCOPE_INSUFFICIENTerror.Format: requests and responses are JSON.
Amounts are in cents, as integers:
150000means €1,500.00.IDs are Ezus Pay IDs. When an endpoint expects a booking or a payment link ID, it's the
idreturned by Ezus Pay, not the Ezus project ID.Rate limits, per key: 600 read requests and 60 write requests per minute. Above that, the API answers
RATE_LIMIT_EXCEEDED: wait a few seconds and retry.
At a glance
Endpoint | What it does | Permission |
| Test your API key | — |
| Create a booking | Bookings (write) |
| Refresh a booking from Ezus | Bookings (write) |
| Create a payment link | Payment links (write) |
| List a booking's payment links | Payment links (read) |
| Get a payment link | Payment links (read) |
| List your agency's payments | Transactions (read) |
| List a booking's payments | Transactions (read) |
| List a payment link's payments | Transactions (read) |
| Get a payment | Transactions (read) |
| Refund a payment | Refunds (write) |
Test your key
GET /ping
The first call to make. It confirms the key works, tells you which agency it belongs to, and lists its permissions. No permission required.
Bookings
POST /bookings: create a booking
Creates a booking in Ezus Pay, typically to import a trip from another system before collecting payments on it.
From an Ezus project: send the project name and its Ezus project ID. Ezus Pay fetches everything else from Ezus (client, options, dates, amounts).
From another system: send the client and the trip details yourself.
No duplicates: calling it twice with the same Ezus project ID returns the booking that already exists instead of creating a second one. You can safely retry.
POST /bookings/:id/resync: refresh a booking from Ezus
Fetches the Ezus project again and updates the booking: amounts, dates, travelers, client, options. Only for bookings imported from Ezus, with the Ezus connection active.
Good to know: if an option was removed in Ezus, Ezus Pay keeps it and flags it as orphan. It is never deleted, so its payment links and payment history stay intact.
Payment links
POST /bookings/:id/payment-links: create a payment link
Creates a payment link and returns its checkoutUrl, the page you send to your traveler.
Only the amount is required. You can also set a label (e.g. Deposit 30%), the payment methods allowed (card by default), an expiry date, and whether the link can be paid several times.
The currency is always the booking's currency.
By default, the link is attached to the booking's main option. You can target another option.
GET /bookings/:id/payment-links: list a booking's payment links
Every link of the booking, across all its options, with its status and checkout URL.
GET /payment-links/:id: get a payment link
One link, with its amount, status, the amount already collected, and its checkout URL.
Transactions
A transaction is one payment: one card payment, one SEPA debit, or one payment you recorded by hand.
GET /transactions, GET /bookings/:id/transactions, GET /payment-links/:id/transactions: list payments
The same list at three levels: your whole agency, one booking, or one payment link. Results are paginated (up to 100 per page) and can be filtered by:
status: pending, succeeded, failed, refunded, partially refunded
source: collected through Ezus Pay, recorded manually, or imported from Ezus
date range, on the payment date
Two things are worth knowing:
The payer isn't always the client.
payerNameis the person who paid, while the booking's client is the traveler the trip is for. They often differ: co-travelers splitting a deposit, a company paying for an employee.refundableAmountCentsis exactly what you can refund right now. It already accounts for refunds in progress.
GET /transactions/:id: get a payment
Everything about one payment, plus its refund history and the traveler's answers to your checkout fields (phone, address, passport number…). This is the only place in the API where those answers are available.
Refunds
POST /transactions/:id/refunds: refund a payment
Refunds all or part of a payment. The money goes back to the traveler's original payment method.
Amount: leave it out to refund everything that remains refundable, or set a partial amount.
Reason and note are optional, and kept for your records.
It's asynchronous. A success response means the refund was accepted, not that the money has already moved. A SEPA refund can take several days. To follow it, listen to the
payment.refundedwebhook rather than calling again.Only payments collected through Ezus Pay can be refunded. A payment you recorded by hand never went through Ezus Pay, so there is nothing to send back.
Keys created before refunds were available don't have the Refunds (write) permission. Create a new key to use this endpoint.
⚠️ Refunds move money out of your account. Only give the Refunds (write) permission to tools that really need it.
How the IDs fit together
Most integrations follow the same chain. Each step gives you the ID the next one needs:
Create a booking → you get the booking ID.
Create a payment link on that booking → you get the payment link ID and the checkout URL to send.
The traveler pays → the payment shows up in the transaction lists, with its transaction ID. The
payment.succeededwebhook also sends it to you as soon as it happens.Refund that payment using its transaction ID.
When something goes wrong
Every error comes back as JSON with a machine-readable code:
HTTP | Code | Meaning |
401 |
| Problem with the key. See Create and manage API keys |
403 |
| The key lacks the permission for this endpoint |
404 |
| The booking, link or transaction doesn't exist, or belongs to another agency |
422 |
| Something in the request is missing or invalid. The response lists which fields |
429 |
| Too many requests. Wait a few seconds and retry |

