Workflow Guides
Workflow pages connect API actions, webhook behavior, settlement state, pricing impact, and troubleshooting. Use this page when you want the full operating sequence instead of only endpoint examples.Developer note: For SDK/API examples across fixed amount invoices, auto-detected payments, payout routes, dynamic payout recipients, and programmatic withdrawals, see Payment flows.
Receive payments
Use this workflow when the payer should pay a specific amount for an order, checkout session, invoice, top-up, or service.Before you begin
- Confirm the business is in the correct environment: sandbox or live.
- Confirm the token and
networkIdare supported. - Store API keys only on your backend.
- Configure webhook URL and signing secret.
- Decide what your system should do after
paidoroverpaid.
What you do
- Create or find a customer.
- Create an invoice with
amount,token,chain,networkId, and your own order metadata. - Show the hosted invoice link or render the payment address in your own checkout.
- Wait for PayChain to detect and confirm the transfer.
- Verify the webhook signature with the raw request body.
- Fetch the canonical invoice.
- Fulfill the order only after the canonical invoice is
paidoroverpaid. - Store the PayChain invoice ID, transaction hash, and your order reference together.
Expected result
- The invoice moves from
pendingtoconfirmingwhen payment is observed. - The invoice moves to
paidafter settlement confirmation. - Eligible funds are swept or made available for treasury movement according to the supported rail and business policy.
- Your backend receives a signed webhook.
- Your own order moves to fulfilled once your handler verifies and fetches the invoice.
Stellar invoices
For Stellar mainnet, PayChain returns the business Stellar treasury address plus a required numeric Stellar Memo ID by default. The payer must send the exact asset todepositAddress and include the returned memo.
The invoice response includes:
invoice.paid webhook. A Stellar payment with a missing memo, wrong memo, wrong asset, or wrong issuer is recorded for review and does not automatically fulfill the invoice.
Stellar issued asset invoices
For Stellar issued assets such as USDC, the asset identity must include the issuer. PayChain matches Stellar issued assets byassetCode, issuerAddress, and canonicalAssetId, not by the display symbol alone.
Use this shape when creating a Stellar USDC invoice:
receiveMode: "dedicated_address", the invoice uses the legacy dedicated-address flow. Dedicated-address Stellar issued-asset invoices require the receiver account and trustline to be ready before the address is shown.
Pricing or gas impact
- The invoice fee applies when the invoice settles.
- Inbound payment detection does not consume gas credits.
- Automatic settlement or sponsored outbound movement after payment may consume gas credits.
Troubleshooting
Auto-detect payments
Use auto-detection when repeat payers deposit to reusable customer addresses and you do not want to pre-create every invoice. Before showing a reusable customer address, ensure the customer has an address for the exact rail you are about to display. Use this pattern for reusable-address rails:- For Solana mainnet, call
POST /api/v1/businesses/:businessId/customers/:customerId/addresses/ensureorpaychain.customers.ensureAddress(...)withchain: "sol"andnetworkId: "sol-mainnet". - For Stellar mainnet, default invoice and Auto Deposit Intent receive uses the business treasury address plus a required Memo ID, so
ensureAddressis not required unless you explicitly opt intoreceiveMode: "dedicated_address".
Reusable-address rail note: PayChain can lazily provision a missing customer address for supported reusable-address rails. Call the ensure endpoint before displaying those addresses, including for existing customers after PayChain enables a new network. Integrations should still send
networkId explicitly and must verify the returned address.chainFamily and address.networkId before displaying it. If the expected address is not returned, fail setup instead of falling back to an EVM 0x... address or another reusable address.What PayChain does
- Watches supported customer deposit addresses.
- Ignores non-positive observations.
- Ignores PayChain operational transfers.
- Applies auto-invoice minimum and dust thresholds.
- Creates an auto-generated invoice for a qualifying deposit.
- Emits the normal invoice webhook.
Auto Deposit Intents
Use an Auto Deposit Intent when a customer deposit represents a specific off-ramp, on-ramp, wallet-funding, or provider-payout order. On Stellar, the default intent returns the business treasury address plus a required Memo ID. On reusable-address rails such as Solana, the intent uses the customer deposit address. For eachbusiness + customer + token + network, PayChain keeps one active intent. Creating a new same-rail intent replaces the older active intent. A deposit is assigned to an order only when exactly one active intent exists and the received amount is within the configured tolerance.
Auto-detect assignment has two business modes:
Order-aware reusable address flow
- Create the customer or fetch the existing customer.
- Create an Auto Deposit Intent with
externalOrderId,chain,networkId,token,expectedAmount, and optional payout route or payout recipients. - Show the returned payment instructions to the payer. For Stellar, show both
depositAddressandmemo.value. - Verify the
invoice.paidwebhook. - Fetch the canonical invoice.
- Fulfill only when
autoDepositAssignmentStatusismatchedandexternalOrderIdmatches the order you are about to release. - Route provider payout only from a matched invoice.
Dust and minimum rules
Auto-detected deposits use plan and network guardrails so tiny or operational transfers do not become customer revenue.Settlement confirmation
PayChain separates “observed” from “settled.” A transfer can be seen before it is safe to treat as final.
Settlement rules can differ by network. Your integration should consume invoice status, not guess finality from a block explorer.
For networks that require multiple confirmations, poll
GET /api/v1/invoices/:invoiceId or the authenticated invoice detail endpoint. The response includes confirmationProgress.current, confirmationProgress.required, confirmationProgress.remaining, confirmationProgress.percent, and confirmationProgress.txHash when a matching transaction is detected.
For Stellar mainnet XLM and registered issued assets, one successfully closed ledger is treated as settled. PayChain marks the invoice paid after it indexes the closed ledger.
If an on-chain Stellar payment is confirmed but the invoice remains pending longer than expected, keep fulfillment pending and contact PayChain support with the invoice ID, network, asset, amount, destination address, and transaction hash.
Payout routes
A payout route is an approved template that tells PayChain how to split an invoice after it is fully paid. Use payout routes when the same split pattern repeats. Use dynamic payout recipients when each invoice has a one-time receiver, such as an on-ramp or marketplace order. Each recipient leg counts as one payout API withdrawal for quota and fee purposes.Withdraw funds
Withdrawals move business treasury funds to an external destination. Dashboard withdrawals are manual; payout API withdrawals are backend-driven.Withdrawal lifecycle
- Quote the withdrawal.
- Review amount, token, network, fee, and destination.
- Create the withdrawal with a payout API key or dashboard action.
- PayChain queues the withdrawal.
- If the funds were just paid into an invoice or customer address, PayChain may wait for sweep completion before submitting the payout.
- PayChain submits the network transaction where applicable.
- PayChain sends withdrawal webhooks as the status changes.
chain: "stellar", networkId: "stellar-mainnet", token: "XLM", and a valid Stellar G... destination address. A withdrawal can include a Stellar memo when the destination requires one.
Fresh-payment note: If your backend creates a withdrawal immediately after an
invoice.paid webhook, the withdrawal can enter pending_funds while PayChain finishes moving sweepable funds into withdrawable treasury capacity. Poll the withdrawal or listen for withdrawal webhooks instead of treating this as a failed payout.Edge cases
Reconcile balances
Reconcile invoices, payments, balances, withdrawals, and transactions together. Raw wallet balance is not the same as invoice truth. Use the balance fields intentionally:amounts.totalis the merchant-facing withdrawable amount.amounts.totalHeldis the projected amount PayChain can see across active address rows.amounts.requiresRecoveryis visible for reconciliation, but is not currently counted as withdrawable capacity.
Webhook lifecycle
PayChain sends a webhook after important state changes. Your endpoint should verify, deduplicate, fetch the canonical resource, act once, and return a2xx quickly.
See Webhooks for payload examples, retry behavior, and replay guidance.