Settle a dispute fee parked for review
const url = 'https://api.aerandil.com/v1/payment-disputes/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/fee-review';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"note":"example","outcome":"recovered","reference":"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/payment-disputes/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/fee-review \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "note": "example", "outcome": "recovered", "reference": "example" }'A lost chargeback’s dispute fee, retried at the night audit, is parked dispute_fee_recovery = needs_review when the retry’s debit could not be read back from Stripe — never retried blind. This records what a person found: recovered (the debit is there; reference names Stripe’s py_…), or written_off (it is not; the platform carries the fee, note says why). Nothing is owed after either, no retry opens, and the case keeps who settled it and when. Stripe is asked nothing. A case not parked for review, an unknown outcome, or a write-off without a note is a 422; the same settlement again changes nothing, a different one after it is a 422. Accepts Idempotency-Key. Operator only (tenant_admin:write).
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The chargeback case (payment_dispute).
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
What was found; required for a write-off.
The Stripe debit (py_…) found, when recovered.
Responses
Section titled “Responses”The case as settled.
object
Examplegenerated
{ "dispute_fee_recovered": { "amount": "example", "currency": "example" }, "dispute_fee_recovery": "example", "dispute_fee_reviewed_at": "2026-04-15T12:00:00Z", "dispute_fee_written_off": { "amount": "example", "currency": "example" }, "idempotent_replay": true, "payment_dispute_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "version": 1}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" }}idempotency_in_flight (an earlier request under the same Idempotency-Key is still running).
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" }}invalid_body, the verb’s refusal (invalid_action: the case is not parked for review, a write-off has no note, or it was settled differently already), or idempotency_key_mismatch.
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" }}