Give money back
const url = 'https://api.aerandil.com/v1/payments/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/refunds';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"refund_amount":{"amount":"example","currency":"example"},"refund_reason":"duplicate"}'};
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/payments/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/refunds \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "refund_amount": { "amount": "example", "currency": "example" }, "refund_reason": "duplicate" }'Creates a new negative-amount payment leg — proposal 0019’s shape, which is why this is 201 and returns a second payment id rather than mutating the original. Partial refunds are ordinary; the kernel computes the remaining refundable balance from the legs already recorded, so the caller does not have to track it. The leg is pending until the processor confirms it on the webhook.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The captured payment being refunded.
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
Partial refunds are ordinary; the kernel computes the remaining refundable balance from the legs already recorded.
object
Exact decimal as a string. Money is never a float — binary floating point cannot hold 0.10.
Responses
Section titled “Responses”The refund leg was recorded.
object
The new negative-amount leg. Proposal 0019’s shape: a refund is a second payment, not an edit of the first.
pending until the processor confirms it on the webhook.
Examplegenerated
{ "original_payment_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "refund_payment_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "status": "example"}Headers
Section titled “Headers”Always no-store. Object and link state is live data and is never cacheable.
Stripe could not be reached (a transport failure, a 5xx, a 429, or this attempt’s key still running at Stripe), so the work was written down as a rail instruction and is taken when the rail is back — under the same processor key as this attempt, so it is never taken twice. A second request while it is queued answers the same instruction (already_queued); the desk may cancel it while it is still queued (cancel_rail_instruction).
object
Example
{ "kind": "capture", "queued": true, "state": "queued"}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" }}rail_instruction_open — another verb is already queued for this hold or stay (a release behind a queued capture); it is taken first, when the card rail is back.
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 request parsed but a validator refused it. The envelope’s code names which rule.
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" }}