Backend Verification
Read this page when a completed widget flow unlocks something valuable, such as an order, subscription, account credit, or in-app balance.
Should you read this?
Yes, if your app treats TokenFlight as a payment step. Browser callbacks are useful for UI, but your backend should decide whether a payment is complete.
If you are only building a demo, you can come back to this page later.
Success callbacks run in the user's browser and can be spoofed. For any business-critical flow (e-commerce payments, SaaS subscriptions, etc.), always verify the order server-side.
Verify via API
After receiving onSwapSuccess or onDepositSuccess on the frontend, confirm the order on your backend:
GET <your-api-endpoint>/v1/orders/:walletAddressThis returns a paginated list of orders for the given address, including status, amounts, and transaction hashes.
Verification Flow
1. Frontend: success callback fires with { orderId, txHash, ... }
2. Frontend: POST to your backend with orderId and txHash
3. Backend: GET /v1/orders/:address from the API
4. Backend: Find the order matching the orderId
5. Backend: Verify status is "filled" or another terminal status
6. Backend: Confirm amounts match expected values
7. Backend: Mark payment as verified in your databaseExample: Express.js Verification Endpoint
const API_ENDPOINT = process.env.HYPERSTREAM_API_URL;
app.post('/api/verify-payment', async (req, res) => {
const { orderId, walletAddress } = req.body;
// Query the API directly — don't trust frontend data
const response = await fetch(
`${API_ENDPOINT}/v1/orders/${walletAddress}`
);
const data = await response.json();
// Find the specific order
const order = data.data?.find((o) => o.id === orderId);
if (!order) {
return res.status(404).json({ error: 'Order not found' });
}
if (order.status !== 'filled') {
return res.status(400).json({ error: 'Order not yet complete', status: order.status });
}
// Verify the order matches your expected payment
// (check token, amount, recipient, etc.)
// Mark as verified in your database
await db.payments.update({
where: { orderId },
data: { verified: true },
});
return res.json({ verified: true });
});Transaction Hash Verification
The txHash from the success callback is the source chain transaction hash. You can also verify it directly on the source chain's block explorer or via an RPC call:
- EVM chains: Query the transaction receipt via
eth_getTransactionReceipt - Solana: Query via
getTransactionRPC method
This confirms the transaction was actually broadcast and included in a block.
Security Best Practices
- Never trust frontend callbacks alone for payment verification
- Always query the API from your backend using the wallet address and order ID
- Validate amounts and tokens — ensure the order matches what you expected
- Check for terminal status — only accept orders with a
filledstatus - Idempotency — handle duplicate verification requests gracefully
Next step
- Need to know when callbacks fire? Read Events & Callbacks.
- Need the full order lifecycle? Read Transaction Lifecycle.