Issue the invoice for a folio
const url = 'https://api.aerandil.com/v1/folios/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/invoice';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"issued_on":"2026-04-15","note":"example","recipient_address_override":{"city":"example","country":"example","line1":"example","line2":"example","postal_code":"example","region":"example"},"recipient_kind":"person","recipient_name_override":"example","recipient_tax_identifier_override":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.aerandil.com/v1/folios/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/invoice \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "issued_on": "2026-04-15", "note": "example", "recipient_address_override": { "city": "example", "country": "example", "line1": "example", "line2": "example", "postal_code": "example", "region": "example" }, "recipient_kind": "person", "recipient_name_override": "example", "recipient_tax_identifier_override": "example" }'Turns a sealed folio into the numbered document its recipient keeps, then renders and stores the PDF. Accepts a closed folio at zero balance (the settled stay) and an open folio already transferred to a company’s A/R account (the billed stay, which this seals as it issues). A failed upload is not a failed request. The number is allocated and the document exists the moment the action commits; pdf_stored reports whether the rendering also reached object storage, and GET /v1/invoices/{invoice_id}/pdf renders on demand when it did not. Retry-safe without an Idempotency-Key: the route re-reads first, and a folio that already carries an uncredited invoice answers with that document and already_issued: true rather than asking the series for a second number.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The folio to project into a document.
Header Parameters
Section titled “Header Parameters”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.
Request Bodyrequired
Section titled “Request Bodyrequired”object
The property’s business date of issue — the document’s date for tax purposes, never the wall clock.
Printed in the document’s footer.
Print this address instead of the profile’s.
object
Defaults to the company when the folio was settled to A/R or the reservation carries one, else the guest.
Responses
Section titled “Responses”Issued.
object
True when the folio already carried an uncredited invoice and this call returned it rather than issuing a second one.
object
Exact decimal as a string. Money is never a float — binary floating point cannot hold 0.10.
object
Exact decimal as a string. Money is never a float — binary floating point cannot hold 0.10.
E.g. STAN-2026-000123.
Whether the rendering reached object storage. False is not an error — the document exists either way, and the pdf route renders on demand.
Example
{ "kind": "invoice"}Headers
Section titled “Headers”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.
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
object
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).
Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.
Human-readable explanation of the failure.
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.
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
object
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).
Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.
Human-readable explanation of the failure.
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 folio cannot be invoiced. The reason is one of INVOICE_BLOCKERS: already_invoiced, folio_open, folio_not_invoiceable, recipient_address_missing, recipient_unknown, issuer_not_configured, folio_empty, rebate_not_a_credit. preview_invoice returns the same list without allocating anything.
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
object
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).
Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.
Human-readable explanation of the failure.
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" }}