PayChainHQ

PaychainHQ Docs

Payment Lifecycle Guides

End-to-end implementation docs organized around the 3 production flows: receive payment, confirm payment, and withdraw payment. Includes request/response and webhook payload shapes.

Overview

Use API keys from your backend for payment APIs. Use dashboard login only for operator UI actions.

Invoice and withdrawal APIs are asynchronous. Build around lifecycle states, not single request success.
Use webhook events as real-time triggers; use invoice/withdrawal reads as reconciliation fallback.
Include Idempotency-Key on mutating calls.
Persist API requestId for support and incident debugging.

Integration Model

Most teams implement PaychainHQ as a 3-step server workflow.

Lifecycle 1

Receive payment

Create customer (optional), create invoice, share payer card/link.

Lifecycle 2

Confirm payment

Verify webhook, update order state, handle underpay/overpay paths.

Lifecycle 3

Withdraw payment

Quote first, execute payout with step-up, then track status to completion.

1. Receive Payment

Create a payable invoice and give the sender a clear destination, amount, token, and chain.

MethodPathAuthDescription
POST/api/v1/businesses/:id/customersx-api-key or BearerOptional: create reusable customer identity before invoicing.
POST/api/v1/businesses/:id/invoicesx-api-key or BearerCreate invoice and allocate deposit address.
GET/api/v1/invoices/:invoiceIdPublicRead shareable invoice payload for payer-facing page/card.

1. Create customer (optional)

If the payer is recurring, create a customer first so invoices can be grouped by identity.

2. Create invoice

Send amount/token/chain/network with a unique Idempotency-Key.

3. Render share card/link

Use public invoice payload to show QR, address, exact amount, and countdown.

Create Invoice Request Body
{
  "customerId": "cus_9f7d7c42",
  "amount": "10",
  "token": "USDC",
  "chain": "eth",
  "networkId": "base-sepolia",
  "expiresIn": 86400,
  "description": "Design sprint payment"
}
Create Invoice Response (201)
{
  "id": "inv_46a1a472",
  "businessId": "biz_123",
  "customerId": "cus_9f7d7c42",
  "amount": "10",
  "token": "USDC",
  "status": "pending",
  "chain": "eth",
  "networkId": "base-sepolia",
  "depositAddress": "0xE5fa2F71065fD49823D33EdD84ecFD2D6245c916",
  "expiresAt": "2026-03-04T12:00:00.000Z",
  "createdAt": "2026-03-03T12:00:00.000Z",
  "feePreview": {
    "platformFee": 0.2,
    "gasReserveFee": 0.05,
    "totalFee": 0.25,
    "effectiveRate": "2.50%",
    "note": "Fees will be deducted when invoice is paid"
  },
  "expectedNet": {
    "usd": 9.75,
    "token": "9.75 USDC"
  }
}

2. Confirm Payment

Confirm invoice settlement using webhook-first logic, with invoice reads as fallback.

MethodPathAuthDescription
PATCH/api/v1/businesses/:id/webhookBearer + step-upConfigure webhook URL, signing secret, and auth token.
GET/api/v1/businesses/invoices/:invoiceIdx-api-key or BearerOperator view of status and reconciliation data.
GET/api/v1/invoices/:invoiceIdPublicPayer view with progress (underpaid/overpaid/paid).
GET/api/v1/businesses/:id/webhook/eventsBearerInspect delivery attempts and replay failed events.

1. Verify webhook signature

Always validate X-Webhook-Signature against the raw request body before processing.

2. Apply state transition

Use webhook event + invoice status to move your order state (pending/confirming/paid/underpaid/overpaid).

3. Resolve edge cases

If underpaid before expiry, keep invoice open for top-up. If overpaid, mark paid and trigger remediation workflow.

Webhook Envelope (Delivered To Your Endpoint)
{
  "id": "evt_2b3f1fa0",
  "event": "invoice.paid",
  "timestamp": "2026-03-03T12:01:04.903Z",
  "data": {
    "invoiceId": "inv_46a1a472",
    "businessId": "biz_123",
    "status": "paid",
    "state": "completed",
    "amount": {
      "raw": "10000000",
      "decimals": 6,
      "display": "10",
      "symbol": "USDC",
      "chain": "eth",
      "networkId": "base-sepolia"
    },
    "paidAmount": {
      "raw": "10000000",
      "decimals": 6,
      "display": "10",
      "symbol": "USDC",
      "chain": "eth",
      "networkId": "base-sepolia"
    },
    "overpaidAmount": {
      "raw": "0",
      "decimals": 6,
      "display": "0",
      "symbol": "USDC",
      "chain": "eth",
      "networkId": "base-sepolia"
    },
    "txHash": "0x9ee6...",
    "confirmations": 12,
    "occurredAt": "2026-03-03T12:01:04.903Z"
  }
}
Webhook Signature Verification (Node.js)
import crypto from 'node:crypto';

export function verifyPaychainHQWebhook(rawBody: string, signatureHex: string, webhookSecret: string): boolean {
  const expected = crypto.createHmac('sha256', webhookSecret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signatureHex, 'hex'), Buffer.from(expected, 'hex'));
}

// Headers sent by PaychainHQ:
// X-Webhook-Signature
// X-Webhook-ID
// X-Webhook-Attempt
// X-Webhook-Timestamp
// X-Webhook-Signature-Alg
Public Invoice Read Shape (Reconciliation Fallback)
{
  "id": "inv_46a1a472",
  "status": "confirming",
  "state": "confirming",
  "amount": {
    "raw": "10000000",
    "decimals": 6,
    "display": "10",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-sepolia"
  },
  "paidAmount": {
    "raw": "7000000",
    "decimals": 6,
    "display": "7",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-sepolia"
  },
  "paymentProgress": {
    "percentPaid": "70.00",
    "status": "Partially paid - additional payment required",
    "remainingAmount": {
      "display": "3"
    }
  },
  "depositAddress": "0xE5fa2F71065fD49823D33EdD84ecFD2D6245c916"
}

3. Withdraw Payment

Move funds out safely with quote-first execution and status tracking.

MethodPathAuthDescription
GET/api/v1/businesses/:id/withdrawals/quotex-api-key or BearerPreview sweep cost, available balance, and best payout option.
POST/api/v1/businesses/:id/withdrawalsBearer + step-upQueue withdrawal execution.
GET/api/v1/businesses/:id/withdrawalsx-api-key or BearerTrack payout status (pending -> processing -> completed/failed).

1. Get quote

Check availability, sweep requirement, cost, and recommendation before creating withdrawal.

2. Create withdrawal

Use dashboard session + step-up for the final payout mutation.

3. Track lifecycle

Poll/list withdrawals for pending -> processing -> completed/failed and surface txHash to operators.

Withdrawal Quote Response (200)
{
  "requestedAmountUSD": 500,
  "token": "USDC",
  "chain": "eth",
  "networkId": "base-sepolia",
  "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
    }
  ]
}
Create Withdrawal Request Body
{
  "amount": "500",
  "token": "USDC",
  "chain": "eth",
  "networkId": "base-sepolia",
  "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3",
  "clientReference": "vendor-payout-2026-03-0031",
  "reference": "Vendor March settlement",
  "metadata": {
    "vendorId": "ven_29831",
    "batch": "march-settlement"
  }
}
Create Withdrawal Response (202)
{
  "id": "wdr_89f0c9",
  "status": "pending",
  "state": "queued",
  "amount": {
    "raw": "500000000",
    "decimals": 6,
    "display": "500",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-sepolia"
  },
  "withdrawalFee": {
    "raw": "1200000",
    "decimals": 6,
    "display": "1.2",
    "symbol": "USDC",
    "chain": "eth",
    "networkId": "base-sepolia"
  },
  "destination": "0x5fBDB2315678afecb367f032d93F642f64180aa3",
  "txHash": null,
  "message": "Withdrawal accepted for processing"
}

Security & Auth

Split machine auth from operator auth.

Server integrations should call payment APIs with x-api-key.
Dashboard login/refresh/step-up endpoints are for first-party UI operator sessions.
Sensitive mutations (team, api keys, withdrawals) require step-up re-authentication.
Store webhook secret and API keys in a server-side secret manager only.

Turnkey-powered treasury operations

PayChainHQ uses Turnkey for MPC-backed key infrastructure behind treasury and wallet operations. In practice, that means operational signing and key management are handled through hardened custody infrastructure rather than raw private keys living in your application environment.

Your integration does not talk to Turnkey directly for normal payment collection. You integrate with PayChainHQ APIs, while PayChainHQ uses Turnkey internally for controlled wallet creation, treasury movement, and operational signing flows.

Go-Live Checklist

Minimum checklist before production traffic.

  • Webhook signature verification enabled in production.
  • Invoice underpaid/overpaid handling paths implemented.
  • Withdrawal quote + create + tracking flow tested on staging.
  • Alerting on webhook delivery failures and payout failures.
Need endpoint-by-endpoint references?Open docs hub