Checking payment status
GET /payments/{paymentId} returns the current state of a payment. It is the authoritative answer to
“was I paid?”, and the thing to call when a payer lands on your
callback URL.
No token required
Section titled “No token required”This endpoint takes no credential. There is no Authorization header and no company scoping: the payment
id is the whole of the lookup. Anyone holding a payment id can read that payment, so keep ids out of URLs
you publish, emails you forward and logs you ship to third parties.
Request
Section titled “Request”GET /payments/pay_4KdR8s2Xn1QwZ7 HTTP/1.1Host: pay-api.paydot.euResponse
Section titled “Response”{ "companyId": "acme", "paymentId": "pay_4KdR8s2Xn1QwZ7", "amountCents": 2599, "currency": "EUR", "reference": "ORDER 1042", "status": "EXECUTED", "createdAt": 1787086549556, "updatedAt": 1787086901233, "merchantReturn": true}| Field | Meaning |
|---|---|
companyId | Your company id. |
paymentId | The Paydot payment id, the same value you received on your callback URL. |
amountCents | The amount in minor units, and the amount actually paid. |
currency | ISO 4217 currency code. |
reference | The reference shown to the payer. |
status | One of the eight values below. |
createdAt | When the payment was created, epoch milliseconds. |
updatedAt | When the status last changed, epoch milliseconds. Absent until the status changes for the first time. |
merchantReturn | true when the payment came from a link you generated, which is why Paydot offers the payer a return step back to you. It does not mean the payer took it. |
Fetch a payment
Section titled “Fetch a payment”const response = await fetch(`https://pay-api.paydot.eu/payments/${paymentId}`);if (!response.ok) { throw new Error(`Paydot API error: ${response.status} ${await response.text()}`);}const payment = await response.json();const paid = payment.status === "EXECUTED" || payment.status === "SETTLED";import requests
response = requests.get(f"https://pay-api.paydot.eu/payments/{payment_id}")response.raise_for_status()payment = response.json()paid = payment["status"] in ("EXECUTED", "SETTLED")<?php$ch = curl_init("https://pay-api.paydot.eu/payments/$paymentId");curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$response = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status !== 200) { throw new Exception("Paydot API error: $status $response");}
$payment = json_decode($response, true);$paid = in_array($payment['status'], ['EXECUTED', 'SETTLED'], true);var request = HttpRequest.newBuilder( URI.create("https://pay-api.paydot.eu/payments/" + paymentId)) .GET() .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());if (response.statusCode() != 200) { throw new RuntimeException("Paydot API error: " + response.statusCode() + " " + response.body());}Status vocabulary
Section titled “Status vocabulary”| Status | Final | Meaning |
|---|---|---|
PENDING | No | Created, waiting on the payer at their bank. |
AUTHORISED | No | The payer finished at their bank. |
EXECUTED | Yes | The bank reports the payment as executed. |
SETTLED | Yes | Funds have settled. |
FAILED | Yes | The bank reported a failure. |
CANCELLED | Yes | Cancelled before it completed. |
INCOMPLETE | No | The payer left without finishing. Still resumable. |
UNKNOWN | No | No status could be resolved. |
A non-final status can still change. A final one will not.
Errors
Section titled “Errors”| Status | Cause |
|---|---|
404 | No payment with that id. The body is a ProblemDetail (RFC 7807) whose detail reads Payment not found. |
The detail is localised from the request’s Accept-Language, so match on the status code rather than on
the message.
Polling, and why you should not
Section titled “Polling, and why you should not”You do not have to poll. Configure a webhook and Paydot posts a signed
payment.status_changed event whenever a payment reaches EXECUTED, SETTLED, FAILED or CANCELLED,
retried for roughly 22 hours if your endpoint is down.
Fetch a payment when you have a reason to: a payer just arrived on your callback URL, someone opened an order in your admin, or you are reconciling after an outage that outlasted the retry window. A payment created from a link you generated does not expire, so a fetch days later still answers.