G

Integration Guide

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/sdk installed (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.