Z Zise Developers 简体中文

What this order requires from the user: reconfirmation / documents / nothing

GET /v1/remittances/{id}/pending-action scope: remittances:read
On behalf of a member · x-on-behalf-of required

Without this endpoint, you can only poll order details and guess. Reconfirmation has a 4-hour window, after which funds are automatically refunded. Otherwise the merchant may not realize an action was missed, and the user sees money unexpectedly returned.

action equal to null means no user action is currently required: normal processing, a terminal state, or an indeterminate action. null is not an error; do not display an exception.

Path Parameters

FieldTypeRequiredDescription
id string Required Order ID, with or without the rmt_ prefix.
FieldTypeRequiredDescription
x-on-behalf-of string Required Member on whose behalf the call is made.

Response

200action is non-null when action is required. Otherwise: {"id": "...", "waiting_on": "none"|"review", "action": null}. The example below is kind: "slippage"; a document request looks like this: `` { "id": "rmt_9c1f0a7e-3b2d-4f81-9a55-1d2e3f4a5b6c", "waiting_on": "member", "action": { "kind": "supplement", "round": 1, "status": "PENDING", "source": "upstream", "message": "Please provide proof of the source of funds.", "items": [ { "field_key": "proof_of_funds", "label": "Proof of source of funds", "type": "file", "required": true, "submitted": false } ], "submit_url": "https://api.zinfra.vip/remit/supplement/6f1c2b9d4a8e47f0b3d5c1a2e9f80b7c", "created_at": "2026-08-12T10:05:00Z", "submitted_at": "", "deadline": null } } ``
{
  "id": "rmt_9c1f0a7e-3b2d-4f81-9a55-1d2e3f4a5b6c",
  "waiting_on": "member",
  "action": {
    "kind": "slippage",
    "moved_bps": 137,
    "slippage_bps": 100,
    "old_total": "499.980000",
    "new_total": "512.340000",
    "extra_charge": "12.360000",
    "extra_locked": "12.483600",
    "available": "820.500000",
    "can_accept": true,
    "reject_reason": "",
    "deadline": "2026-08-12T13:30:00Z"
  }
}
404not_found: order not associated with this member or not owned by you.

Additional Details

Read waiting_on first, then action

action answers what the end user must do. Once documents are submitted and await our or the upstream’s review, action is always null, because asking for another upload would overwrite prior files. That otherwise looks identical to normal processing. waiting_on distinguishes them:

  • member: waiting for the end user; action is necessarily non-null.
  • review: documents submitted, awaiting our or upstream review. action is null; do not prompt the user. Render the review screen from the order detail’s supplement, which remains populated; source identifies whether we or the upstream are reviewing.
  • none: waiting for no human action.

⚠ This is not a second action contract: action remains the sole source of truth for what must be done. Do not infer document requirements or action branches from waiting_on. Branch on action.kind, which changes when a new action type is added, while this indicator does not.

For non-null action, branch on action.kind. There are currently two types. Existing shapes remain unchanged when new types are added. Use a switch, and expose unknown kinds unchanged instead of treating them as reconfirmation.

── kind: "slippage": awaiting acceptance of a new price ── Show old_total → new_total and the difference, extra_charge. Use deadline for the countdown. On user acceptance, send new_total unchanged to POST /v1/remittances/{id}/reconfirm.

── kind: "supplement": awaiting documents ── Fields are identical to the supplement block in GET /v1/remittances/{id}: round / status / source / message / items[] / submit_url / created_at / submitted_at. See that endpoint for their meaning. Give submit_url to the end user. We handle uploading, validation, status advancement, and upstream forwarding; you do not need to receive files.

⚠ deadline is always null for this type, deliberately. Reviews and document requests are not automatically cancelled on timeout. Compliance reviews and upstream RFIs can take days or weeks; a refund after 24 hours would let the system make a rejection decision on behalf of reviewers. Do not invent a countdown.

⚠ Only a round awaiting user submission appears here. After submission, supplement.status: SUBMITTED yields action: null + waiting_on: "review". The next action belongs to us or the upstream, not the user. Render the review screen from the order detail’s supplement, which remains populated during SUBMITTED. Do not ask users to re-upload during SUBMITTED: each upload overwrites the previous one, and the hosted page will tell them the round has already been processed.

When can_accept: false, do not show a confirmation button. Inspect reject_reason:

  • insufficient_balance: member funds cannot cover the additional hold; ask them to fund first.
  • too_many_rounds: no reconfirmation rounds remain; only cancellation or expiration is available.

⚠ extra_charge and extra_locked differ: the former is the additional charge; the latter is the additional hold including slippage reserve, so it is ≥ the former. Show the former to users; use the latter for balance sufficiency.

⚠ These prices reflect the upstream cost at the last dispatch, not a new quote. We do not query upstream to render this screen: quotes last only 75 seconds and would already be expired when seen, while every query is an upstream write with an idempotency key. This is decision context, not a promise. The actual execution price is determined at release and remains covered by the user’s original slippage ceiling.

Request
curl -X GET 'https://api.zinfra.vip/v1/remittances/{id}/pending-action' \
  -H 'x-auth-token: Bearer $TOKEN' \
  -H 'x-on-behalf-of: $MEMBER_ID'
const res = await fetch("https://api.zinfra.vip/v1/remittances/{id}/pending-action", {
  method: "GET",
  headers: {
    "x-auth-token": "Bearer $TOKEN",
    "x-on-behalf-of": "$MEMBER_ID",
  },
});
// Keep monetary amounts as strings, never numbers.
const data = await res.json();
import requests

res = requests.get(
    "https://api.zinfra.vip/v1/remittances/{id}/pending-action",
    headers={
        "x-auth-token": "Bearer $TOKEN",
        "x-on-behalf-of": "$MEMBER_ID",
    },
)
# Use Decimal(str(...)) for amounts, not float.
data = res.json()
req, _ := http.NewRequest("GET", "https://api.zinfra.vip/v1/remittances/{id}/pending-action",
    nil)
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-on-behalf-of", "$MEMBER_ID")
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/remittances/{id}/pending-action"))
    .header("x-auth-token", "Bearer $TOKEN")
    .header("x-on-behalf-of", "$MEMBER_ID")
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
// Use String / BigDecimal for amounts, not double.
$ch = curl_init('https://api.zinfra.vip/v1/remittances/{id}/pending-action');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'x-auth-token: Bearer $TOKEN',
    'x-on-behalf-of: $MEMBER_ID',
  ],
]);
$res = curl_exec($ch);
// Use bcmath / strings for amounts, not floatval.
200
{
  "id": "rmt_9c1f0a7e-3b2d-4f81-9a55-1d2e3f4a5b6c",
  "waiting_on": "member",
  "action": {
    "kind": "slippage",
    "moved_bps": 137,
    "slippage_bps": 100,
    "old_total": "499.980000",
    "new_total": "512.340000",
    "extra_charge": "12.360000",
    "extra_locked": "12.483600",
    "available": "820.500000",
    "can_accept": true,
    "reject_reason": "",
    "deadline": "2026-08-12T13:30:00Z"
  }
}