The hotel's onboarding link: a page that continues to Stripe
const url = 'https://api.aerandil.com/v1/onboarding-links/example';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.aerandil.com/v1/onboarding-links/examplePublic — the hotel holds no bearer of ours. The link the operator sends the hotel, and where Stripe’s hosted onboarding sends it when its own link has expired, been opened before, or been spent by a messaging client’s preview. Answers a small self-contained HTML page — the house’s name and one button, “Continue to Stripe”, a form that POSTs to this same address — and spends nothing: a mail scanner or a link preview that fetches the link leaves it as it was. No script, no external asset (Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'), Referrer-Policy: no-referrer. Every refusal — forged, expired, used, replaced, a closed account — is the same 404, which says nothing about whether the account exists, and Stripe is asked nothing. Rate-limited per IP like /oauth/token.
Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The signed one-use token the operator’s onboarding link minted.
Responses
Section titled “Responses”The page with the one button.
Headers
Section titled “Headers”Always no-store. Object and link state is live data and is never cacheable.
onboarding_link_not_found — expired, used, replaced or never ours.
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" }}Per-IP rate limit exceeded (the /oauth/token limiter).
No card rail, or no public address, 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" }}