Single API Call Payouts API Integration Guide

Context

The Single API Call Payouts API lets platforms initiate a compliant stablecoin (or crypto) payout in a single API call. Rather than making four sequential calls to onboard participants, link an external account, and submit a payment, POST /payouts handles all of this in one request.

Participant Roles

RoleDescriptionSupported typesExample participant_code
PlatformThe zerohash partner submitting the API request. Must have a signed MSA contract with zerohash.n/aPLAT01
PayorThe entity or individual submitting payouts on behalf of the Ultimate Payor. Pre-registered via POST /participants/entity/new with zerohash and referenced by participant_code on every request.entity, individualPAYOR1
Ultimate PayorThe entity or individual whose funds are being sent. zerohash creates and manages this participant internally.entity, individualUPAYR1
BeneficiaryThe entity or individual receiving the payout. zerohash creates and manages this participant internally.entity, individualBENEF1

Account Models

The account_model field controls how participants are treated from a regulatory and compliance perspective. Your zerohash account must be configured for a given account model before it can be used.

ModelDescription
fully_disclosedThe Ultimate Payor is a legal zerohash customer, signs zerohash T&Cs, and is subject to KYB/KYC. The Payor does not put this activity within their own licenses.
omnibusThe Payor is a licensed money service business that puts this activity within their own licenses and is the legal zerohash customer. The Ultimate Payor is not a direct zerohash customer.


Pass the account model on every POST /payouts request:

{
  "account_model": "fully_disclosed",
  ...
}

Fund Float Account

You will fund their float account by sending fiat to the mutually decided-upon bank account. Here are the account details:

  • participant_code: 00SCXM

  • account_group: PLAT01 (replace with your Platform's code)

  • account_label: general

  • account_type: available

  • asset: USD

ℹ️

In Cert, your platform will be pre-funded with Float account funds.

Onboard Payor

⚠️

Approval Required

The Payor PII requirements reflected below require prior approval for your integration. Contact your zerohash representative to begin the review process.

Use the POST /participants/entity/new endpoint to pre-register the Payor.

Note: you must supply a value of originator_entity for onboarding_profile

Request Example:

{
  "onboarding_profile": "originator_entity",
  "legal_name": "Bank Corp.",
  "contact_number": "15553765431",
  "tax_id": "76-5432109",
  "id_issuing_authority": "US",
  "address_one": "2000 McKinney Avenue",
  "address_two": "Suite 1400",
  "city": "Dallas",
  "postal_code": "75201",
  "jurisdiction_code": "US-TX",
  "sanction_screening": "pass",
  "sanction_screening_timestamp": 1718000520000,
  "signed_agreements": [
    {
      "type": "user_agreement",
      "region": "us",
      "signed_timestamp": 1718000520000
    }
  ]
}

Note: The postal_code field is conditionally required; if the provided jurisdiction_code = US-XX , postal_code is required. Else, it is optional.

Validate Payout Request

Before submitting a live payout via POST /payouts, you can validate your request payload without executing any actions on the backend. Set "validate": true in the request body.
zerohash performs three checks:

  • Schema validation - all required fields are present and correctly formatted
  • Business logic validation - account model permissibility, required agreements, and other rules
  • Address validation - the destination crypto address is not on zerohash's deny-list and is compatible with the specified blockchain network (e.g., a BTC address for a SOL payout is rejected)

The idempotency key may be omitted when validating.

Request:

{
  "account_model": "fully_disclosed",
  "validate": true,
  "payor": {
    "participant_code": "PAYOR1",
    "payor": {
      "info": {
        "entity": {
          "onboarding_profile": "payouts_payor_ultimate",
          "legal_name": "Acme Corp",
          "contact_number": "15553765432",
          "address_one": "1 Main St.",
          "address_two": "Suite 1000",
          "city": "Chicago",
          "postal_code": "12345",
          "jurisdiction_code": "US-IL",
          "email": "[email protected]",
          "tax_id": "883987654",
          "id_issuing_authority": "US",
          "merchant_category_code": "4511",
          "sanction_screening": "pass",
          "sanction_screening_timestamp": 1603378501286,
          "signed_agreements": [
            {
              "type": "user_agreement",
              "region": "us",
              "signed_timestamp": 1603378501286
            }
          ]
        }
      }
    }
  },
  "beneficiary": {
    "info": {
      "individual": {
        "onboarding_profile": "payouts_beneficiary",
        "first_name": "Jane",
        "last_name": "Smith",
        "date_of_birth": "1990-01-01",
        "address_one": "123 Main St",
        "address_two": "Apt 4B",
        "city": "New York",
        "zip": "10001",
        "jurisdiction_code": "US-NY",
        "tax_id": "123456789",
        "id_issuing_authority": "US"
      }
    },
    "external_account": {
      "info": {
        "network": "SOL",
        "crypto_address": "ab123...",
        "supported_symbols": ["USDC"]
      }
    }
  },
  "payment": {
    "asset": "USDC.SOL",
    "quoted_asset": "USD",
    "total": "100.00",
    "description": "Contractor payout"
  },
  "metadata": {
    "client_ref": "your-internal-ref-id",
    "campaign": "weekly-contractor-payout"
  }
}

Note: The postal_code field in the payor and beneficiary object is conditionally required; if the provided jurisdiction_code = US-XX , postal_code is required. Else, it is optional.

Responses:

StatusMeaning
200 {}All validations passed. Your live request will succeed.
400One or more validations failed. See errors array for details.
// 400 — schema validation failure
{
  "errors": ["zip format is not valid"]
}

// 400 — unexpected field
{
  "errors": ["unexpected field: network_fee_notional"]
}

Initiate Payout - New Participants

Use this pattern when submitting a payout for participants that have not been previously onboarded with zerohash. Provide full PII inline for the Ultimate Payor and Beneficiary. zerohash creates the corresponding participant_code values automatically.

For now - only entity types are supported for the Ultimate Payor. For the Beneficiary, both entity and individual are currently supported

Request - Individual Beneficiary:

{
  "account_model": "fully_disclosed",
  "payor": {
    "participant_code": "PAYOR1",
    "payor": {
      "info": {
        "entity": {
         "onboarding_profile": "payouts_payor_ultimate",
          "legal_name": "Acme Corp",
          "contact_number": "15553765432",
          "address_one": "1 Main St.",
          "address_two": "Suite 1000",
          "city": "Chicago",
          "postal_code": "12345",
          "jurisdiction_code": "US-IL",
          "email": "[email protected]",
          "tax_id": "883987654",
          "id_issuing_authority": "US",
          "merchant_category_code": "4511",
          "sanction_screening": "pass",
          "sanction_screening_timestamp": 1603378501286,
          "signed_agreements": [
            {
              "type": "user_agreement",
              "region": "us",
              "signed_timestamp": 1603378501286
            }
          ]
        }
      }
    }
  },
  "beneficiary": {
    "info": {
      "individual": {
        "onboarding_profile": "payouts_beneficiary",
        "first_name": "Jane",
        "last_name": "Smith",
        "date_of_birth": "1990-01-01",
        "address_one": "123 Main St",
        "address_two": "Apt 4B",
        "city": "New York",
        "zip": "10001",
        "jurisdiction_code": "US-NY",
        "tax_id": "123456789",
        "id_issuing_authority": "US"
      }
    },
    "external_account": {
      "info": {
        "network": "SOL",
        "crypto_address": "ab123...",
        "supported_symbols": ["USDC"]
      }
    }
  },
  "payment": {
    "asset": "USDC.SOL",
    "quoted_asset": "USD",
    "total": "100.00",
    "description": "Contractor payout"
  },
  "metadata": {
    "client_ref": "your-internal-ref-id",
    "campaign": "weekly-contractor-payout"
  }
}

Notes:

  • For the Beneficiary object, the API will respect the following as it relates to the tax_id, id_number_type and id_number fields:
    • If id_issuing_authority = US or PR, then either the tax_id is required OR the id_number_type and the id_number is required
      • the tax_id value may an SSN or ITIN (both are expected to be 9 digits)
    • If id_issuing_authority is not US or PR, then the tax_id is expected to be omitted. And then the API will expect a value for both id_number_type and id_number

Request Entity Beneficiary:

{
  "account_model": "fully_disclosed",
  "payor": {
    "participant_code": "PAYOR1",
    "payor": {
      "info": {
        "entity": {
         "onboarding_profile": "payouts_payor_ultimate",
          "legal_name": "Acme Corp",
          "contact_number": "15553765432",
          "address_one": "1 Main St.",
          "address_two": "Suite 1000",
          "city": "Chicago",
          "postal_code": "12345",
          "jurisdiction_code": "US-IL",
          "email": "[email protected]",
          "tax_id": "883987654",
          "id_issuing_authority": "US",
          "sanction_screening": "pass",
          "sanction_screening_timestamp": 1603378501286,
          "signed_agreements": [
            {
              "type": "user_agreement",
              "region": "us",
              "signed_timestamp": 1603378501286
            }
          ]
        }
      }
    }
  },
  "beneficiary": {
    "info": {
      "entity": {
        "onboarding_profile": "payouts_beneficiary",
        "legal_name": "Contractor LLC",
        "contact_number": "15553765432",
        "address_one": "456 Oak Ave",
        "address_two": "",
        "city": "Austin",
        "postal_code": "73301",
        "jurisdiction_code": "US-TX",
        "tax_id": "123456789",
        "id_issuing_authority": "US",
        "email": "[email protected]"
      }
    },
    "external_account": {
      "info": {
        "network": "SOL",
        "crypto_address": "cd456...",
        "supported_symbols": ["USDC"]
      }
    }
  },
  "payment": {
    "asset": "USDC.SOL",
    "quoted_asset": "USD",
    "total": "500.00",
    "description": "Invoice payment"
  },
  "metadata": {
    "client_ref": "your-internal-ref-id"
  }
}

Response:

// 202
{
  "idempotency_key": "your-idempotency-key",
  "payout_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "status": "pending"
}

Initiate Payout - Existing Participants

If the Ultimate Payor, Beneficiary, and/or external account have already been onboarded in a previous payout, you can reference them by ID instead of re-submitting full PII. Mix and match - any combination of inline PII and reference IDs is supported.

ObjectReference Field
Ultimate Payorpayor.payor.participant_code
Beneficiarybeneficiary.participant_code
Beneficiary external accountbeneficiary.external_account.external_account_id

Request:

{
  "account_model": "fully_disclosed",
  "payor": {
    "participant_code": "PAYOR1",
    "payor": {
      "participant_code": "UPAYOR1"
    }
  },
  "beneficiary": {
    "participant_code": "BENEF1",
    "external_account": {
      "external_account_id": "ea_3b1d8e4a"
    }
  },
  "payment": {
    "asset": "USDC.SOL",
    "quoted_asset": "USD",
    "total": "100.00",
    "description": "Contractor payout"
  },
  "metadata": {
    "client_ref": "your-internal-ref-id",
    "campaign": "weekly-contractor-payout"
  }
}

Response:

// 202
{
  "idempotency_key": "your-idempotency-key",
  "payout_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "status": "pending"
}

Idempotency

POST /payouts is idempotent. Supply an Idempotency-Key header with each request.

  • Same key + same payload → zerohash returns the original response and does not initiate a duplicate payout.
  • Same key + different payload → zerohash returns 400.

The idempotency key is included on all webhook events, GET responses, and reports. You can also query by it directly: GET /payouts?idempotency-key=your-key.

Error Reference

StatusErrorCause
400should have required property 'platform_code'Missing platform_code
400should have required property 'entity_name'Missing entity_name
400<field> format is not validField fails schema format validation
400unexpected field: <field_name>Request body contains an unrecognized field
400idempotency key reused with different payloadSame key submitted with a different body
422asset is currently depegged and conversions are haltedPayout asset is depegged

Query Payout

You can query a Payout record via the GET /payouts endpoint.

Response:

{
  "payout_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "idempotency_key": "client-supplied-uuid",
  "status": "completed",
  "sub_status": "payment.settled",
  "previous_sub_status": "payment.posted",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "failure_reason": null,
  "resources": {
    "payor": {
      "participant_code": "PAYOR1",
      "payor": {
        "participant_code": "ORIG01",
        "status": "approved"
      }
    },
    "beneficiary": {
      "participant_code": "BENEF1",
      "status": "approved",
      "external_account": {
        "external_account_id": "ea_3b1d8e4a",
        "account_nickname": "Max's USDC wallet",
        "status": "approved",
        "details": {
          "network": "SOL",
          "supported_symbols": [
            "USDC"
          ],
          "crypto_address": "ab123...",
          "destination_tag": ""
        },
        "created_at": "2026-05-06T12:01:00Z",
        "updated_at": "2026-05-06T12:01:20Z"
      }
    },
    "payment": {
      "payment_id": "pmt_4c9d2e10",
      "network": "SOL",
      "asset": "USDC",
      "quoted_asset": "USD",
      "total": "100.00",
      "rate": "1.00",
      "destination_amount": "100.00",
      "status": "posted",
      "description": "Monthly payout",
      "payment_details": {
        "withdrawal_request_id": "wr_uuid_xyz",
        "trade_id": "tr_uuid_qrs",
        "on_chain_transaction_id": "0xabc123...",
        "network_fee_notional": "0.00",
        "network_fee_quantity": "0.00"
      },
      "created_at": "2026-05-06T12:01:30Z",
      "updated_at": "2026-05-06T12:01:45Z"
    }
  },
  "account_model": "fully_disclosed"
}

Webhooks

All payout lifecycle events use payload_type: payout.status_updated. After a successful POST /payouts events are emitted in the following sequence. The payout_id and idempotency_key are present on every event.

Event Sequence

#sub_statusPayout status
1null (initial)pending
2payor.payor.submittedpending
3payor.payor.approvedpending
3apayor.payor.rejectedrejected
4beneficiary.submittedpending
5beneficiary.approvedpending
5abeneficiary.pending_approvalpending
5bbeneficiary.rejectedrejected
6beneficiary.external_account.submittedpending
7beneficiary.external_account.approvedpending
7abeneficiary.external_account.rejectedrejected
8payment.submittedpending
9payment.postedpending
10payment.settledcompleted
10apayment.failedfailed

Event payloads

Payout pending (initial)

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": null,
  "previous_sub_status": null,
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": null } },
    "beneficiary": { "participant_code": null, "status": null, "external_account": { "external_account_id": null, "status": null } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Ultimate Payor submitted

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "payor.payor.submitted",
  "previous_sub_status": null,
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "submitted", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": null, "status": null, "external_account": { "external_account_id": null, "status": null } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Ultimate Payor approved

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "payor.payor.approved",
  "previous_sub_status": "payor.payor.submitted",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "approved", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": null, "status": null, "external_account": { "external_account_id": null, "status": null } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Ultimate Payor rejected

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "rejected",
  "sub_status": "payor.payor.rejected",
  "previous_sub_status": null,
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "rejected", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": null, "status": null, "external_account": { "external_account_id": null, "status": null } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Beneficiary submitted

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "beneficiary.submitted",
  "previous_sub_status": "payor.payor.approved",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "approved", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "submitted", "external_account": { "external_account_id": null, "status": null } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Beneficiary approved

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "beneficiary.approved",
  "previous_sub_status": "beneficiary.submitted",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "approved", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "approved", "external_account": { "external_account_id": null, "status": null } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Beneficiary pending approval

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "beneficiary.pending_approval",
  "previous_sub_status": "beneficiary.submitted",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "approved", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "pending_approval", "external_account": { "external_account_id": null, "status": null } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Beneficiary rejected

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "rejected",
  "sub_status": "beneficiary.rejected",
  "previous_sub_status": "beneficiary.pending_approval",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "approved", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "rejected", "external_account": { "external_account_id": null, "status": null } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Beneficiary external account submitted

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "beneficiary.external_account.submitted",
  "previous_sub_status": "beneficiary.approved",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "approved", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "approved", "external_account": { "external_account_id": "ea_xyz789", "status": "submitted" } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Beneficiary external account approved

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "beneficiary.external_account.approved",
  "previous_sub_status": "beneficiary.external_account.submitted",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "approved", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "approved", "external_account": { "external_account_id": "ea_xyz789", "status": "approved" } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Beneficiary external account rejected

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "rejected",
  "sub_status": "beneficiary.external_account.rejected",
  "previous_sub_status": "beneficiary.external_account.submitted",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "status": "approved", "participant_code": "UPAYOR1" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "approved", "external_account": { "external_account_id": "ea_xyz789", "status": "rejected" } },
    "payment": { "payment_id": null, "on_chain_transaction_id": null, "status": null, "rate": "1.00",
      "destination_amount": "100.00"}
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": null
}

Payment submitted

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "payment.submitted",
  "previous_sub_status": "beneficiary.external_account.approved",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "participant_code": "UPAYOR1", "status": "approved" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "approved", "external_account": { "external_account_id": "ea_xyz789", "status": "approved" } },
    "payment": {
      "payment_id": "pmt_abc123",
      "description": "Contractor payout",
      "asset": "USDC",
      "quoted_asset": "USD",
      "total": "100.00",
      "rate": "1.00",
      "destination_amount": "100.00",
      "status": "submitted",
      "network": "SOL",
      "payment_details": {
        "withdrawal_request_id": null,
        "trade_id": "tr_abc123",
        "on_chain_transaction_id": null,
        "network_fee_notional": null,
        "network_fee_quantity": null
      }
    }
  },
  "timestamp": "2026-05-06T12:06:00Z",
  "failure_reason": null
}

Payment posted

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "pending",
  "sub_status": "payment.posted",
  "previous_sub_status": "payment.submitted",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "participant_code": "UPAYOR1", "status": "approved" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "approved", "external_account": { "external_account_id": "ea_xyz789", "status": "approved" } },
    "payment": {
      "payment_id": "pmt_abc123",
      "description": "Contractor payout",
      "asset": "USDC",
      "quoted_asset": "USD",
      "total": "100.00",
      "rate": "1.00",
      "destination_amount": "100.00",
      "status": "posted",
      "network": "SOL",
      "payment_details": {
        "withdrawal_request_id": "wr_xyz456",
        "trade_id": "tr_abc123",
        "on_chain_transaction_id": null,
        "network_fee_notional": null,
        "network_fee_quantity": null
      }
    }
  },
  "timestamp": "2026-05-06T12:07:15Z",
  "failure_reason": null
}

Payment settled

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "completed",
  "sub_status": "payment.settled",
  "previous_sub_status": "payment.posted",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "participant_code": "UPAYOR1", "status": "approved" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "approved", "external_account": { "external_account_id": "ea_xyz789", "status": "approved" }},
    "payment": {
      "payment_id": "pmt_abc123",
      "description": "Contractor payout",
      "asset": "USDC",
      "quoted_asset": "USD",
      "total": "100.00",
      "rate": "1.00",
      "destination_amount": "100.00",
      "status": "settled",
      "network": "SOL",
      "payment_details": {
        "withdrawal_request_id": "wr_xyz456",
        "trade_id": "tr_abc123",
        "on_chain_transaction_id": "0xabc123...",
        "network_fee_notional": "0.01",
        "network_fee_quantity": "0.0000000384712"
      }
    }
  },
  "timestamp": "2026-05-06T12:08:45Z",
  "failure_reason": null
}

Payment failed

{
  "payout_id": "payout_abc123",
  "idempotency_key": "your-idempotency-key",
  "created_at": "2026-05-06T12:00:00Z",
  "updated_at": "2026-05-06T12:01:45Z",
  "status": "failed",
  "sub_status": "payment.failed",
  "previous_sub_status": "payment.posted",
  "resources": {
    "payor": { "participant_code": "PAYOR1", "payor": { "participant_code": "UPAYOR1", "status": "approved" } },
    "beneficiary": { "participant_code": "BENEF1", "status": "approved", "external_account": { "external_account_id": "ea_xyz789", "status": "approved" } },
    "payment": {
      "payment_id": "pmt_abc123",
      "on_chain_transaction_id": "0xabc123...",
      "status": "failed"
    }
  },
  "timestamp": "2026-05-06T12:01:30Z",
  "failure_reason": "on_chain_transaction_failed"
}

API error scenarios

EndpointHTTP StatusScenarioResponse
POST /payouts403Request carries no API key{"error": true, "message": "Missing API Key"}
POST /payouts403API key lacks the withdraw permissions required to post payouts{"error": true, "message": "This api key does not have the required withdraw permissions to post payouts."}
POST /payouts400Missing required body field{"errors": ["payor should have required property 'participant_code'"]}
POST /payouts400Missing required nested field (examples){"errors": ["payment should have required property 'asset'"]}
POST /payouts400Wrong field type{"errors": ["payment.total should be string"]}
POST /payouts400signed_timestamp not an integer{"errors": ["signed_timestamp should be integer"]}
POST /payouts400sanction_screening not in enum{"errors": ["sanction_screening should be equal to one of the allowed values"]}
POST /payouts400onboarding_profile not in allowed enum (UP entity){"errors": ["onboarding_profile should be equal to one of the allowed values"]}
POST /payouts400merchant_category_code not a 4-digit string{"errors": ["merchant_category_code should match pattern "^[0-9]{4}$""]}
POST /payouts400Unknown / extra field anywhere in body{"errors": ["should NOT have additional properties"]}
POST /payouts400validate flag wrong type{"errors": ["validate should be boolean"]}
POST /payouts400payor not exactly one of participant_code or info (both or neither){"errors": ["payor must specify exactly one of participant_code or info"]}
POST /payouts400beneficiary not exactly one of participant_code or info{"errors": ["beneficiary must specify exactly one of participant_code or info"]}
POST /payouts400beneficiary.info not exactly one of entity or individual{"errors": ["beneficiary.info must specify exactly one of entity or individual"]}
POST /payouts400external_account not exactly one of external_account_id or info{"errors": ["beneficiary.external_account must specify exactly one of external_account_id or info"]}
POST /payouts400External account not approvedExternal account not approved
POST /payouts400External account does not support the payment asset{"errors": ["external account does not support asset USDC"]}
POST /payouts400Platform not enrolled in payouts product{"errors": ["platform is not enrolled in payouts and cannot onboard payouts profiles"]}
POST /payouts400Entity legal_name missing{"errors": ["entity legal name must be supplied"]}
POST /payouts400Entity tax_id missing{"errors": ["tax_id is required for payouts entity applications"]}
POST /payouts400Entity tax_id not a valid US EIN (US jurisdiction){"errors": ["invalid us ein format"]}
POST /payouts400Entity id_issuing_authority missing{"errors": ["id_issuing_authority is required for payouts entity applications"]}
POST /payouts400Entity address_one missing{"errors": ["address_one is required for payouts entity applications"]}
POST /payouts400Address/city/zip format invalid (examples; PO Box, length, special chars, US zip){"errors": ["address_one should not be empty and should not contain PO Box"]}
POST /payouts400Entity jurisdiction_code missing{"errors": ["jurisdiction_code is required"]}
POST /payouts400sanction_screening status not explicitly defined / not PASSED / bad timestamp{"errors": ["sanction_screening status should be explicitly defined"]}
POST /payouts400Ultimate Payor entity email missing{"errors": ["email is required for payouts payor ultimate entity applications"]}
POST /payouts400merchant_category_code not a valid 4-digit Mastercard MCC{"errors": ["invalid merchant_category_code: must be a 4-digit Mastercard MCC"]}
POST /payouts400Individual beneficiary first_name missing{"errors": ["should have required property 'first_name'"]}
POST /payouts400Individual beneficiary last_name missing{"errors": ["last_name should NOT be shorter than 1 characters"]}
POST /payouts400Individual beneficiary date_of_birth missing{"errors": ["date_of_birth is required for payouts beneficiary applications"]}
POST /payouts400Individual beneficiary id_issuing_authority not ISO 3166-1 alpha-2{"errors": ["id_issuing_authority must be a valid ISO 3166-1 alpha-2 country code for payouts beneficiary applications"]}
POST /payouts400US beneficiary supplies neither tax_id nor id_number + id_number_type{"errors": [""exactly one of tax_id or id_number with id_number_type is required when id_issuing_authority is US for payouts beneficiary applications"]}
POST /payouts400US beneficiary tax_id not 9-digit SSN/ITIN{"errors": ["tax_id must be a 9-digit SSN or ITIN for payouts beneficiary applications"]}
POST /payouts400Non-US beneficiary supplied tax_id (not allowed){"errors": ["tax_id is not allowed when id_issuing_authority is not US for payouts beneficiary applications"]}
POST /payouts400Float/credit balance insufficient for payout{"errors": ["insufficient balance"]}
POST /payouts400Asset not supported (no asset / not payout-enabled / account symbol mismatch){"errors": ["asset is not supported"]}
POST /payouts400quoted_asset is not USD{"errors": ["invalid quoted asset"]}
POST /payouts400Resolved account not approved{"errors": ["account is not approved"]}
POST /payouts400Participant (payor) not approved (payments view){"errors": ["participant is not approved"]}
POST /payouts400Account not found (payments view){"errors": ["account not found"]}
POST /payouts400Inline crypto address invalid for network or on deny list{"errors": ["invalid or denied destination address"]}
POST /payouts400Inline crypto address is sanctioned{"errors": ["sanctioned address"]}
POST /payouts400Asset is currently depegged (orchestrator depeg gate){"errors": ["asset is currently depegged and conversions are halted"]}
POST /payouts400Orchestrator/downstream internal error (unmapped){"errors": ["internal server error"]}
GET /payouts403Request carries no API key{"error": true, "message": "Missing API Key"}
GET /payouts400Neither payout_id nor idempotency_key supplied{"errors": ["exactly one of payout_id or idempotency_key is required"]}
GET /payouts400Both payout_id and idempotency_key supplied{"errors": ["exactly one of payout_id or idempotency_key is required"]}
GET /payouts400payout_id not a valid UUID{"errors": ["payout_id should match format "uuid""]}
GET /payouts400Unknown / extra query field{"errors": ["should NOT have additional properties"]}
GET /payouts400Neither identifier (orchestrator guard){"errors": ["either payout_id or idempotency_key is required"]}
GET /payouts400Both identifiers (orchestrator guard){"errors": ["only one of payout_id or idempotency_key must be provided"]}
GET /payouts400payout_id invalid UUID (orchestrator guard){"errors": ["payout_id must be a valid UUID"]}
GET /payouts404payout_id does not exist{"errors": ["payout not found"]}
GET /payouts404idempotency_key does not exist{"errors": ["payout not found"]}
GET /payouts500Orchestrator/repository internal error{"errors": ["internal server error"]}