Payments
OpacusPay — 0G App Integration
Send USDC.e payments on 0G Mainnet or Base from your app in a single API call. No wallet management, no gas juggling — Opacus handles execution.
Live on 0G Mainnet. OpacusPay executes real on-chain USDC.e transfers on 0G (chain ID 16661) and USDC on Base (chain ID 8453). Transactions confirm in <5 seconds on 0G.
How it works
Your app calls the Opacus REST API with a recipient address, amount, and chain. Opacus signs and broadcasts the on-chain transfer from your execution wallet, returns the tx hash, and records the payment in your history.
- Your app backend calls
POST /api/x402/settlewith an Opacus API key. - Opacus verifies balance, signs the USDC transfer, and broadcasts it.
- Tx hash + explorer URL are returned immediately after on-chain confirmation.
- Payment is recorded in your history (queryable via
GET /api/x402/payments).
Execution wallet. Every Opacus API key has a deterministic execution wallet on both Base and 0G. Fund it with USDC (Base) or USDC.e (0G) + a small amount of native gas (ETH on Base, A0GI on 0G) before making payments.
Supported chains
| Chain | chain value | Token | Contract | Explorer |
|---|---|---|---|---|
| 0G Mainnet | 0g |
USDC.e | 0x1f3aa82227281ca364bfb3d253b0f1af1da6473e | chainscan.0g.ai |
| Base Mainnet | base |
USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | basescan.org |
| Stellar Testnet | stellar |
USDC / XLM | Native / Stellar Asset | stellar.expert |
| Arc Testnet | arc |
USDC | 0x1f3aa82227281ca364bfb3d253b0f1af1da6473e | explorer.testnet.arc.network |
Authentication
Pass your API key in either header:
HEADERS
X-Opacus-Api-Key: opak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # or Authorization: Bearer opak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Get your API key from Agentboard → Settings → API Keys.
Send a payment
POST
https://opacus.xyz/api/x402/settle
{
"recipient": "0xRecipientAddress", // required — destination EVM address
"amountUsdc": 1.50, // required — USDC amount (max 1000)
"chain": "0g", // required — "0g" or "base"
"memo": "invoice #42", // optional — up to 200 chars
"idempotencyKey": "my-app-txn-id-001" // optional — prevents duplicate sends on retry
}Request fields
| Field | Type | Description |
|---|---|---|
| recipient | string | required — destination 0x EVM address |
| amountUsdc | number | required — amount in USDC (0 < amount ≤ 1000) |
| chain | string | required — "0g" or "base" |
| memo | string | optional — payment note, max 200 chars |
| idempotencyKey | string | optional — unique key; if the same key is re-submitted the original tx is returned (safe retries) |
Response
200 OK
{
"ok": true,
"settled": true,
"txHash": "0xabc123...",
"chain": "0g",
"amountUsdc": 1.50,
"explorerUrl": "https://chainscan.0g.ai/tx/0xabc123...",
"status": "confirmed",
"replayed": false // true if idempotencyKey was already used
}400 Bad Request
{
"ok": false,
"settled": false,
"error": "Insufficient USDC.e balance for x402 payment. Have: 0.000000, Need: 1.500000 on 0g"
}Code examples
TSsend payment on 0G
const OPACUS_API_KEY = process.env.OPACUS_API_KEY; // opak_xxx
async function sendPayment(recipient: string, amountUsdc: number) {
const res = await fetch('https://opacus.xyz/api/x402/settle', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Opacus-Api-Key': OPACUS_API_KEY,
},
body: JSON.stringify({
recipient,
amountUsdc,
chain: '0g',
memo: 'payment from my 0G app',
idempotencyKey: `txn-${Date.now()}`,
}),
});
const data = await res.json();
if (!data.ok) throw new Error(data.error);
console.log('Tx hash:', data.txHash);
console.log('Explorer:', data.explorerUrl);
return data;
}
// Usage
await sendPayment('0xRecipientAddress', 1.50);List payment history
GET
https://opacus.xyz/api/x402/payments
GET /api/x402/payments?chain=0g&limit=20 X-Opacus-Api-Key: opak_xxx
| Query param | Type | Description |
|---|---|---|
| chain | string | optional — filter by 0g or base |
| limit | number | optional — max results, default 50, max 200 |
200 OK
{
"ok": true,
"count": 2,
"payments": [
{
"id": "x402_lv2abc",
"chain": "0g",
"recipient": "0xRecipientAddress",
"amountUsdc": 1.50,
"txHash": "0xabc123...",
"explorerUrl": "https://chainscan.0g.ai/tx/0xabc123...",
"memo": "invoice #42",
"status": "confirmed",
"createdAt": "2026-04-19T10:22:31.000Z"
}
]
}Fund your execution wallet
Find your execution wallet address in Agentboard → Billing → Balance tab.
0G network (for chain: "0g")
- Bridge USDC.e to 0G using Opacus Bridge or any 0G bridge.
- Send a small amount of A0GI (native gas, ≥ 0.001 A0GI) to the execution wallet address.
- USDC.e contract: 0x1f3aa82227281ca364bfb3d253b0f1af1da6473e
Base network (for chain: "base")
- Send USDC to the execution wallet on Base.
- Send a small amount of ETH (native gas, ≥ 0.001 ETH) to the execution wallet address.
- USDC contract: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Gas required. 0G transactions require A0GI for gas. If the execution wallet has no A0GI, the payment will fail with "Insufficient A0GI (native gas)". Always keep ≥ 0.01 A0GI in the wallet.
Idempotency (safe retries)
Pass a unique idempotencyKey with every request. If your network request fails before you receive a response, resend the exact same body — Opacus will return the original transaction instead of sending a second payment.
Tip: Use your internal transaction/invoice ID as the idempotencyKey. Example:
"idempotencyKey": "order-8821"
Error reference
| Error message | Cause | Fix |
|---|---|---|
| recipient must be a valid 0x EVM address | Invalid recipient | Pass a 42-char hex address starting with 0x |
| amountUsdc must be between 0 and 1000 | Amount out of range | Use a value between 0.000001 and 1000 |
| chain must be base or 0g | Unknown chain string | Use exactly "base" or "0g" |
| Insufficient USDC.e balance … | Not enough USDC.e in execution wallet | Bridge more USDC.e to the execution wallet on 0G |
| Insufficient A0GI (native gas) … | No gas in execution wallet on 0G | Send ≥ 0.01 A0GI to the execution wallet |
| API key is required | Missing or wrong auth header | Include X-Opacus-Api-Key header with your key |
Full integration example (Next.js API route)
TSapp/api/checkout/route.ts
// Next.js 14 App Router — pay a seller on 0G after checkout
export async function POST(req: Request) {
const { sellerWallet, amountUsdc, orderId } = await req.json();
const res = await fetch('https://opacus.xyz/api/x402/settle', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Opacus-Api-Key': process.env.OPACUS_API_KEY!,
},
body: JSON.stringify({
recipient: sellerWallet,
amountUsdc: amountUsdc,
chain: '0g',
memo: `Order ${orderId}`,
idempotencyKey: `order-${orderId}`, // idempotent — safe to retry
}),
});
const data = await res.json();
if (!data.ok) {
return Response.json({ error: data.error }, { status: 400 });
}
return Response.json({
success: true,
txHash: data.txHash,
explorerUrl: data.explorerUrl,
});
}
That's it. No wallet management, no private keys in your frontend, no gas estimation. Opacus handles signing, broadcasting, and confirmation tracking. You get back a tx hash in under 5 seconds on 0G.
Related
- Escrow API — lock funds before releasing on task completion
- Bridge API — move USDC between Base ↔ 0G
- Authentication — API key scopes and wallet binding
- Funds & Locks — balance, deposits, withdrawals