Skip to content
BaxPayDevelopers

Get started

API conventions

The rules every endpoint follows, so the rest of the docs don't have to repeat them.

Responses are wrapped

A successful call returns its result in data, next to three fields that describe the call:

{
  "success": true,
  "data": { "id": "1c9f4a2e-…", "status": "OPEN" },
  "timestamp": "2026-07-16T14:02:10.000Z",
  "path": "/v1/payment-links"
}

Read data, and ignore fields you don't recognise: we add fields to /v1 without notice. Errors are not wrapped; they have their own shape.

Lists and pagination

List endpoints take page (from 1) and limit (default 25, at most 100), and return the page in data.data with the totals beside it:

curl "https://sandbox-api.baxpay.com/v1/payment-links?status=OPEN&page=1&limit=25" \
  -H "Authorization: Bearer $BAXPAY_API_KEY"
{
  "success": true,
  "data": {
    "data": [{ "id": "1c9f4a2e-…", "status": "OPEN" }],
    "total": 1,
    "page": 1,
    "limit": 25
  }
}

A limit above 100 is treated as 100.

Idempotency keys

Every call that creates something or moves money requires an Idempotency-Key header: any unique string of 8 to 255 characters (a UUID is ideal). Without it the call is refused with 400.

If a request times out, you don't know whether it went through. Send it again with the same key: if the first attempt succeeded, you get its original response back and nothing is created twice.

KEY=$(uuidgen)
BODY='{ "description": "Order #1042", "amount": 25, "businessWide": true }'
 
first=$(curl -s -X POST https://sandbox-api.baxpay.com/v1/payment-links \
  -H "Authorization: Bearer $BAXPAY_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $KEY" -d "$BODY" | jq -r .data.id)
again=$(curl -s -X POST https://sandbox-api.baxpay.com/v1/payment-links \
  -H "Authorization: Bearer $BAXPAY_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $KEY" -d "$BODY" | jq -r .data.id)
 
echo "first=$first again=$again"   # the same link: the retry created nothing
[ "$first" = "$again" ]

The rules:

SituationResult
Same key, same body, first call finishedThe original response, replayed
Same key, same body, first call still running409: wait a moment and retry with the same key
Same key, different body400: a bug in your code, never retried for you
No key on a call that requires one400

Keys are remembered for 24 hours, per merchant and per endpoint.

KEY=$(uuidgen)
curl -s -X POST https://sandbox-api.baxpay.com/v1/payment-links \
  -H "Authorization: Bearer $BAXPAY_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $KEY" -d '{ "description": "Order #1043", "amount": 25, "businessWide": true }' > /dev/null
curl -X POST https://sandbox-api.baxpay.com/v1/payment-links \
  -H "Authorization: Bearer $BAXPAY_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $KEY" -d '{ "description": "Order #1043", "amount": 30, "businessWide": true }'
{
  "statusCode": 400,
  "message": "This Idempotency-Key was already used with a different request body.",
  "error": "Bad Request"
}

Rate limits

Limits are counted per IP address over a rolling minute:

ScopeLimit
Any endpoint (default)200 requests / minute
POST /payment-links, POST /einvoices, POST /clients, POST /products60 / minute
POST /einvoices/{id}/send30 / minute

Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the limit you get 429: wait for the reset, then retry with the same idempotency key.

Amounts

  • Payment links, e-invoices, clients and products use decimal euros: 47.30.
  • In-store sessions (/integration/…) use integer minor units: 4730, in fields ending in Minor.

Currencies are ISO 4217 codes in capitals (EUR).

Ids, times and request ids

  • Ids are UUIDs (1c9f4a2e-6b1d-4c1e-9a52-0d9f6f2c1b7a). Payment-link tokens (plk_…) are the only prefixed ids, and they belong in URLs you give to payers, never in API paths that need an id.
  • Times are ISO 8601 in UTC (2026-07-16T14:03:21.512Z).
  • Every call made with an API key gets a request id: the X-Request-Id response header, and requestId in an error. Send your own X-Request-ID (8 to 128 letters, digits, ., _, : or -) and it is used instead. Quote it when you contact support.

Request log

Every call made with an API key is logged for 30 days, in its mode: method, path (without the query string), status, duration, request id, key and IP. Never a body, a header or a key. The dashboard shows the same log under Developers → Requests.

GET/requeststhis mode's requests, newest first; filter by status, method, path, apiKeyId
GET/requests/{id}one request

status takes a class (2xx, 4xx, 5xx) and path any part of the path:

curl "https://sandbox-api.baxpay.com/v1/requests?status=2xx&path=/payment-links&limit=5" \
  -H "Authorization: Bearer $BAXPAY_API_KEY"
{
  "success": true,
  "data": {
    "data": [
      {
        "id": "6e1d0f3a-…",
        "method": "POST",
        "path": "/v1/payment-links",
        "status": 201,
        "durationMs": 38,
        "requestId": "req_9b1c…",
        "ip": "203.0.113.9",
        "livemode": false,
        "apiKey": { "id": "0c5d…", "label": "Backend server", "prefix": "bx_test_", "last4": "a9f2" },
        "createdAt": "2026-07-16T14:03:21.512Z"
      }
    ],
    "total": 1,
    "page": 1,
    "limit": 5
  }
}
curl https://sandbox-api.baxpay.com/v1/requests/6e1d0f3a-… \
  -H "Authorization: Bearer $BAXPAY_API_KEY"
{ "success": true, "data": { "id": "6e1d0f3a-…", "method": "POST", "status": 201, "requestId": "req_9b1c…" } }