Open a property's merchant account
const url = 'https://api.aerandil.com/v1/properties/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/merchant-account';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"country":"example","email":"hello@example.com","fee_conversion_bps":1,"fee_schedule":[{"bps":1,"card_present":true,"fee_class":"domestic_standard","fixed":{"amount":"example","currency":"example"},"processor_bps":1,"processor_fixed":{"amount":"example","currency":"example"}}],"markup_bps":1}'};
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/properties/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/merchant-account \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "country": "example", "email": "hello@example.com", "fee_conversion_bps": 1, "fee_schedule": [ { "bps": 1, "card_present": true, "fee_class": "domestic_standard", "fixed": { "amount": "example", "currency": "example" }, "processor_bps": 1, "processor_fixed": { "amount": "example", "currency": "example" } } ], "markup_bps": 1 }'Creates the hotel’s own Stripe account under the platform’s (Stripe Connect, Express-style: Stripe verifies the hotel on its hosted form, the hotel gets Stripe’s Express dashboard, the platform pays Stripe’s fees) and records it with open_merchant_account. The account opens in onboarding; send the hotel to the onboarding link next. While the account is open but not yet active, card payments at the property are refused with merchant_account_not_ready rather than taken on the platform’s account. If the ledger refuses the account after Stripe has made it, the Stripe account is deleted again. Operator only (tenant_admin:write): the platform signs the hotel up and sets its fee. 501 unless AERANDIL_STRIPE_ENABLED=1.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The property whose card payments will settle to the account.
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
Where the hotel trades (ISO 3166-1 alpha-2). Fixed for the account’s life.
The hotel’s contact, prefilled on Stripe’s form.
Stripe’s currency-conversion fee, for the estimate. Defaults to the country’s.
The whole schedule, row by row: every card class online and card-present, once.
object
This row prices a terminal’s charge rather than an online one.
The card’s class: regional is the EEA for a UK account and the UK for a eurozone one.
The fixed fee the hotel pays — Stripe’s own, passed through.
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.
The platform’s markup over Stripe’s published rate for each card class, in basis points — the country’s table plus this. Defaults to 40 (Stripe + 0.40%). Not with fee_schedule.
Responses
Section titled “Responses”The account, opened and waiting on the hotel.
object
Example
{ "status": "onboarding"}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" }}merchant_account_exists — the property already has an account that is not closed.
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 country is not an ISO 3166-1 alpha-2 code, or the fee is outside 0–10000 basis points.
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 card rail is configured on this deployment.
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" }}rail_unavailable — the card processor could not be reached (a transport failure, a 5xx, a 429, or this request’s key still running at the processor). No account was opened. Try again after Retry-After.
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" }}Headers
Section titled “Headers”Seconds to wait before trying the same request again (RFC 9110 §10.2.3) — the queue’s first backoff.