Z Zise Developers 简体中文

On-chain payout failed: return the full amount to available balance

POST /v1/withdrawals/{id}/fail scope: withdrawals:write
Merchant account Requires x-idempotency-key Moves funds · Clears the member's corresponding withdrawing amount and returns it to available balance.
This endpoint moves funds

See the response table below for failure handling. Retry timeouts (504) with the same idempotency key — we may already have processed the request; use a new key after a business failure; the same key replays that failure.

Clears the corresponding withdrawing amount and returns the same amount to available. merchant.custody has remained unchanged throughout, because you have held the money the entire time.

Call as the merchant; no x-on-behalf-of is required.

⚠ Call only after the on-chain transaction has definitely failed. Sent but outcome unknown is not a state managed on our side, since we did not initiate the chain transaction. This endpoint therefore has no unknown state. Calling fail while the outcome is unknown would return funds to the member that may already have been sent. Leave the order unchanged while investigating the chain.

Repeat and concurrent calls follow the same rules as confirm: already failed returns 200 + replayed: true; already settled returns 400 order_not_cancellable.

Prerequisites

  • The order is currently locked.
  • The on-chain transaction has definitely failed, rather than having an unknown outcome.

Path Parameters

FieldTypeRequiredDescription
id string Required Withdrawal order ID, with or without the wdr_ prefix.
FieldTypeRequiredDescription
x-idempotency-key string Required UUID。

Response

200Returned; replayed: true means no new posting occurred on this call.
{
  "id": "wdr_9f1c0b2a-4d33-4a51-9f2e-7c1b0a5d6e88",
  "status": "failed",
  "replayed": false
}
400order_not_cancellable: the order has moved to another state, usually settled.
404not_found: nonexistent or belonging to another merchant.
409idempotency_key_reused · idempotency_in_progress
Request
curl -X POST 'https://api.zinfra.vip/v1/withdrawals/{id}/fail' \
  -H 'x-auth-token: Bearer $TOKEN' \
  -H 'x-idempotency-key: $IDEMPOTENCY_KEY'
const res = await fetch("https://api.zinfra.vip/v1/withdrawals/{id}/fail", {
  method: "POST",
  headers: {
    "x-auth-token": "Bearer $TOKEN",
    "x-idempotency-key": "$IDEMPOTENCY_KEY",
  },
});
// Keep monetary amounts as strings, never numbers.
const data = await res.json();
import requests

res = requests.post(
    "https://api.zinfra.vip/v1/withdrawals/{id}/fail",
    headers={
        "x-auth-token": "Bearer $TOKEN",
        "x-idempotency-key": "$IDEMPOTENCY_KEY",
    },
)
# Use Decimal(str(...)) for amounts, not float.
data = res.json()
req, _ := http.NewRequest("POST", "https://api.zinfra.vip/v1/withdrawals/{id}/fail",
    nil)
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-idempotency-key", "$IDEMPOTENCY_KEY")
res, err := http.DefaultClient.Do(req)
// Decode amount fields as string, not float64.
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.zinfra.vip/v1/withdrawals/{id}/fail"))
    .header("x-auth-token", "Bearer $TOKEN")
    .header("x-idempotency-key", "$IDEMPOTENCY_KEY")
    .method("POST", HttpRequest.BodyPublishers.noBody())
    .build();
// Use String / BigDecimal for amounts, not double.
$ch = curl_init('https://api.zinfra.vip/v1/withdrawals/{id}/fail');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'x-auth-token: Bearer $TOKEN',
    'x-idempotency-key: $IDEMPOTENCY_KEY',
  ],
]);
$res = curl_exec($ch);
// Use bcmath / strings for amounts, not floatval.
200
{
  "id": "wdr_9f1c0b2a-4d33-4a51-9f2e-7c1b0a5d6e88",
  "status": "failed",
  "replayed": false
}