API reference

Withdrawals and treasury reference

Quote, create, and track withdrawals, then reconcile treasury balances and transaction feeds.

GET/api/v1/businesses/:id/withdrawals/quotex-api-keySandbox + live

Get withdrawal quote

Estimate treasury availability, sweep requirements, and payout cost before creating a withdrawal.

When to use it

Always quote before presenting a payout option to operators or customers.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
amountqueryYesRequested amount in token display units.-
tokenqueryYesToken symbol.-
chainqueryYesChain family.-
networkIdqueryNoSpecific network.-
forceSweepAllqueryNoForce sweep all eligible balances before quoting.-

Flags and defaults

  • forceSweepAll (default: false): Include dust / low-value balances in the sweep plan.

Cautions

  • Quote availability is still subject to confirmation, treasury freshness, and runtime network policy at execution time.
  • Force sweep does not guarantee fulfillment if net sweepable-to-treasury value is still insufficient.

Common errors

  • 401: Missing or invalid API key.
  • 400: Payload shape, query params, or business-state validation failed.

Sample response

json
{
  "requestedAmountUSD": 500,
  "token": "USDC",
  "chain": "eth",
  "networkId": "base-mainnet",
  "treasuryBalanceUSD": 220,
  "totalAvailableUSD": 760.5,
  "addressesWithFunds": 8,
  "sweepNeeded": true,
  "recommended": "exact",
  "message": "Withdrawal feasible. Will sweep 3 address(es) first.",
  "options": [
    {
      "type": "exact_withdrawal",
      "label": "Withdraw Exact Amount",
      "payoutUSD": 500,
      "sweepCount": 3,
      "totalCostUSD": 2.34,
      "feePercent": 0.47,
      "available": true
    }
  ]
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals/quote" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals/quote', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
POST/api/v1/businesses/:id/withdrawalsx-api-keySandbox + live

Create withdrawal

Queue a treasury withdrawal with dashboard step-up or a policy-controlled payout API key.

When to use it

Use only after quoting and after your operator or automation is ready to accept async processing.

Idempotency: required

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
amountbodyYesRequested amount in token display units.-
tokenbodyYesToken symbol.-
chainbodyYesChain family.-
networkIdbodyNoSpecific network.-
destinationbodyYesDestination address.-
clientReferencebodyNoYour payout reference for idempotent reconciliation.-
referencebodyNoHuman-readable payout reference.-
forceSweepAllbodyNoForce sweeping all eligible funds before payout.-

Flags and defaults

  • forceSweepAll (default: false): Force sweep every eligible non-treasury address before payout.

Cautions

  • Send a stable `Idempotency-Key` per intended payout and reuse it for retries until you receive or can fetch the created withdrawal.
  • Standard API keys cannot create withdrawals. Programmatic withdrawals require a dedicated payout API key.
  • Payout API keys can withdraw only to configured destinations within their token, network, amount, daily, and IP policy.
  • Requested amount and payout amount can differ because PayChainHQ withdrawal fees are deducted from the requested amount.
  • For native assets, network gas can reduce the send amount further at broadcast time.

Common errors

  • 401: Missing or invalid API key.
  • 403 HIGH_RISK_API_KEY_SCOPE_DISABLED: A standard API key attempted a protected operation that now requires dashboard session auth or a dedicated payout or contract execution API key.
  • 403 PAYOUT_POLICY_REJECTED: A payout API key withdrawal failed destination policy, token, network, amount, daily cap, or IP allowlist policy.
  • 400: Payload shape, query params, or business-state validation failed.
  • Cannot fulfill withdrawal: Net treasury + sweepable balance cannot satisfy the requested payout.

Sample request body

json
{
  "amount": "500",
  "token": "USDC",
  "chain": "eth",
  "networkId": "base-mainnet",
  "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3",
  "clientReference": "vendor-payout-2026-03-0031",
  "reference": "Vendor March settlement",
  "metadata": {
    "vendorId": "ven_29831",
    "batch": "march-settlement"
  },
  "forceSweepAll": true
}

Sample response

json
{
  "id": "wdr_123",
  "status": "pending",
  "state": "queued",
  "requestedAmount": {
    "raw": "500000000",
    "decimals": 6,
    "display": "500",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "payoutAmount": {
    "raw": "498800000",
    "decimals": 6,
    "display": "498.8",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "withdrawalFee": {
    "raw": "1200000",
    "decimals": 6,
    "display": "1.2",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3"
}

cURL example

bash
curl -X POST "https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key" \
  -H "Idempotency-Key: example-request-001" \
  -d '{
  "amount": "500",
  "token": "USDC",
  "chain": "eth",
  "networkId": "base-mainnet",
  "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3",
  "clientReference": "vendor-payout-2026-03-0031",
  "reference": "Vendor March settlement",
  "metadata": {
    "vendorId": "ven_29831",
    "batch": "march-settlement"
  },
  "forceSweepAll": true
}'

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
    'Idempotency-Key': 'example-request-001',
  },
  body: JSON.stringify({
  "amount": "500",
  "token": "USDC",
  "chain": "eth",
  "networkId": "base-mainnet",
  "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3",
  "clientReference": "vendor-payout-2026-03-0031",
  "reference": "Vendor March settlement",
  "metadata": {
    "vendorId": "ven_29831",
    "batch": "march-settlement"
  },
  "forceSweepAll": true
}),
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/withdrawalsx-api-keySandbox + live

List withdrawals

List withdrawal attempts and their current processing states.

When to use it

Use for operational dashboards, payout polling, and settlement exports.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
statusqueryNoFilter by withdrawal status.-
pagequeryNoPage number.1
limitqueryNoPage size.20

Cautions

  • Treat `pending`, `sweeping`, `processing`, and `retrying` as non-terminal. Only `completed`, `failed`, and `cancelled` are terminal.
  • Payout API keys can list only withdrawals created by that same payout key.

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "data": [
    {
      "id": "wdr_123",
      "status": "processing",
      "processingStep": "broadcast_withdrawal",
      "token": "USDC",
      "chain": "eth",
      "networkId": "base-mainnet",
      "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1,
    "hasMore": false
  }
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals?page=1&limit=20" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals?page=1&limit=20', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/withdrawals/:withdrawalIdx-api-keySandbox + live

Get withdrawal detail

Return one withdrawal with fee, payout, retry, and processing metadata.

When to use it

Use after webhook receipt or when drilling into a failed or retrying payout.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
withdrawalIdpathYesWithdrawal ID.-

Cautions

  • Payout API keys receive `404` for withdrawals created by another key or surface.

Common errors

  • 401: Missing or invalid API key.
  • 404: Requested resource does not exist or is not owned by the business.

Sample response

json
{
  "id": "wdr_123",
  "status": "pending",
  "state": "queued",
  "requestedAmount": {
    "raw": "500000000",
    "decimals": 6,
    "display": "500",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "payoutAmount": {
    "raw": "498800000",
    "decimals": 6,
    "display": "498.8",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "withdrawalFee": {
    "raw": "1200000",
    "decimals": 6,
    "display": "1.2",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3"
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals/wdr_123" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals/wdr_123', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
PATCH/api/v1/businesses/:id/withdrawals/:withdrawalId/cancelx-api-keySandbox + live

Cancel withdrawal

Cancel a queued withdrawal before it reaches an irreversible stage.

When to use it

Use for operator intervention when a payout should not proceed.

Idempotency: recommended

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
withdrawalIdpathYesWithdrawal ID.-

Cautions

  • Once broadcast starts, cancellation may no longer be possible. Inspect the returned status after the call.

Common errors

  • 401: Missing or invalid API key.
  • 404: Requested resource does not exist or is not owned by the business.

Sample response

json
{
  "id": "wdr_123",
  "status": "pending",
  "state": "queued",
  "requestedAmount": {
    "raw": "500000000",
    "decimals": 6,
    "display": "500",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "payoutAmount": {
    "raw": "498800000",
    "decimals": 6,
    "display": "498.8",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "withdrawalFee": {
    "raw": "1200000",
    "decimals": 6,
    "display": "1.2",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-mainnet"
  },
  "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3"
}

cURL example

bash
curl -X PATCH "https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals/wdr_123/cancel" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key" \
  -H "Idempotency-Key: example-request-001"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/withdrawals/wdr_123/cancel', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
    'Idempotency-Key': 'example-request-001',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/balancesx-api-keySandbox + live

List balances

Return business balances grouped by asset.

When to use it

Use before quoting withdrawals or when showing operator portfolio balances.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "data": [
    {
      "chain": "eth",
      "networkId": "base-mainnet",
      "token": "USDC",
      "available": "149.75",
      "withdrawable": "149.50"
    }
  ]
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/balances" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/balances', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/balances/totalx-api-keySandbox + live

Get total balances

Return total gross, reserved, and net withdrawable USD values.

When to use it

Use for top-line dashboards and treasury health checks.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "openInvoiceCount": 3,
  "inFlightWithdrawalCount": 1,
  "nextOpenInvoiceExpiryAt": "2026-03-14T14:15:00.000Z"
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/balances/total" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/balances/total', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/balances/by-networkx-api-keySandbox + live

Get balances by network

Return balances grouped by network and token.

When to use it

Use when payout logic or treasury UI needs network-level segmentation.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "data": [
    {
      "networkId": "base-mainnet",
      "chain": "eth",
      "tokens": [
        {
          "symbol": "USDC",
          "available": "149.75",
          "withdrawable": "149.50"
        }
      ]
    }
  ]
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/balances/by-network" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/balances/by-network', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/balances/historyx-api-keySandbox + live

Get balance history

Return historical balance snapshots.

When to use it

Use for analytics, audit exports, or trend charts.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
startDatequeryNoISO start date.-
endDatequeryNoISO end date.-

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "data": [
    {
      "asOf": "2026-03-14T13:00:00.000Z",
      "totalBalanceUSD": 12495.22
    }
  ]
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/balances/history" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/balances/history', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/transactionsx-api-keySandbox + live

List transactions

List invoices and withdrawals in one operational feed.

When to use it

Use for recent activity feeds or compact reconciliation screens.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
typequeryNoOptional `invoice` or `withdrawal` filter.-
statusqueryNoOptional lifecycle filter.-

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "data": [
    {
      "id": "inv_123",
      "type": "invoice",
      "status": "paid",
      "token": "USDC",
      "chain": "eth",
      "networkId": "base-mainnet",
      "amount": {
        "raw": "150000000",
        "decimals": 6,
        "display": "150",
        "symbol": "USDC",
        "chain": "eth",
        "networkId": "base-mainnet"
      },
      "createdAt": "2026-03-14T12:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1,
    "hasMore": false
  }
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/transactions" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/transactions', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/transactions/summaryx-api-keySandbox + live

Get transaction summary

Return invoice and withdrawal totals for a date range.

When to use it

Use in analytics dashboards or operational summaries.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
startDatequeryNoOptional ISO start date.-
endDatequeryNoOptional ISO end date.-

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "invoices": {
    "total": 31,
    "paid": 24,
    "pending": 3,
    "totalAmount": "21450.18"
  },
  "withdrawals": {
    "total": 9,
    "completed": 7,
    "pending": 1,
    "totalAmount": "18500.00"
  }
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/transactions/summary" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/transactions/summary', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/payment-addressesx-api-keySandbox + live

List payment addresses

List derived payment addresses owned by the business.

When to use it

Use for reconciliation, compliance review, or indexer diagnostics.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-

Cautions

  • These are operational addresses. Do not infer invoice state from address balance alone.

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "data": [
    {
      "chain": "eth",
      "networkId": "base-mainnet",
      "address": "0xE5fa2F71065fD49823D33EdD84ecFD2D6245c916",
      "purpose": "invoice_or_customer_deposit"
    }
  ]
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/payment-addresses" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/payment-addresses', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/payment-addresses/:chainx-api-keySandbox + live

List payment addresses by chain

Return payment addresses for a single chain family.

When to use it

Use when you only need one chain scope, such as BTC or SOL deposit infrastructure.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-
chainpathYesChain family: `eth`, `btc`, or `sol`.-

Common errors

  • 401: Missing or invalid API key.
  • 400: Payload shape, query params, or business-state validation failed.

Sample response

json
{
  "data": [
    {
      "chain": "eth",
      "networkId": "base-mainnet",
      "address": "0xE5fa2F71065fD49823D33EdD84ecFD2D6245c916",
      "purpose": "invoice_or_customer_deposit"
    }
  ]
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/payment-addresses/eth" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/payment-addresses/eth', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
GET/api/v1/businesses/:id/activity-summaryx-api-keySandbox + live

Get live activity summary

Return open-invoice and in-flight-withdrawal counters used by the dashboard.

When to use it

Use for light-weight realtime badge counts without fetching full tables.

FieldLocationRequiredDescriptionExample / default
idpathYesBusiness ID.-

Common errors

  • 401: Missing or invalid API key.

Sample response

json
{
  "businessId": "biz_123",
  "totalBalanceUSD": 12495.22,
  "grossOnChainUSD": 12610.41,
  "reservedFeesUSD": 115.19,
  "netWithdrawableUSD": 12495.22
}

cURL example

bash
curl -X GET "https://api.paychainhq.io/api/v1/businesses/biz_123/activity-summary" \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_business_key"

Node.js example

ts
const response = await fetch('https://api.paychainhq.io/api/v1/businesses/biz_123/activity-summary', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'pk_live_your_business_key',
  },
});
const payload = await response.json();
console.log(payload);
Withdrawals and treasury reference | PayChainHQ