Skip to content

Take a check's card payment on an Adyen terminal

POST
/v1/fnb/checks/{check_id}/card-payment
curl --request POST \
--url https://api.aerandil.com/v1/fnb/checks/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/card-payment \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "amount": { "amount": "example", "currency": "example" }, "device_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "tip_mode": "none" }'

Sends a registered Adyen terminal a Terminal API PaymentRequest for part of an open check’s balance — with tip_mode = on_terminal, the terminal asks the guest for a tip (tenderOption=AskGratuity) — and records the approval as the check’s payment through add_check_payment under the caller’s own identity: tender = card, amount = the authorised total less the terminal’s TipAmount, tip, psp_reference, terminal_transaction_id, poiid, external_ref = the pspReference. Authorised before the terminal is touched: the caller’s add_check_payment scope, the house and (for a till) outlet gate, the check open and owing at least amount, and a dry run of the payment the kernel will record. Idempotency-Key is required: a lost answer is asked after (TransactionStatusRequest), and one the terminal still will not give answers 504 card_outcome_unknown — check the terminal, then retry with the same key, which resumes the question rather than charging again. A terminal approval the kernel then refuses is reversed on the terminal (ReversalRequest) and answered 409. 501 unless AERANDIL_ADYEN_ENABLED=1.

check_id
required
string format: uuid

The open hospitality.guest_check the card pays.

Idempotency-Key
string
>= 1 characters

Opaque idempotency token (Stripe-shape). Repeated POSTs with the same key replay the original response within the cache TTL rather than creating a duplicate object.

Media typeapplication/json
object
amount
required

The part of the check’s balance this card pays, tip excluded: more than zero, at most balance_due, in the check’s currency.

object
amount
required

Exact decimal as a string. Money is never a float — binary floating point cannot hold 0.10.

string format: decimal
currency
required
string format: iso-4217
device_id
required

The registered hospitality.device the guest pays on. Must be active and carry the Adyen POIID in vendor_device_ref.

string format: uuid
tip_mode

on_terminal asks the guest for a tip on the terminal (tenderOption=AskGratuity); the tip comes back in AmountsResp.TipAmount and is recorded as the payment’s tip.

string
default: none
Allowed values: none on_terminal

The card was approved and the payment recorded on the check.

Media typeapplication/json
object
amount
required
object
amount
required

Exact decimal as a string. Money is never a float — binary floating point cannot hold 0.10.

string format: decimal
currency
required
string format: iso-4217
check
required
object
balance_due
required
object
amount
required

Exact decimal as a string. Money is never a float — binary floating point cannot hold 0.10.

string format: decimal
currency
required
string format: iso-4217
status
required
string
Allowed values: open settled
idempotent_replay

true on a cached Idempotency-Key replay.

boolean
payment_id
required

The hospitality.check_payment recorded.

string format: uuid
psp_reference

Adyen’s pspReference for the payment.

string | null
tip
required
object
amount
required

Exact decimal as a string. Money is never a float — binary floating point cannot hold 0.10.

string format: decimal
currency
required
string format: iso-4217
Example
{
"check": {
"status": "open"
}
}
Cache-Control
string

Always no-store. Object and link state is live data and is never cacheable.

The bearer authenticated but does not hold the scope this operation requires.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

No such object in the caller’s tenant — which is also the answer when it exists in another tenant, by design.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

Nothing recorded: check_not_open, amount_exceeds_balance; card_declined, card_cancelled, terminal_busy (nothing charged); card_reversed — the terminal approved, the kernel refused (its reason in the message, its code in parameters.kernel_code) and the payment was reversed; card_reversal_failed — the same, but the reversal failed: the card was charged, refund parameters.psp_reference by hand or retry with the same key; idempotency_in_flight.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

idempotency_key_required, invalid_body, invalid_amount, currency_mismatch, device_not_active, device_missing_vendor_ref, terminal_rejected (Adyen never delivered the message — e.g. an unknown POIID), idempotency_key_mismatch, or the kernel’s refusal of the dry run (invalid_action).

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

The Adyen bridge is not enabled on this deployment.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

terminal_unreachable — the payment never reached the terminal, nothing was charged; terminal_gateway_error — the terminal refused the request itself.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

card_outcome_unknown — the terminal has not said whether the card was charged. Check the terminal; a retry with the same Idempotency-Key asks again and records the payment if it was approved, never sending a second one.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}