Integration Guide
SDK reference, developer onboarding, and error codes for integrating Gao Payment into applications and agent workflows.
Prerequisites
-
A registered Gao Domain (see Gao Domain docs)
-
A signed payment CAP token issued by your domain owner
-
@gao/sdkinstalled (npm install @gao/sdk)
CAP Token Issuance Flow
Before any payment can be initiated programmatically, a domain owner must issue a signed payment CAP token. This is a one-time setup per integration deployment.
Developer Domain Owner Gao Payment Layer
│ │ │
│── define capability ───────▶️│ │
│ manifest │ │
│ (amount, currencies, │ │
│ networks, budget) │ │
│ │ │
│◀️── reviews scope ──────────│ │
│ and risk tier │ │
│ │ │
│ │── signs CAP token ───────▶️│
│ │ (wallet signature) │
│ │ │
│◀️────────────── cap_id + token returned ────────────────│
│ │
│── set GAO_PAYMENT_CAP_TOKEN in env ─────────────────── │
│── initialize SDK ──────────────────────────────────────▶️│
│ │
│ runtime validates:
│ - aud == payment.gao.systems
│ - domain ownership (L5)
│ - nonce not replayed
│ - not expired
│ - signature valid
│
│◀️── ACTIVE (ready to create intents) ───────────────────│
---
### Quick Start
#### 1\. Install
npm install @gao/sdk
#### 2\. Initialize
import { GaoPayment } from '@gao/sdk';
const payment = new GaoPayment({
payerDomain: 'yourdomain.gao',
capToken: process.env.GAO_PAYMENT_CAP_TOKEN,
environment: 'production', // or 'testnet'
});
#### 3\. Create a Payment Intent
const intent = await payment.intents.create({
payeeDomain: 'shop.gao',
amount: '25.00',
currency: 'USDC',
idempotencyKey: `order-${orderId}-pay`,
metadata: { orderId, initiatedBy: 'my-checkout-agent' },
});
console.log(intent.intentId); // pi_abc123
console.log(intent.status); // PENDING_AUTH or AUTHORIZED (if Tier 0-1)
4. Wait for Settlement
const receipt = await payment.intents.waitForSettlement(intent.intentId, {
timeoutMs: 60000, // 60 seconds
pollIntervalMs: 2000,
});
console.log(receipt.status); // 'settled'
console.log(receipt.settlement.txHash); // on-chain tx
console.log(receipt.receiptId); // rcpt_pay_abc123
---
Core SDK Modules
`payment.intents`
// Create
const intent = await payment.intents.create({
payeeDomain: string,
amount: string, // decimal string, e.g. "25.00"
currency: string, // "USDC" | "USDT" | "Pay$"
network?: string, // auto-routed if omitted
idempotencyKey?: string,
metadata?: Record<string, string>,
expiresInSeconds?: number, // default: 900 (15 min)
});
// Get status
const intent = await payment.intents.get('pi_abc123');
// List
const intents = await payment.intents.list({
payeeDomain: 'shop.gao',
status: 'settled',
since: '2026-01-01T00:00:00Z',
limit: 50,
});
// Wait for settlement (polling)
const receipt = await payment.intents.waitForSettlement('pi_abc123', {
timeoutMs: 120000,
});
payment.receipts
// Get
const receipt = await payment.receipts.get('rcpt_pay_abc123');
// Verify
const result = await payment.receipts.verify('rcpt_pay_abc123');
console.log(result.valid, result.onChainMatch, result.anchorValid);
// List
const receipts = await payment.receipts.list({
payerDomain: 'yourdomain.gao',
since: '2026-01-01T00:00:00Z',
status: 'settled',
limit: 100,
});
`payment.budget`
// Check remaining budget
const budget = await payment.budget.remaining({
capTokenId: 'cap_pay_abc123',
period: 'daily', // 'per_transaction' | 'daily' | 'monthly'
});
console.log(budget.used); // "250.00 USDC"
console.log(budget.remaining); // "1750.00 USDC"
console.log(budget.limit); // "2000.00 USDC"
Handling Risk Tiers#
Tier 0–1 (Auto-approved)
Intents resolve automatically without any user interaction. Use waitForSettlement() after creation.
Tier 2 (In-band confirmation)
const intent = await payment.intents.create({ ... });
if (intent.status === 'AWAITING_CONFIRMATION') {
// Present confirmation UI to payer
const confirmed = await showConfirmationUI({
amount: intent.amount,
currency: intent.currency,
payee: intent.payeeDomain,
});
if (confirmed) {
await payment.intents.confirm(intent.intentId);
} else {
await payment.intents.abort(intent.intentId);
}
}
Tier 3 (Out-of-band human authorization)
payment.on('intent:tier3_escalation', async (event) => {
await notifyDomainOwner({
contact: event.escalationContact,
intentId: event.intentId,
amount: event.amount,
payee: event.payeeDomain,
deadline: event.authorizationDeadline,
approveUrl: event.approveUrl,
});
});
The domain owner receives the notification, reviews, and signs the authorization via Gao Workspace or a direct wallet interaction. The intent resumes automatically upon authorization.
---
### Webhooks
Subscribe to payment lifecycle events via Gao Workspace → Settings → Webhooks.
#### Webhook Signature Verification
Always verify webhook signatures before processing:
import { verifyPaymentWebhook } from '@gao/sdk';
app.post('/hooks/gao-payment', (req, res) => {
const isValid = verifyPaymentWebhook({
payload: req.rawBody,
signature: req.headers['x-gao-payment-signature'],
secret: process.env.GAO_WEBHOOK_SECRET,
});
if (!isValid) return res.status(401).end();
const event = req.body;
// event.type: 'intent.settled' | 'intent.failed' | 'intent.tier3_escalation'
handleEvent(event);
res.status(200).end();
});
Event Types
Event
Trigger
intent.created
Intent successfully created
intent.validated
Validation passed
intent.rejected
Validation failed
intent.awaiting_confirmation
Tier 2 confirmation required
intent.authorized
Wallet signature received
intent.settled
On-chain confirmation received
intent.confirmation_timeout
Confirmation window exceeded
intent.tier3_escalation
Tier 3 human auth required
Idempotency#
All payment.intents.create() calls accept an idempotencyKey:
-
Scope:
(payerDomain, capTokenId, idempotencyKey) -
Dedup window: 24 hours from intent creation
-
During window: same key returns existing intent (including receipt if completed)
-
After window: new intent is created
// Safe to retry — will not double-charge
const intent = await payment.intents.create({
payeeDomain: 'shop.gao',
amount: '25.00',
currency: 'USDC',
idempotencyKey: `order-12345-payment-v1`, // deterministic, order-scoped
});
---
Retry & Backoff
async function createWithRetry(params, maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await payment.intents.create(params);
} catch (err) {
// Never retry validation errors (PAY_001–PAY_007)
if (err.code?.startsWith('PAY_0') && parseInt(err.code.slice(4)) <= 7) {
throw err;
}
if (attempt === maxAttempts) throw err;
await sleep(1000 * Math.pow(2, attempt - 1)); // exponential backoff
}
}
}
Rate Limits#
Limit
Default
Intent creation requests per minute
60 per domain
Concurrent in-flight intents per domain
10
Receipt queries per minute
200 per domain
Webhook delivery attempts
5 (exponential backoff)
Rate limit responses include Retry-After header. SDK surfaces as PAY_429: RATE_LIMITED.
Testing#
const payment = new GaoPayment({
payerDomain: 'yourapp.testnet.gao',
capToken: process.env.GAO_TESTNET_CAP_TOKEN,
environment: 'testnet',
});
Testnet settlements are not written to production ledger or broadcast on mainnet. All behavior is identical to production. Use testnet USDC faucet at faucet.testnet.gao.
Error Reference#
Code
Message
Resolution
PAY_001
CAP token expired or not found
Issue new CAP token from domain owner
PAY_002
Payee domain not in CAP scope
Add payee to domain_scope in CAP token
PAY_003
Amount exceeds per-transaction ceiling
Reduce amount or request higher CAP ceiling
PAY_004
Daily or monthly budget exhausted
Wait for reset or request higher budget CAP
PAY_005
Currency not in CAP allowlist
Add currency to allowed_currencies
PAY_006
No valid routing path found
Check network compatibility and CAP allowed_networks
PAY_007
Intent expired before authorization
Increase expiresInSeconds or speed up auth flow
PAY_008
Intent already exists (idempotency)
Use existing intent; check idempotency_key
PAY_009
Broadcast failed after 3 retries
Check network status; create new intent
PAY_010
Confirmation timeout
Create new intent; check network congestion
PAY_011
Tier 3 authorization timed out
Re-trigger with fresh intent
PAY_012
Cross-chain bridge not approved
Use same-chain settlement or wait for bridge governance approval
PAY_429
Rate limit exceeded
Check Retry-After header; reduce request frequency
Version Compatibility#
SDK Version
Payment Layer
Status
@gao/sdk@1.x
GP/1.1
✅ Current
@gao/sdk@0.9.x
GP/1.0
⚠️ Deprecated — receipts not cross-compatible
The Gao SDK is the only officially supported integration path for Gao Payment. Always use _@gao/sdk_ — direct calls to internal payment APIs are not guaranteed stable.