API reference
Payouts
The payout endpoints, documented as defined. No payout method is available today.
| Endpoint | Purpose |
|---|---|
| POST/api/v1/payouts/create | Send money from your balance to a payee |
| POST/api/v1/payouts/query | Look up a payout |
| POST/api/v1/payouts/cancel | Cancel a payout that is still processing |
| POST/api/v1/payouts/precheck | Check your balance and the fee before creating a payout |
{
"payment_method": "CASH_APP",
"merchant_payout_no": "PAYOUT-1001-069I",
"trans_amount": {
"currency": "USD",
"value": "20.00"
},
"payee": {
"account_id": "$testpayee",
"account_type": "CASHTAG",
"full_name": "Test Payee"
},
"notify_url": "https://merchant.example.com/hansapay/webhook"
}BODY='{"payment_method":"CASH_APP","merchant_payout_no":"PAYOUT-1001-069I","trans_amount":{"currency":"USD","value":"20.00"},"payee":{"account_id":"$testpayee","account_type":"CASHTAG","full_name":"Test Payee"},"notify_url":"https://merchant.example.com/hansapay/webhook"}'
TS=$(date +%s); NONCE=$(openssl rand -hex 8)
SIGN=$(printf '%s\n%s\n%s\n%s' "$MERCHANT_ID" "$TS" "$NONCE" "$BODY" \
| openssl dgst -sha256 -hmac "$SECRET_KEY" | sed 's/^.* //')
curl https://api-test.hansapay.io/api/v1/payouts/create \
-H "Content-Type: application/json" \
-H "X-MerchantID: $MERCHANT_ID" -H "X-Timestamp: $TS" \
-H "X-Nonce: $NONCE" -H "X-Sign: $SIGN" \
--data-raw "$BODY"// callHansaPay() is on the Authentication page, under "Signing in code".
const { rawBody } = await callHansaPay(BASE_URL, MERCHANT_ID, SECRET_KEY, "/payouts/create", {
payment_method: "CASH_APP",
merchant_payout_no: "PAYOUT-1001-069I",
trans_amount: {
currency: "USD",
value: "20.00"
},
payee: {
account_id: "$testpayee",
account_type: "CASHTAG",
full_name: "Test Payee"
},
notify_url: "https://merchant.example.com/hansapay/webhook"
})
const { code, msg, data } = JSON.parse(rawBody)# call_hansapay() is on the Authentication page, under "Signing in code".
headers, raw = call_hansapay(BASE_URL, MERCHANT_ID, SECRET_KEY, "/payouts/create", {
"payment_method": "CASH_APP",
"merchant_payout_no": "PAYOUT-1001-069I",
"trans_amount": {
"currency": "USD",
"value": "20.00",
},
"payee": {
"account_id": "$testpayee",
"account_type": "CASHTAG",
"full_name": "Test Payee",
},
"notify_url": "https://merchant.example.com/hansapay/webhook",
})
res = json.loads(raw)POST /api/v1/payouts/create HTTP/1.1
Content-Type: application/json
X-MerchantID: M_74209884
X-Timestamp: 1790420278
X-Nonce: 1340ee63600096b1
X-Sign: 2fa5cf39f00c0adbbab399928c8ba85ecda7b111f1922c55a659d910cc0003b1
{
"payment_method": "CASH_APP",
"merchant_payout_no": "PAYOUT-1001-069I",
"trans_amount": {
"currency": "USD",
"value": "20.00"
},
"payee": {
"account_id": "$testpayee",
"account_type": "CASHTAG",
"full_name": "Test Payee"
},
"notify_url": "https://merchant.example.com/hansapay/webhook"
}{
"code": 5007,
"msg": "payment_method CASH_APP is not available for payouts|unsupportedPayoutMethod"
}Create a payout
POST/api/v1/payouts/create| Field | Type | Required | Description |
|---|---|---|---|
payment_method | string | Yes | CASH_APP, PAYPAL or PIX |
merchant_payout_no | string | Yes | Your payout number, at most 64 characters, unique among your payouts |
trans_amount | object | Yes | The amount the payee receives, not including the fee |
payee | object | Yes | account_id, account_type, full_name, email, mobile, country, document, payee_id |
memo | string | No | At most 128 characters |
notify_url | string | Yes | Where to send payout.updated webhooks |
metadata | string | No | Returned in queries and webhooks |
client_ip | string | No |
account_type is one of EMAIL, MOBILE, CASHTAG, USERID, BANK_ACCOUNT or USDT_ADDRESS; for PIX also CPF, CNPJ or PHONE.
Response fields: payment_method, payout_no, merchant_payout_no, status, trans_amount, fee, total_debit (amount plus fee, in USD), next_action (WAIT_NOTIFY, SUCCESS or FAILED) and created_at.
The fee is the payout amount times your payout fee rate, plus your per-payout fee. Your available balance must cover total_debit; otherwise the request fails with 5004 insufficient merchant payout balance|insufficientFunds.
Query a payout
POST/api/v1/payouts/queryPOST/api/v1/payouts/query with exactly one of payout_no or merchant_payout_no. Response fields: payment_method, payout_no, merchant_payout_no, status, status_reason, trans_amount, fee, total_debit, payee (with the account masked), metadata, paid_at, created_at and updated_at. An unknown payout returns 5002 payout not found|notFound.
Cancel a payout
POST/api/v1/payouts/cancelPOST/api/v1/payouts/cancel with exactly one of payout_no or merchant_payout_no, and an optional reason (at most 128 characters). Only a payout in PROCESSING can be cancelled, and only if the channel supports it. Cancelling a payout that is already cancelled succeeds again. Response fields: payout_no, merchant_payout_no and status.
Precheck
POST/api/v1/payouts/precheckPOST/api/v1/payouts/precheck with payment_method and, optionally, trans_amount. Response fields: payment_method, currency, available_balance, unsettled_balance, frozen_balance, spendable_balance, estimated_fee and estimated_debit (when an amount was sent), and can_payout. Without an amount, can_payout only says whether your available balance is above zero; it does not mean a payout method is available.
{
"payment_method": "CASH_APP"
}BODY='{"payment_method":"CASH_APP"}'
TS=$(date +%s); NONCE=$(openssl rand -hex 8)
SIGN=$(printf '%s\n%s\n%s\n%s' "$MERCHANT_ID" "$TS" "$NONCE" "$BODY" \
| openssl dgst -sha256 -hmac "$SECRET_KEY" | sed 's/^.* //')
curl https://api-test.hansapay.io/api/v1/payouts/precheck \
-H "Content-Type: application/json" \
-H "X-MerchantID: $MERCHANT_ID" -H "X-Timestamp: $TS" \
-H "X-Nonce: $NONCE" -H "X-Sign: $SIGN" \
--data-raw "$BODY"// callHansaPay() is on the Authentication page, under "Signing in code".
const { rawBody } = await callHansaPay(BASE_URL, MERCHANT_ID, SECRET_KEY, "/payouts/precheck", {
payment_method: "CASH_APP"
})
const { code, msg, data } = JSON.parse(rawBody)# call_hansapay() is on the Authentication page, under "Signing in code".
headers, raw = call_hansapay(BASE_URL, MERCHANT_ID, SECRET_KEY, "/payouts/precheck", {
"payment_method": "CASH_APP",
})
res = json.loads(raw)POST /api/v1/payouts/precheck HTTP/1.1
Content-Type: application/json
X-MerchantID: M_74209884
X-Timestamp: 1790420278
X-Nonce: 9c65fecbd4d45fcc
X-Sign: 180b89709fede070012bc7e59500fcffa65365c48e10f59fae37151ad696eb74
{
"payment_method": "CASH_APP"
}{
"code": 0,
"msg": "success",
"data": {
"payment_method": "CASH_APP",
"currency": "USD",
"available_balance": {
"currency": "USD",
"value": "97.20"
},
"unsettled_balance": {
"currency": "USD",
"value": "137.00"
},
"frozen_balance": {
"currency": "USD",
"value": "80.00"
},
"spendable_balance": {
"currency": "USD",
"value": "97.20"
},
"can_payout": true
}
}Payout statuses
PENDING (accepted), PROCESSING (sent to the provider), SUCCESS, FAILED and CANCELED. The last three are final and are sent as payout.updated webhooks, with status_reason set to Payout failed, Payout request failed or Payout canceled where it applies.
