Quick start
Create a Test v2 session and verify an order on your server.
Create a Test v2 payment session, open checkout and verify one test order. You need a merchant backend: requests, secret storage and payment verification run on your server. This walkthrough is not a complete production application. Implement the complete webhook verifier before processing events; use the session guide for the full contract. Existing v1 invoices remain supported for older integrations.
1. Prepare the project
Register and verify your email, select a project, then select Test in the dashboard. Register a Test receiving wallet that you control and explicitly accept USDT on TRON Shasta. A Live wallet registration does not become a Test wallet automatically. BramaPay never needs its private key or recovery phrase.
Configure successUrl, cancelUrl and exact allowedRedirectDomains. Add an active public HTTPS webhook endpoint, securely save its one-time secret and keyId, and implement signature verification before sending a connection test. Create a Test API secret for this project and keep it on your server. See project setup and return URLs.
Test requires enabled Test availability. If unavailable, contact support and use local fixtures to test verification; do not silently switch to Live. Test tokens cannot pay real orders or fund the Live service balance.
2. Create one Test session
Persist the order identity, expected project/mode, exact body and idempotency key before sending. After an uncertain timeout or lost response, retry the same body with the same key. Do not issue another order or bypass a conflict with a new key. Amounts are decimal strings, never JavaScript floating-point numbers.
curl --request POST 'https://api.bramapay.com/v2/payment-sessions' \
--header 'X-Api-Key: YOUR_TEST_PROJECT_SECRET_KEY' \
--header 'Idempotency-Key: order-demo-1042-attempt-1' \
--header 'Content-Type: application/json' \
--data '{"amountUsd":"25.00","currency":"USD","externalId":"order-demo-1042"}'The key selects project and mode. Do not send wallet IDs, projectId, mode or return-URL overrides. Optional fields and buyer-fee contracts are documented in the session guide and buyer pricing.
3. Save the response
Bind the returned session ID, project, mode, external order ID, currency, amount and immutable pricing snapshot to your order before opening checkout. This is a partial synthetic response, with an intentionally fake capability and reserved example domain; it is not the complete schema or payment instructions.
{
"sessionId": "00000000-0000-4000-8000-000000000001",
"projectId": "prj_00000000000000000000000000000000",
"externalId": "order-demo-1042",
"mode": "TEST",
"paymentMode": "TEST",
"amountUsd": "25",
"currency": "USD",
"status": "OPEN",
"checkoutUrl": "https://checkout.example/en/checkout/00000000-0000-4000-8000-000000000001#token=EXAMPLE_NOT_A_REAL_CAPABILITY",
"routes": [],
"attempts": []
}routes: [] means no selectable route is available. Do not invent one or ask for a transfer. New hosted attempts use USDT; registry entries do not establish session availability. Previously issued attempts retain their instructions.
4. Open checkout
Use the returned checkoutUrl unchanged. Its fragment is a bearer capability: keep the full URL out of logs and analytics. Keep API secrets out of browser code. Never construct the capability URL yourself or put its token in a query string.
The buyer chooses an available network and follows the current address, token, exact amount and deadline once. The QR contains the address only. Do not round, split transfers, calculate the buyer's token amount yourself or ask for a difference payment. Changing routes does not extend expiry. Follow your first Test payment for test-wallet operations.
5. Verify confirmation
Run the complete raw-body verifier before JSON business processing: enforce the body limit, timestamp freshness within 300 seconds, signed event ID/type, key-ID secret selection, exact protocol v2 envelope and constant-time HMAC comparison. Require X-Idempotency-Key === X-Event-Id. Retain uncompromised old secrets for existing delivery snapshots. The namespace is literally vaultless.webhook (the historical protocol name; keep it exactly as is); API v2 and webhook protocol v2 are separate versions.
Only payment_session.paid is the session fulfillment event. integration.test, webhook.test, a browser redirect and a child invoice event cannot authorize session fulfillment. A Test event must never pay a Live order. After signature and payload validation, read the session from your backend:
curl 'https://api.bramapay.com/v2/payment-sessions/SESSION_ID' \
--header 'X-Api-Key: YOUR_TEST_PROJECT_SECRET_KEY'Require authenticated status === "PAID" and match the saved session, order, project, mode, currency and expected pricing contract. Compare decimal values exactly. Project-managed buyer pricing preserves order value in integration amountUsd; explicit BUYER_FEE_V1 has different semantics. Do not confuse order value, payable USD and exact token amount.
Persist event deduplication and once-only order fulfillment in one database transaction, using unique event and order constraints and an outbox for delivery. Return 2xx only after durable acceptance; transient lookup/storage failures should retry. See confirm an order and delivery retries.
6. Before Live
Configure separate Live wallets, secrets and webhooks; successfully test every current Live endpoint/configuration. Check concrete readiness blockers, available routes and the effective account fee. New Live creation requires B + C > 0 (actual service balance B plus approved credit C). Credit defaults to zero. Previously issued payments continue processing and can increase debt beyond that threshold. Fund through Billing, using its separate treasury instructions.
Exercise invalid signatures, wrong mode/order/event, duplicate events and fulfillment, unavailable routes, expiry and uncertain creation with local fixtures. A bare 503 does not prove refusal: only a validated PAYMENT_CREATION_DECLINED receipt with matching identity, retryable: false and sessionCreated: false establishes terminal rejection. Preserve it.
Do not infer finality from the countdown: a timely transfer may confirm later. Check authoritative status, monitoringComplete and isFinal. For wrong, late or additional transfers, stop and investigate; do not automatically request more money or promise refunds. Successful tests do not establish production availability.