Partners
Markdown

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_url and failure_url are required and https-only. Omitting either sends the buyer to the merchant’s own page on that screen — so the API refuses it with 400 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 reference returns a generic reference_conflict — it never tells you whose order holds it.