Skip to content

Add check payment

POST
/v1/actions/hospitality.action.add_check_payment/apply
curl --request POST \
--url https://api.aerandil.com/v1/actions/hospitality.action.add_check_payment/apply \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "branch": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "params": { "amount": { "amount": "example", "currency": "example" }, "authorised_by": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "credential_token": "example", "external_ref": "example", "folio_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "guest_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "override_reason": "example", "paid_at": "2026-04-15T12:00:00Z", "poiid": "example", "psp_reference": "example", "reservation_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "tender": "room_charge", "tendered": { "amount": "example", "currency": "example" }, "terminal_transaction_id": "example", "tip": { "amount": "example", "currency": "example" } }, "return_modified": false, "target": { "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "object_type": "hospitality.guest_check" } }'

Take one tender against an open check — the kernel is the system of record for a check’s payments. amount is what the payment applies to the check and may not exceed balance_due, except in cash: cash tendered (default amount) above the balance applies the balance and gives the rest back as change_given. A tip rides only on card, room_charge and charge_to_key and stays out of paid_total. A card payment carries the terminal’s references (psp_reference, terminal_transaction_id, poiid), never card data. A folio tender is bound server-side, the same on every path: room_charge requires folio_id and reservation_id, and the folio must be an open guest window of that booking’s in-house stay at the check’s own property (a house, master or company account, another booking’s bill or another hotel’s is refused); charge_to_key requires credential_token, the tapped key, resolved as post_charge_by_credential resolves it — its in-house stay names the folio and the reservation (a client folio_id or reservation_id that is not the key’s is refused) and its per-charge and daily caps bound the payment and its tip; a tap is live, so a paid_at more than five minutes from the kernel’s clock is refused and its postings are dated when the kernel records them, the clock the daily cap counts by. guest_id, the guest the server confirmed, must be the reservation’s guest (a sharer signs on their own booking); it is recorded on the payment and on each folio charge as signed_by. They post to that open folio as the payment is taken: one charge per revenue category on the check (bucket = the outlet’s usali_department, charge_at_outlet, revenue_category, its share of the VAT as tax applications), apportioned by largest remainder so the parts sum to the payment exactly, and the tip as a separate gratuity charge — a pass-through, never revenue — each emitting charge.posted.recorded, the payment linked to the charges and the check to the folio. The stay’s package allowance is consumed with no prompt and no other tender: when the folio’s in-house stay holds a live package component with a daypart — the check’s own meal period, else an all_day credit — due on the check’s business date (a breakfast the morning after its night), eaten at this outlet (an alternate outlet, or any when it names none) and with something left, it covers the payment’s food and soft-drink shares up to what is left (never alcohol, never the tip): that part is recorded as the payment’s allowance_applied and as a package_component_consumption (allowance and consumed both the amount, consumed, with the check’s covers) through the one package write, linked to the payment (consumption_for_check_payment), whose balance-neutral package line on the folio is one of the payment’s postings — and only the rest posts as the charges the guest owes, the covered shares shrunk with their VAT. One component per payment. Every payment records its share of each category and its VAT (allocation) over what earlier payments left, so a check paid in parts sums exactly. The payment that brings balance_due to zero settles the check — every line must be fulfilled, voided or comped by then — stamping settled_at (= paid_at), marking a seated table dirty and emitting fnb.check_settled with the per-tender breakdown. Business time: paid_at defaults to now. A present external_ref routes the create through the check_payment_external_ref business key, so a replayed payment is a no-op rather than a second payment. A room charge or charge-to-key is held to the stay’s posting rules (set_posting_rules): a no-post stay refuses it (no_post: …), and so does one whose credit — the greater of its credit limit and its live card holds, less its bills’ balance and the room still due — the posting and its tip would pass (no_credit: …). An override (override_reason) taken under a manager’s own session lets the refusal through — an override is proven by who is signed in, not by who is named: the authoriser recorded on the payment (override_kind, authorised_by, override_reason) and emitted as fnb.posting_override is the session’s staff member, and a body authorised_by must be that same one (override_not_authenticated: …). An override with nothing to override is refused (nothing_to_override: …), as is one under a session that is no manager’s (not_a_manager: …) or none at all (override_not_authenticated: …). Emits fnb.payment_added.

Effects: create hospitality.check_payment; link hospitality.link.check_payment_on_check; link hospitality.link.check_payment_to_folio; modify hospitality.guest_check; create hospitality.charge; create hospitality.tax_application; link hospitality.link.folio_has_charge; link hospitality.link.charge_at_outlet; link hospitality.link.charge_has_tax_application; link hospitality.link.check_payment_posted_charge; link hospitality.link.check_settled_to_folio; link hospitality.link.charge_via_credential; modify hospitality.folio; modify hospitality.service_table; create hospitality.check_receipt; link hospitality.link.receipt_for_check; create hospitality.package_component_consumption; modify hospitality.package_sale; link hospitality.link.package_sale_has_consumption; link hospitality.link.consumption_for_charge; link hospitality.link.charge_attributed_to_package_sale; link hospitality.link.charge_attributed_to_package_component; link hospitality.link.consumption_for_check_payment.

Media typeapplication/json
object
branch

Apply against an open branch’s overlay view instead of the canonical (main) plane. The action’s writes land in the branch’s copy-on-first-write overlay, its events in the branch’s own stream, and the invocation is journaled for merge-by-replay. Branch writes are action-only, so this is the write-side entry point to a branch (POST /v1/branches forks one).

string format: uuid
params
required
object
amount
required
Applied to the check (tip excluded); cash may exceed the balance and gives change
object
amount
required
string format: decimal
currency
required
string format: iso-4217
authorised_by
Confirms the overriding manager (optional; with override_reason): must be the staff member signed in — the override's authoriser is always the session's own, never one named here
string format: uuid
credential_token
The tapped room key's token (required for charge_to_key) — resolved server-side to its in-house stay and folio
string
external_ref
Source-system key for a replayed / connector-landed payment (replay key)
string
folio_id
Folio to post to (required for room_charge; for charge_to_key the key names it, and any other is refused)
string format: uuid
guest_id
The guest the server confirmed — the reservation's guest (room_charge and charge_to_key)
string format: uuid
override_reason
Override the stay's no-post or credit refusal, and why (room_charge and charge_to_key) — taken under a manager's own session: an F&B manager, a front-office supervisor, the manager on duty, the general manager or the owner, active at the check's house
string
paid_at
When the payment was taken — business time (defaults to now)
string format: date-time
poiid
The terminal (POIID) a card payment was taken on
string
psp_reference
The processor's reference for a card payment (Adyen pspReference)
string
reservation_id
The reservation the folio is a window of (required for room_charge; for charge_to_key the key names it)
string format: uuid
tender
required
Tender
string
Allowed values: room_charge cash card comp external charge_to_key
tendered
Cash handed over (cash only; defaults to amount)
object
amount
required
string format: decimal
currency
required
string format: iso-4217
terminal_transaction_id
The terminal's own transaction id for a card payment
string
tip
Tip (card, room_charge and charge_to_key only)
object
amount
required
string format: decimal
currency
required
string format: iso-4217
return_modified

When true, the response carries modified_objects and modified_links projections — the engine reads the event log inside the same transaction so the projection observes the handler’s own writes.

boolean
target
required
object
id
required
string format: uuid
object_type
required
Allowed value: hospitality.guest_check

Action applied. modified_objects and modified_links populated when return_modified: true was supplied.

Media typeapplication/json
ApplyActionResponse

Envelope returned by the Aerandil action engine. correlation_id ties every event emitted by this invocation; modified_objects and modified_links project the events the handler emitted (per the action’s declared effects); warnings carries any non-blocking soft-validator observations.

object
correlation_id
required

Per-invocation correlation id; matches events.correlation_id for every event this action appended.

string format: uuid
modified_links
required

Links established or removed by this invocation. Empty when the caller did not request return_modified.

Array<object>
object
from_id
required
string format: uuid
from_type
required
string
kind
required
Allowed values: linked
link_type
required
Allowed values: hospitality.link.check_payment_on_check hospitality.link.check_payment_to_folio hospitality.link.folio_has_charge hospitality.link.charge_at_outlet hospitality.link.charge_has_tax_application hospitality.link.check_payment_posted_charge hospitality.link.check_settled_to_folio hospitality.link.charge_via_credential hospitality.link.receipt_for_check hospitality.link.package_sale_has_consumption hospitality.link.consumption_for_charge hospitality.link.charge_attributed_to_package_sale hospitality.link.charge_attributed_to_package_component hospitality.link.consumption_for_check_payment
to_id
required
string format: uuid
to_type
required
string
modified_objects
required

Objects created, modified, or soft-deleted by this invocation. Empty when the caller did not request return_modified.

Array<object>
object
id
required
string format: uuid
kind
required
Allowed values: created modified
object_type
required
Allowed values: hospitality.check_payment hospitality.guest_check hospitality.charge hospitality.tax_application hospitality.folio hospitality.service_table hospitality.check_receipt hospitality.package_component_consumption hospitality.package_sale
warnings

Non-blocking soft-validator observations emitted during this invocation (e.g. comp-authority over-limit, recipe pour-cost over sell-price). Absent when no warnings were emitted.

Array<object>
object
message
required

Human-readable summary, suitable for logging or operator-UI surfacing.

string
object_type
required

Object type the warning was raised against.

string
property

Property the warning anchors to, when a single field is the locus. Absent for multi-field rules.

string
rule
required

Stable kebab-case rule identifier (e.g. comp-authority-over-limit).

string
Example
{
"modified_links": [
{
"kind": "linked",
"link_type": "hospitality.link.check_payment_on_check"
}
],
"modified_objects": [
{
"kind": "created",
"object_type": "hospitality.check_payment"
}
]
}

Conflict — concurrent modification or unique constraint violation.

Validation error — parameter validation or business-rule violation.