Create a fiat card order
POST /api/v1/partner/customers/{customerId}/fiat-orders
Required scope:
payments:create(granted only after the partner migration is applied).
Creates a card payment on behalf of the customer.
Request
curl -X POST https://www.niftipay.com/api/v1/partner/customers/pc-1/fiat-orders \
-H "Authorization: Bearer <partner_api_key>" \
-H "Idempotency-Key: <uuid>" \
-H "Content-Type: application/json" \
-d '{ "integration_id": "int-1", "amount_cents": 1000, "currency": "EUR",
"reference": "INV-1", "return_url": "https://shop.test/done",
"failure_url": "https://shop.test/oops",
"email": "ada@example.com", "first_name": "Ada", "last_name": "Lovelace",
"phone": "+34600111222", "country": "ES" }'
| Field | Type | Required | Notes |
|---|---|---|---|
integration_id |
string | yes | Which integration processes the payment. Get one from List fiat integrations. |
amount_cents |
integer | yes | Major units are not accepted; send cents. |
currency |
string | yes | ISO 4217, e.g. EUR. |
reference |
string | yes | Your id for this order (unique per merchant). |
return_url |
string | yes | https only. Where the buyer goes after success. |
failure_url |
string | yes | https only. Where the buyer goes after a decline. |
description |
string | no | Optional memo. |
email |
string | no | Buyer email. |
first_name |
string | no | Buyer first name. See Buyer details below. |
last_name |
string | no | Buyer last name. |
phone |
string | no | Buyer phone. E.164 preferred, e.g. +34600111222. |
country |
string | no | Buyer ISO-2 billing country. Normalized to upper case. |
Both
return_urlandfailure_urlare required and https-only. Omitting either sends the buyer to the merchant’s own page on that screen — so the API refuses it with400 invalid_request.
Buyer details
The five buyer fields are all optional, and all are forwarded to the card
processor rather than stored on the order. Only email is persisted on the order
row; the other four are also written to the merchant’s customer profile for that
email, where the first value seen wins and a later order without them does not
erase it.
Send them when your checkout already has them. Processors differ in what they require, and the one handling the payment may need a name, a phone and a billing country — when a field is missing, a placeholder is generated for it, which is accepted but makes a card issuer more likely to decline.
They are the one place this rail takes either naming convention. first_name
/ last_name / phone / country and firstName / lastName /
customer_phone / customer_country are both read; the snake_case spelling is
preferred, to match the rest of this body.
A blank or wrong-typed buyer field is dropped, not refused. Unlike
reference or email, these never produce a 400 — a bad phone is not a reason
to fail a payment the buyer is waiting on.
Response 201
{
"request_id": "req-1",
"api_version": "2026-08-01",
"data": {
"fiat_order": {
"order_key": "1001",
"status": "new",
"currency": "EUR",
"amount_cents": 1000,
"service_fee_cents": 25,
"total_cents": 1025,
"merchant_reference": "INV-1",
"created_at": "2026-08-24T10:00:00.000Z",
"updated_at": null
},
"pay_url": "https://psp.test/pay/1001"
}
}Errors
| Status | code | Meaning |
|---|---|---|
| 400 | invalid_request | Missing/!https return_url/failure_url, wrong-typed field |
| 409 | reference_conflict | reference already used (generic, ownerless) |
| 409 | integration_missing | integration_id does not belong to this customer |
| 409 | capability_unavailable | Card payments granted but not currently usable |
A repeated
referencereturns a genericreference_conflict— it never tells you whose order holds it.