DEVELOPERS

Account Operations API

Read balances, request refunds and withdrawals, answer disputes and manage webhook deliveries. Sign every request as described under Authentication.

  • Base URLhttps://www.manuellsolutions.com/api/v3
  • API version3.0.0

Browse the operations

Environment

Test without moving real money.

Real payments. A live key is required.

Balance

Read your available and withdrawable balance.

The sandbox balance is virtual. Sandbox payments move to available_amount at once, without waiting for a value date, so you can test withdrawals right away.

The live balance comes from real collections. A payment waits in pending_settlement_amount until its value date, then moves to available_amount.

GET/api/v3/balance

Get balance

Response · 200

Balance summary.

Balance

FieldTypeRequiredDescription
currency_codestringRequiredConfigured platform base currency.
USDEURAEDTRY
available_amountstringRequiredCombined available balance across link, API and store wallets. A sandbox key reads the isolated virtual API wallet instead.
pending_settlement_amountstringRequiredCollected but not yet settled (value date pending). Always 0.00 with a sandbox key, because sandbox payments do not wait for a value date.
environmentstringRequiredEnvironment the figures belong to (the environment of the signing key).
livesandbox

Response · Example

{
  "currency_code": "USD",
  "available_amount": "48200.00",
  "pending_settlement_amount": "250.00",
  "environment": "live"
}

Possible errors

GET/api/v3/balance/withdrawable

Get withdrawable balance

Response · 200

Withdrawable summary.

WithdrawableBalance

FieldTypeRequiredDescription
currency_codestringRequiredConfigured platform base currency.
USDEURAEDTRY
withdrawable_amountstringRequiredCombined available link, API and store balance; POST /withdrawals can debit only the API wallet and applies additional checks. A sandbox key reads the isolated virtual API wallet.
can_withdrawbooleanRequiredFalse if any wallet bucket is negative.
environmentstringRequiredEnvironment the figures belong to (the environment of the signing key).
livesandbox

Response · Example

{
  "currency_code": "USD",
  "withdrawable_amount": "48200.00",
  "can_withdraw": true,
  "environment": "live"
}

Possible errors

Refunds

Request a refund or void and track it.

In live, HTTP 202 means the request was received, not that the refund is done. Follow the result through the status endpoints: requested, then awaiting_provider_manual, then completed; or rejected / cancelled.

In sandbox a request is finalized immediately (completed by default). Send X-CAV-Sandbox-Scenario: rejected to test a rejected refund.

Live requests are reviewed. Track the returned reversal until it is completed, rejected or cancelled. refund reverses a settled payment; void cancels one that is not final. Only a completed refund sends payment.refunded; track a void with GET.

POST/api/v3/refundsIdempotency-Key required

Request a refund or void

Parameters

FieldTypeRequiredDescription
X-CAV-Sandbox-Scenariostring · headerOptionalSandbox keys only. Selects the simulated outcome: completed (default) or rejected (no effect on the virtual wallet). A live key that sends this header, or any other value, gets 422 1000001. The header is not part of the signed string; it is part of the Idempotency-Key fingerprint, so reusing a key with another scenario returns 9000010. The applied scenario is echoed in the response header of the same name.
completedrejected

Request body

FieldTypeRequiredDescription
payment_codestringRequiredCode of the successfully paid payment to reverse.
maxLength 16
operation_typestringRequiredrefund returns a settled payment; void cancels a card collection that is not yet finalised. Both open a reversal request (status requested). An operator reviews it; once approved, the amount is reserved from your balance and the status is awaiting_provider_manual until the provider refund reference is recorded (completed); otherwise the request ends rejected or cancelled (the reserve is released). This endpoint does not call the provider.
refundvoid
reasonstringRequiredWhy the reversal is requested.
minLength 3maxLength 500

Request body · Example

{
  "payment_code": "ab34cdef",
  "operation_type": "refund",
  "reason": "Customer cancelled the order."
}

Response · 202

Reversal requested. It is reviewed and sent to the provider manually. With a sandbox key the simulated result is returned (environment sandbox); an idempotent replay also returns 202.

Reversal

FieldTypeRequiredDescription
idstringRequiredReversal request identifier (UUID).
operationstringRequiredOperation type.
refundvoid
statusstringRequiredReversal lifecycle: requested (waiting for an operator) → awaiting_provider_manual (approved; the amount is reserved until the provider refund reference is recorded) → completed, or rejected / cancelled (the reserve is released). processing and failed are reserved values that are not used for payment reversals today. With a sandbox key the status is final at once: completed (default) or rejected.
requestedprocessingcompletedrejectedfailedawaiting_provider_manualcancelled
amountstringRequiredFull amount of the reversed payment, in the payment's own currency (the same amount and currency as the payment and its payment.refunded webhook), as a decimal string with 2 fraction digits. A requested status does not mean funds have moved.
currencystringRequiredCurrency of amount: the currency_code of the reversed payment.
reasonstringRequiredReason you provided.
provider_referencestring | nullRequiredProvider refund reference, filled when the real-POS refund is completed. In sandbox a synthetic reference starting with SBX- is returned when the simulated reversal completes; it is not a provider record.
provider_refunded_atstring · date-time | nullRequiredWhen the provider refund was recorded (UTC). Null until manual completion.
created_atstring · date-timeRequiredRequest time (UTC).
updated_atstring · date-time | nullRequiredLast status change (UTC).
payment_codestring | nullRequiredCode of the payment this reversal belongs to (the code returned when the payment was created).
environmentstringRequiredEnvironment of the reversal (the environment of the signing key).
livesandbox

Response · Example

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "operation": "refund",
  "status": "requested",
  "amount": "250.00",
  "currency": "USD",
  "reason": "Customer cancelled the order.",
  "provider_reference": "string",
  "provider_refunded_at": "2026-09-26T09:00:00.000Z",
  "created_at": "2026-09-26T09:00:00.000Z",
  "updated_at": "2026-09-26T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "live"
}

Possible errors

GET/api/v3/refunds

List refunds

Parameters

FieldTypeRequiredDescription
pageinteger · queryOptionalPage number.
minimum 1
per_pageinteger · queryOptionalItems per page.
minimum 1maximum 100
statusstring · queryOptionalFilter by status.
requestedprocessingawaiting_provider_manualcompletedrejectedfailedcancelled
operation_typestring · queryOptionalFilter by operation.
refundvoid

Response · 200

Paginated refunds.

FieldTypeDescription
dataReversal[]
metaPaginationMeta

Response · Example

{
  "data": [
    {
      "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
      "operation": "refund",
      "status": "requested",
      "amount": "250.00",
      "currency": "USD",
      "reason": "Customer cancelled the order.",
      "provider_reference": "string",
      "provider_refunded_at": "2026-09-26T09:00:00.000Z",
      "created_at": "2026-09-26T09:00:00.000Z",
      "updated_at": "2026-09-26T09:00:00.000Z",
      "payment_code": "ab34cdef",
      "environment": "live"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Possible errors

GET/api/v3/refunds/{id}

Get refund status

Parameters

FieldTypeRequiredDescription
idstring · uuid · pathRequiredThe reversal id.

Response · 200

The reversal.

Object: Reversal (fields are listed under Request a refund or void).

Response · Example

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "operation": "refund",
  "status": "requested",
  "amount": "250.00",
  "currency": "USD",
  "reason": "Customer cancelled the order.",
  "provider_reference": "string",
  "provider_refunded_at": "2026-09-26T09:00:00.000Z",
  "created_at": "2026-09-26T09:00:00.000Z",
  "updated_at": "2026-09-26T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "live"
}

Possible errors

Notification

When a refund completes, a signed payment.refunded notification is sent to the payment's webhook URL. Headers, signature and retries are the same as in Webhooks. A void sends no notification.

POSTpayment.refunded

Signed payment.refunded notification to the merchant URL

Request body

FieldTypeRequiredDescription
event_idstring · uuidRequired
event_typestringRequired
payment.refunded
environmentstringRequired
sandboxlive
occurred_atstring · date-timeRequired
refundobjectRequired
refund.public_idstring · uuidRequired
refund.statusstringRequired
completed
refund.amountstringRequiredPositive amount as a fixed-scale decimal string with 2 decimals. "0.00" is not accepted.
refund.currency_codestringRequiredFiat currency code, limited to the four supported currencies.
USDEURAEDTRY
refund.completed_atstring · date-timeRequiredSame instant as occurred_at.
paymentobjectRequired
payment.public_idstring · uuidRequired
payment.codestringRequired
minLength 1maxLength 16
payment.merchant_referencestring | nullRequired
maxLength 64
orderobjectRequired
order.public_idstring · uuidRequired

Request body · Example

{
  "event_id": "B5D4E456-EFC1-4EC2-A613-D64A16E45BD5",
  "event_type": "payment.refunded",
  "environment": "sandbox",
  "occurred_at": "2026-09-28T12:00:00.000Z",
  "refund": {
    "public_id": "A1B2C3D4-E5F6-4789-8ABC-DEF012345678",
    "status": "completed",
    "amount": "100.00",
    "currency_code": "USD",
    "completed_at": "2026-09-28T12:00:00.000Z"
  },
  "payment": {
    "public_id": "11111111-2222-4333-8444-555555555555",
    "code": "ab34cdef",
    "merchant_reference": "SIP-2026-0001"
  },
  "order": {
    "public_id": "66666666-7777-4888-8999-AAAAAAAAAAAA"
  }
}

Withdrawals

Request a USDT (TRC20) withdrawal and track it.

In live, HTTP 201 means the request was accepted and the amount is held, not that the USDT was sent. Check status and tx_hash, and double-check the address: a transfer on the chain cannot be reversed.

A sandbox withdrawal debits the virtual balance and never sends anything on the chain. It follows the same rules as live, including the minimum, the daily cap and the conversion rate. Send X-CAV-Sandbox-Scenario: rejected to test a rejection. The sandbox accepts the TRON zero address as a destination; live rejects burn addresses with 1000030.

The minimum and the daily cap are set per account by Manuell; below the minimum the API returns 9000019, above the cap 9000021. In live, an operator of Manuell sends the USDT and records tx_hash (sent), or rejects the request with a reason (rejected) and the amount returns to your balance.

POST/api/v3/withdrawalsIdempotency-Key required

Request a USDT withdrawal

Parameters

FieldTypeRequiredDescription
X-CAV-Sandbox-Scenariostring · headerOptionalSandbox keys only. Selects the simulated outcome: sent (default) or rejected (no effect on the virtual wallet). A live key that sends this header, or any other value, gets 422 1000001. The header is not part of the signed string; it is part of the Idempotency-Key fingerprint, so reusing a key with another scenario returns 9000010. The applied scenario is echoed in the response header of the same name.
sentrejected

Request body

FieldTypeRequiredDescription
amountstringRequiredAmount to hold from the API wallet, in the configured platform base currency, as a decimal string with 2 fraction digits. The minimum amount and the daily cap are set per account by the platform operator: an amount below the minimum returns 9000019 and one above the daily cap returns 9000021. Ask your account manager for your limits.
addressstringRequiredYour own checked TRON address for a USDT TRC20 payout. The example is a placeholder and will be rejected unchanged.
maxLength 64
address_acknowledgedbooleanRequiredMust be true — you confirm the destination address is correct and irreversible.

Request body · Example

{
  "amount": "250.00",
  "address": "REPLACE_WITH_YOUR_TRON_ADDRESS",
  "address_acknowledged": true
}

Response · 201

Withdrawal requested. Balance is held; the on-chain send is performed manually. With a sandbox key the simulated result is returned (environment sandbox); an idempotent replay also returns 201.

Withdrawal

FieldTypeRequiredDescription
idstringRequiredWithdrawal request identifier (UUID).
statusstringRequiredWithdrawal lifecycle status: requested → sent or rejected. The on-chain send is performed manually by the platform operator. With a sandbox key the status is final at once: sent (default) or rejected.
requestedsentrejected
amountstringRequiredAmount requested and held from the API wallet, in the platform base currency, as a decimal string with 2 fraction digits; it is not a USDT amount.
currencystringRequiredBase currency the amount is expressed in.
assetstringRequiredPayout asset (USDT).
networkstringRequiredPayout network (TRC20).
addressstringRequiredDestination address you provided.
usdt_amountstringRequiredUSDT amount calculated when the request is accepted, as a fixed-scale decimal string with 6 fraction digits. This field alone does not confirm a chain transfer.
tx_hashstring | nullRequiredOn-chain transaction hash, filled after the send. In sandbox a synthetic 64-character hash is returned for a sent withdrawal; no chain transfer takes place.
rejection_reasonstring | nullRequiredReason, filled if rejected. In sandbox a rejected withdrawal carries Sandbox scenario: rejected.
requested_atstring · date-timeRequiredRequest time (UTC).
processed_atstring · date-time | nullRequiredWhen it was sent or rejected (UTC).
created_atstring · date-timeRequiredRecord creation time (UTC).
environmentstringRequiredEnvironment of the withdrawal (the environment of the signing key).
livesandbox

Response · Example

{
  "id": "7F0C2A94-3B1E-4D58-9A6F-1C2D3E4F5A6B",
  "status": "requested",
  "amount": "250.00",
  "currency": "USD",
  "asset": "USDT",
  "network": "TRC20",
  "address": "REPLACE_WITH_YOUR_TRON_ADDRESS",
  "usdt_amount": "249.000000",
  "tx_hash": null,
  "rejection_reason": null,
  "requested_at": "2026-09-26T09:30:00.000Z",
  "processed_at": null,
  "created_at": "2026-09-26T09:30:00.000Z",
  "environment": "live"
}

Possible errors

GET/api/v3/withdrawals

List withdrawals

Parameters

FieldTypeRequiredDescription
pageinteger · queryOptionalPage number.
minimum 1
per_pageinteger · queryOptionalItems per page.
minimum 1maximum 100
statusstring · queryOptionalFilter by status.
requestedsentrejected

Response · 200

Paginated withdrawals.

FieldTypeDescription
dataWithdrawal[]
metaPaginationMeta

Response · Example

{
  "data": [
    {
      "id": "7F0C2A94-3B1E-4D58-9A6F-1C2D3E4F5A6B",
      "status": "requested",
      "amount": "250.00",
      "currency": "USD",
      "asset": "USDT",
      "network": "TRC20",
      "address": "REPLACE_WITH_YOUR_TRON_ADDRESS",
      "usdt_amount": "249.000000",
      "tx_hash": null,
      "rejection_reason": null,
      "requested_at": "2026-09-26T09:30:00.000Z",
      "processed_at": null,
      "created_at": "2026-09-26T09:30:00.000Z",
      "environment": "live"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Possible errors

GET/api/v3/withdrawals/{id}

Get withdrawal status

Parameters

FieldTypeRequiredDescription
idstring · uuid · pathRequiredThe withdrawal id.

Response · 200

The withdrawal.

Object: Withdrawal (fields are listed under Request a USDT withdrawal).

Response · Example

{
  "id": "7F0C2A94-3B1E-4D58-9A6F-1C2D3E4F5A6B",
  "status": "requested",
  "amount": "250.00",
  "currency": "USD",
  "asset": "USDT",
  "network": "TRC20",
  "address": "REPLACE_WITH_YOUR_TRON_ADDRESS",
  "usdt_amount": "249.000000",
  "tx_hash": null,
  "rejection_reason": null,
  "requested_at": "2026-09-26T09:30:00.000Z",
  "processed_at": null,
  "created_at": "2026-09-26T09:30:00.000Z",
  "environment": "live"
}

Possible errors

Disputes

List chargebacks and submit your evidence.

Disputes come from the card networks, so in sandbox you create a test dispute yourself with POST /api/v3/sandbox/disputes. See Testing account operations.

Manuell records a dispute when the bank notifies it. The disputed amount is deducted from your balance (the balance can go negative and can_withdraw becomes false) and is restored if you win. Send your evidence before evidence_due_at; a new Idempotency-Key replaces your earlier note while the dispute is open.

GET/api/v3/disputes

List disputes

Parameters

FieldTypeRequiredDescription
pageinteger · queryOptionalPage number.
minimum 1
per_pageinteger · queryOptionalItems per page.
minimum 1maximum 100
statusstring · queryOptionalFilter by status.
openunder_reviewwonlost

Response · 200

Paginated disputes.

FieldTypeDescription
dataDispute[]
metaPaginationMeta

Dispute

FieldTypeRequiredDescription
idstringRequiredDispute identifier (UUID).
servicestringRequiredService the disputed payment belongs to: api for a payment created through this API, link for a payment link.
amountstringRequiredDisputed amount (decimal string).
currencystringRequiredCurrency of the dispute.
statusstringRequiredDispute status.
openunder_reviewwonlost
reasonstringRequiredChargeback reason category.
fraudunauthorizedproduct_not_deliveredduplicateamount_mismatchother
reason_notestring | nullRequiredBank reason note, verbatim.
occurred_onstring · dateRequiredDate the chargeback was raised (YYYY-MM-DD).
evidence_due_atstring · date-time | nullRequiredDeadline to submit evidence (UTC). A sandbox dispute stays open for evidence for 7 days after creation.
evidence_submitted_atstring · date-time | nullRequiredWhen the platform submitted the defense to the bank.
merchant_evidence_notestring | nullRequiredThe note you submitted.
merchant_evidence_submitted_atstring · date-time | nullRequiredWhen you submitted your note.
resolved_atstring · date-time | nullRequiredWhen the dispute closed.
created_atstring · date-timeRequiredRecord creation time (UTC).
payment_codestring | nullRequiredCode of the API payment the dispute belongs to (the code returned when the payment was created); null when the dispute is not linked to an API payment.
environmentstringRequiredEnvironment of the dispute (the environment of the signing key).
livesandbox

Response · Example

{
  "data": [
    {
      "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
      "service": "api",
      "amount": "250.00",
      "currency": "USD",
      "status": "open",
      "reason": "fraud",
      "reason_note": "string",
      "occurred_on": "2026-09-26",
      "evidence_due_at": "2026-09-26T09:00:00.000Z",
      "evidence_submitted_at": "2026-09-26T09:00:00.000Z",
      "merchant_evidence_note": "string",
      "merchant_evidence_submitted_at": "2026-09-26T09:00:00.000Z",
      "resolved_at": "2026-09-26T09:00:00.000Z",
      "created_at": "2026-09-26T09:00:00.000Z",
      "payment_code": "ab34cdef",
      "environment": "live"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Possible errors

GET/api/v3/disputes/{id}

Get a dispute

Parameters

FieldTypeRequiredDescription
idstring · uuid · pathRequiredThe dispute id.

Response · 200

The dispute.

Object: Dispute (fields are listed under List disputes).

Response · Example

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "service": "api",
  "amount": "250.00",
  "currency": "USD",
  "status": "open",
  "reason": "fraud",
  "reason_note": "string",
  "occurred_on": "2026-09-26",
  "evidence_due_at": "2026-09-26T09:00:00.000Z",
  "evidence_submitted_at": "2026-09-26T09:00:00.000Z",
  "merchant_evidence_note": "string",
  "merchant_evidence_submitted_at": "2026-09-26T09:00:00.000Z",
  "resolved_at": "2026-09-26T09:00:00.000Z",
  "created_at": "2026-09-26T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "live"
}

Possible errors

POST/api/v3/disputes/{id}/evidenceIdempotency-Key required

Submit dispute evidence

Parameters

FieldTypeRequiredDescription
idstring · uuid · pathRequiredThe dispute id.

Request body

FieldTypeRequiredDescription
notestringRequiredYour evidence text for the dispute.
minLength 3maxLength 4000

Request body · Example

{
  "note": "Order 4821 was delivered on 2026-09-25. Carrier reference ABC123."
}

Response · 200

Evidence recorded; the dispute status does not change. An identical idempotent replay returns the original response body.

Object: Dispute (fields are listed under List disputes).

Response · Example

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "service": "api",
  "amount": "250.00",
  "currency": "USD",
  "status": "open",
  "reason": "fraud",
  "reason_note": "string",
  "occurred_on": "2026-09-26",
  "evidence_due_at": "2026-09-26T09:00:00.000Z",
  "evidence_submitted_at": "2026-09-26T09:00:00.000Z",
  "merchant_evidence_note": "string",
  "merchant_evidence_submitted_at": "2026-09-26T09:00:00.000Z",
  "resolved_at": "2026-09-26T09:00:00.000Z",
  "created_at": "2026-09-26T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "live"
}

Possible errors

Manage deliveries

Inspect webhook deliveries and retry failed ones.

The address that receives notifications is set per environment on “API Key & Integration”. The endpoints below list deliveries and requeue failed ones.

GET/api/v3/webhooks/deliveries

List webhook deliveries

Parameters

FieldTypeRequiredDescription
pageinteger · queryOptionalPage number.
minimum 1
per_pageinteger · queryOptionalItems per page.
minimum 1maximum 100
statusstring · queryOptionalFilter by status.
pendingdeliveredfailed

Response · 200

Paginated deliveries.

FieldTypeDescription
dataWebhookDelivery[]
metaPaginationMeta

WebhookDelivery

FieldTypeDescription
idstringDelivery identifier (UUID).
eventstringEvent type of the delivery: payment.paid, payment.refunded or payment.failed. A failed attempt is non-terminal; its payment remains created and may later be paid.
statusstringDelivery status.
pendingdeliveredfailed
payment_codestring | nullRelated payment code, if any.
attempt_countintegerNumber of delivery attempts so far.
last_status_codeinteger | nullHTTP status of the last attempt.
last_errorstring | nullLegacy raw delivery error; use last_error_code and last_error_message.
last_error_codestring | nullStable machine-readable delivery error code.
invalid_webhook_targetwebhook_target_private_networkwebhook_environment_invalidwebhook_signing_unavailablewebhook_response_unsuccessfulwebhook_egress_proxy_unreachablewebhook_unreachablewebhook_delivery_failed
last_error_messagestring | nullShort human-readable delivery error selected from Accept-Language.
next_attempt_atstring · date-time | nullWhen the next retry is scheduled (UTC).
delivered_atstring · date-time | nullWhen it was delivered (UTC).
created_atstring · date-timeRecord creation time (UTC).

Response · Example

{
  "data": [
    {
      "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
      "event": "payment.paid",
      "status": "pending",
      "payment_code": null,
      "attempt_count": 1,
      "last_status_code": null,
      "last_error": null,
      "last_error_code": null,
      "last_error_message": null,
      "next_attempt_at": null,
      "delivered_at": null,
      "created_at": "2026-09-26T09:00:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Possible errors

GET/api/v3/webhooks/deliveries/{id}

Get webhook delivery

Parameters

FieldTypeRequiredDescription
idstring · uuid · pathRequiredThe delivery id.

Response · 200

The delivery, including url and payload.

WebhookDeliveryDetail

FieldTypeDescription
idstringDelivery identifier (UUID).
eventstringEvent type of the delivery: payment.paid, payment.refunded or payment.failed. A failed attempt is non-terminal; its payment remains created and may later be paid.
statusstringDelivery status.
pendingdeliveredfailed
payment_codestring | nullRelated payment code, if any.
attempt_countintegerNumber of delivery attempts so far.
last_status_codeinteger | nullHTTP status of the last attempt.
last_errorstring | nullLegacy raw delivery error; use last_error_code and last_error_message.
last_error_codestring | nullStable machine-readable delivery error code.
invalid_webhook_targetwebhook_target_private_networkwebhook_environment_invalidwebhook_signing_unavailablewebhook_response_unsuccessfulwebhook_egress_proxy_unreachablewebhook_unreachablewebhook_delivery_failed
last_error_messagestring | nullShort human-readable delivery error selected from Accept-Language.
next_attempt_atstring · date-time | nullWhen the next retry is scheduled (UTC).
delivered_atstring · date-time | nullWhen it was delivered (UTC).
created_atstring · date-timeRecord creation time (UTC).
urlstringYour webhook URL for this delivery.
payloadobject | nullThe JSON body that was sent.

Response · Example

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "event": "payment.paid",
  "status": "pending",
  "payment_code": null,
  "attempt_count": 1,
  "last_status_code": null,
  "last_error": null,
  "last_error_code": null,
  "last_error_message": null,
  "next_attempt_at": null,
  "delivered_at": null,
  "created_at": "2026-09-26T09:00:00.000Z",
  "url": "string",
  "payload": null
}

Possible errors

POST/api/v3/webhooks/deliveries/{id}/retryIdempotency-Key required

Retry a failed delivery

Parameters

FieldTypeRequiredDescription
idstring · uuid · pathRequiredThe delivery id.

Response · 200

Failed delivery requeued. An identical idempotent replay returns the original queued response without another retry.

Object: WebhookDeliveryDetail (fields are listed under Get webhook delivery).

Response · Example

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "event": "payment.paid",
  "status": "pending",
  "payment_code": null,
  "attempt_count": 1,
  "last_status_code": null,
  "last_error": null,
  "last_error_code": null,
  "last_error_message": null,
  "next_attempt_at": null,
  "delivered_at": null,
  "created_at": "2026-09-26T09:00:00.000Z",
  "url": "string",
  "payload": null
}

Possible errors

Delivery errors

last_error is a legacy field; use last_error_code in new integrations.

FieldDescription
invalid_webhook_targetThe webhook target is invalid.
webhook_target_private_networkThe webhook target resolves to a private network.
webhook_environment_invalidThe webhook environment is invalid.
webhook_signing_unavailableThe webhook could not be signed.
webhook_response_unsuccessfulThe target returned a non-2xx response.
webhook_egress_proxy_unreachableThe delivery egress proxy is unreachable.
webhook_unreachableThe webhook target is unreachable.
webhook_delivery_failedThe webhook delivery failed.

Service status and maintenance

Some services can be put under maintenance temporarily. Only new work is affected; this section shows what stops, what keeps working and how to check the status.

GET/api/v3/service-statusPublic

Get service status

Response · 200

Services under maintenance (the list can be empty).

FieldTypeRequiredDescription
dataServiceStatusItem[]RequiredServices that are under maintenance right now; an empty list means none is.

ServiceStatusItem

FieldTypeRequiredDescription
servicestringRequiredService code: api_collection (payments created through the API and their payment pages), withdrawals (withdrawal requests), or one of link_collection, storefront, usdt_sales and balance_load (other services of the platform).
api_collectionlink_collectionwithdrawalsstorefrontusdt_salesbalance_load
untilstring · date-time | nullRequiredEstimated return time (UTC, ISO-8601), or null. It is only an estimate: maintenance does not end by itself, and once the time has passed the field is null.
notestring | nullRequiredShort plain-text message from the platform operator, or null.
maxLength 240

Response · Example

{
  "data": [
    {
      "service": "api_collection",
      "until": "2026-10-01T12:00:00Z",
      "note": "Planned maintenance."
    }
  ]
}

Other responses

  • 429Request limit exceeded.

Possible errors

Pagination

List endpoints accept page (default 1) and per_page (default 20, maximum 100) and return data and meta.

PaginationMeta

FieldTypeRequiredDescription
pageintegerRequired1-based page number.
per_pageintegerRequiredItems per page (1–100).
totalintegerRequiredTotal matching records.
total_pagesintegerRequiredceil(total / per_page).

Testing account operations

Balance, refunds, withdrawals and disputes work in sandbox with the same endpoints, bodies and error codes as in live.

  • Sandbox payments move to available_amount at once, without waiting for a value date.
  • Refund and withdrawal requests are finalized immediately. The X-CAV-Sandbox-Scenario header selects the outcome.
  • Disputes come from the bank, so in sandbox you create one with POST /api/v3/sandbox/disputes.

Review refund, withdrawal and dispute tests in “Sandbox operations”.

Choosing the outcome

Refund and withdrawal requests use the same endpoints and bodies as live. To choose the outcome, add the optional X-CAV-Sandbox-Scenario header. It is not part of the signature. On a live key the header is rejected with 422 (1000001) so that a test can never become a real request.

X-CAV-Sandbox-Scenario

X-CAV-Sandbox-Scenario: rejected
EndpointHeader valuesDefaultEffect
POST /api/v3/refundscompleted rejectedcompletedcompleted finalizes the refund and debits the virtual balance; rejected records the rejection and changes nothing.
POST /api/v3/withdrawalssent rejectedsentsent debits the virtual balance and fills tx_hash with a placeholder value; rejected releases the amount.
POST /api/v3/sandbox/disputesopen won lostopenSet in the request body, not in a header. open, won or lost.

Test dispute

Disputes come from the card networks and cannot be started from your side in live. This is the only sandbox-only endpoint: it creates a test dispute for a paid sandbox payment and returns the same Dispute object as live.

POST/api/v3/sandbox/disputesIdempotency-Key required

Create a sandbox dispute for a paid sandbox payment

Request body

FieldTypeRequiredDescription
payment_codestringRequiredReplace with the code of a paid payment created with your own sandbox key.
maxLength 16
scenariostringOptionalOutcome to record: open (default) stays open for evidence; won and lost are already resolved.
openwonlost
reasonstringRequiredDispute reason category; the same values as Dispute.reason.
fraudunauthorizedproduct_not_deliveredduplicateamount_mismatchother

Request body · Example

{
  "payment_code": "ab34cdef",
  "scenario": "open",
  "reason": "fraud"
}

Response · 201

Dispute recorded; an idempotent replay returns the same dispute.

Object: Dispute (fields are listed under List disputes).

Response · Example

{
  "id": "B5D4E456-EFC1-4EC2-A613-D64A16E45BD5",
  "service": "api",
  "amount": "250.00",
  "currency": "USD",
  "status": "open",
  "reason": "fraud",
  "reason_note": null,
  "occurred_on": "2026-09-30",
  "evidence_due_at": "2026-10-07T09:00:00.000Z",
  "evidence_submitted_at": null,
  "merchant_evidence_note": null,
  "merchant_evidence_submitted_at": null,
  "resolved_at": null,
  "created_at": "2026-09-30T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "sandbox"
}

Possible errors

Talk to your account manager about the live terminal and the final end-to-end test. Contact