Withdraws (payouts)
POST /v1/withdraws
Section titled “POST /v1/withdraws”Requests a payout. Goes through the policy engine — the call returns immediately in all cases, it never blocks or long-polls, even when approval is required.
Requires header: Idempotency-Key
Request
Section titled “Request”curl -X POST https://sandbox-api.nuez.app/v1/withdraws \ -H "Authorization: Bearer <jwt>" \ -H "Idempotency-Key: inv-2026-04-001" \ -H "Content-Type: application/json" \ -d '{ "amount_ars": 5000, "destination": "0000003100010000123456", "destination_kind": "CBU", "note": "Invoice #42" }'Body parameters
Section titled “Body parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
amount_ars | number | ✓ | Amount in ARS |
destination | string | ✓ | CBU, CVU, or alias |
destination_kind | string | CBU | CVU | ALIAS. Default CBU. | |
note | string | Free-text note |
Response — executes immediately (201)
Section titled “Response — executes immediately (201)”{ "id": "b3f1...", "status": "submitted", "decision": "allow" }Response — approval required (202)
Section titled “Response — approval required (202)”{ "id": "b3f1...", "status": "pending_approval", "decision": "require_approval", "reasons": ["per_tx_limit"], "approval_id": "9a02...", "expires_in": 300}reasons names which policy rule(s) triggered — see Policy engine for the full list (kyc_incomplete, absolute_cap, per_tx_limit, daily_limit, monthly_limit).
Poll GET /v1/withdraws/{id} (below) to see when it resolves to approved/submitted/confirmed, rejected, or expired — or configure a webhook instead of polling.
Error codes
Section titled “Error codes”| HTTP | Code | Description |
|---|---|---|
400 | MISSING_IDEMPOTENCY_KEY | Idempotency-Key header absent |
400 | INVALID_JSON | Malformed body |
404 | USER_NOT_FOUND | Invalid user in token |
422 | ONBOARDING_INCOMPLETE | User has no CVU yet |
422 | PAYOUT_DENIED | Policy engine denied — e.g. kyc_incomplete or amount_invalid |
502 | WITHDRAW_FAILED | The bank rail rejected the payout when the decision was allow (e.g. insufficient balance) |
503 | APPROVAL_NOT_CONFIGURED | Decision was require_approval but no approval service is wired up |
GET /v1/withdraws/{id}
Section titled “GET /v1/withdraws/{id}”Retrieve a single payout attempt by ID.
curl https://sandbox-api.nuez.app/v1/withdraws/b3f1... \ -H "Authorization: Bearer <jwt>"Returns the full payout_attempts row — id, amount_ars, destination, destination_kind, status, decision, decision_reasons, idempotency_key, created_at, resolved_at, and (once submitted) provider_transfer_id.
status progresses through one of: approved → submitted → confirmed (allowed path), or pending_approval → approved/rejected/expired → submitted → confirmed (approval path), or failed on a downstream error.
GET /v1/withdraws
Section titled “GET /v1/withdraws”Lists all payout attempts for the authenticated user, most recent behavior determined by the store query (no pagination params currently).
curl https://sandbox-api.nuez.app/v1/withdraws \ -H "Authorization: Bearer <jwt>"{ "withdraws": [ /* same shape as GET /v1/withdraws/{id} */ ] }GET /v1/withdraws/{id}/receipt
Section titled “GET /v1/withdraws/{id}/receipt”Returns a rendered receipt for a payout — used by the WhatsApp/Telegram receipt links, and backed by the same underlying data as get_receipt in MCP. See MCP tools → get_receipt for the JSON shape.