Build it with an AI agent
Give this to your AI agent
Paste it into Claude Code, Cursor or any agent that can read a URL. It reads the OpenAPI contract and the signing recipe, and follows the rules for handling real funds.
Read https://www.payaries.com/ai-agents.md and integrate Payaries crypto payments into this project. Follow its rules for handling real funds.Never paste your API secret into an agent. Keep it in an environment variable.
01Before you start
- Payaries runs on real mainnet networks only. There is no sandbox. Test-mode keys transact on the same chains as live keys, so plan the final test as a small real payment.
- You need a server. The API secret must never reach browser code.
- The API lives at
https://bqpay-api-gateway.buildquick.tech. The contract is athttps://www.payaries.com/openapi.json.
021. One-time setup in the dashboard
- 01Create an account. Passwords need at least 10 characters and can't be a well-known one.
- 02Create a test API key from the dashboard. The key and secret are shown once; store them as
PAYARIES_API_KEYandPAYARIES_API_SECRET. A test key works immediately; live keys are issued once your account is approved. - 03Submit your business profile. This is mandatory before any invoice, test or live: until then
POST /v1/invoicesreturns403withcode: "ONBOARDING_REQUIRED". Submitting is enough to start testing. - 04Register your webhook URL (a public
https://address, no redirects) and create the webhook secret. It is shown once and is not the API secret.
032. See what you can accept
GET /v1/chains is public and always authoritative. An asset appears only once it is actually configured.
{ "chains": [ { "chainId": "tron-mainnet", "name": "Tron Mainnet", "assets": ["TRX", "USDT_TRC20"] }, ... ] }043. Create an invoice
Every request is signed; the signing guide has the exact recipe and a test vector for Node, Python, Go and shell. referenceId is your idempotency key: sending the same one again returns the existing invoice, never a duplicate.
# body: {"referenceId":"order_10231","fiat":{"amount":"49.99","currency":"USD"},"crypto":{"asset":"USDT_TRC20","chainId":"tron-mainnet"}}
# X-Timestamp and X-Signature come from the signing guide's helper
curl -s -X POST https://bqpay-api-gateway.buildquick.tech/v1/invoices \
-H "X-Api-Key: $PAYARIES_API_KEY" -H "X-Timestamp: $TS" -H "X-Signature: $SIG" \
-H "Content-Type: application/json" \
-d "$BODY"The response carries the one-time depositAddress.value, the locked rate in crypto.rateLocked, the amount in crypto.amountDue, expiresAt (one hour by default) and a checkoutId. Show the customer the address and amount, or send them to /pay/<checkoutId>, a no-login payment page. To bring them back to your store afterwards, pass a successUrl and cancelUrl (hosted checkout). Never share the invoice id.
Common refusals: 400 for an unsupported or disabled asset, 400 BELOW_MINIMUM_INVOICE on chains where Payaries pays the gas (read minimumUsd from the error), 403 ONBOARDING_REQUIRED, 400 REDIRECT_URL_NOT_ALLOWED when a successUrl or cancelUrl host isn't one of your redirect domains, and 402 FEE_WALLET_INSUFFICIENT for assets that require a funded fee wallet.
054. Handle the webhook
Payaries POSTs a signed event on every status change. Verify X-Gateway-Signature against the raw body first (how), then dedupe on idempotencyKey and make your handler idempotent on (invoiceId, status).
{
"event": "invoice.status_changed",
"idempotencyKey": "3f9c1a...",
"invoiceId": "66f...",
"status": "confirmed",
"referenceId": "order_10231",
"timestamp": 1725700000000,
"data": { "attempt": 0 }
}| Status | Meaning | Do |
|---|---|---|
pending | Waiting for the customer | Nothing |
detected, confirming | Seen on-chain, collecting confirmations | Show "payment received, confirming" |
confirmed | Confirmations reached; your ledger is credited | Fulfil the order |
forwarding, settled | Swept to your Payaries wallet; now withdrawable | Nothing (reconcile) |
underpaid | Less than the amount due arrived | See underpaid payments |
expired | No payment before the deadline | Release the order. Final, unless an event later moves it out |
failed | The invoice failed | Don't fulfil; contact support if funds were sent |
Fulfil on confirmed, not on a wallet or explorer: a different token sent to the address, including a fake one with a real-looking name, is flagged on the invoice and never counted.
065. Check the balance and withdraw
GET /v1/merchants/me/balance returns four buckets per chain and asset: available (withdrawable now), pendingSweep (credited, awaiting the sweep to your wallet), pending (reserved by a withdrawal in flight) and frozen (an admin hold, normally zero). A withdrawal is debited from available only; asking for more is a 409.
Quote first, then create the withdrawal with an Idempotency-Key. The details are in the withdrawals guide.
07Go-live checklist
- Signing tested against a
GETwith a query string and aPOST, using the published test vector. - Every retry re-signs; every withdrawal retry reuses its
Idempotency-Key. - Webhook endpoint: public HTTPS, no redirects, verifies the signature on the raw body, dedupes, answers
2xxwithin 10 seconds. - Order logic tolerates a status change out of
expired, and alerts onunclaimedDepositsorlatePaymentDetectedAt. - If you use hosted checkout: redirect domains are registered, and the return route shows a result but fulfils only from the webhook.
- Secrets live in a secrets manager; the API-key IP whitelist is set to your servers.
- A small real payment ran end to end: create, pay,
settled, withdraw.
Questions
- Why does POST /v1/invoices return ONBOARDING_REQUIRED?
- Submitting the business profile is mandatory before any invoice, test or live, from the API or the dashboard. Submit it once in the dashboard; submitting is enough to start testing.
- When should I fulfil the order?
- When the invoice reaches confirmed, learned from a signature-verified webhook or from GET /v1/invoices/:id. Your ledger is credited at that moment; the amount becomes withdrawable once the sweep settles.
- How do I avoid creating duplicate invoices?
- Use a unique referenceId per order. Sending the same referenceId again returns the existing invoice.
Keep reading
- Build a crypto payment integration with an AI agent, safelyEverything an AI agent or coding assistant needs to integrate Payaries: an OpenAPI spec, llms.txt, markdown docs, signing test vectors and the rules for handling real funds safely.
- How to sign crypto payment API requests (HMAC-SHA256)How to sign Payaries API requests with HMAC-SHA256, with working Node.js, Python, Go and shell code and published test vectors to check your implementation against.
- Hosted crypto checkout: send the customer, get them backUse Payaries's hosted payment page without building a checkout: create an invoice with a success and cancel URL, redirect the customer, verify the signed return and fulfil from the webhook.
- Crypto payment API errors, rate limits and safe retriesEvery status code and error code the Payaries API returns, what each means, whether to retry it, the rate limits, and a retry loop that never double-pays.
- Withdrawing crypto through the API: quote, idempotency and approvalHow to withdraw crypto through the Payaries API: check the balance, quote the fees, create an idempotent withdrawal, follow its status and understand auto-approval.
- A crypto payment API that behaves like the rest of your stackA REST crypto payment API: create an invoice, get a one-time deposit address, receive signed webhooks and withdraw on demand. HMAC-signed and idempotent.
- Accept crypto on Shopify without payments-partner approvalHow Payaries's Shopify connector works: a manual payment method or a cart-page button, the hosted pay page, how orders are marked paid, the order tags to watch, and the limits. Early access.