Quick Start
Get an AI Agent accepting QR payments in under 5 minutes. This guide walks through the complete flow — from account setup to receiving your first payment and verifying it via webhook.
Prerequisites
Before you begin, you'll need:
- An ItPay Platform account — Register at itpay.ai (free tier available).
- An API key — Generate one from the API Keys section of your dashboard. You'll receive a key like
sk_live_xxxxxxxxxxxxxxxx. - A supported runtime — Node.js 18+, Python 3.9+, or Go 1.21+.
That's it. No merchant account, no card processing setup, no bank verification.
The free tier supports up to 100 payment intents per day across all supported channels. Upgrade to a paid plan for higher limits and priority channel routing.
Step 1: Install the SDK
ItPay provides official SDKs for the three most common agent development environments.
Node.js / TypeScript
npm install @itpay/mcp
Python
pip install itpay-sdk
Go
go get github.com/itpay-ai/itpay-go
The SDKs wrap the ItPay REST API and provide typed clients for all protocol operations — ServiceManifest management, PaymentIntent creation, QR generation, and webhook verification.
Step 2: Configure Your Credentials
Set your API key and default payment channel as environment variables. These are picked up automatically by the SDK.
export ITPAY_API_KEY=sk_live_xxxxxxxxxxxxxxxx
export ITPAY_CHANNEL=alipay
Alternatively, configure them programmatically in your code:
- TypeScript
- Python
- Go
import { ItPayClient } from '@itpay/mcp';
const client = new ItPayClient({
apiKey: 'sk_live_xxxxxxxxxxxxxxxx',
channel: 'alipay', // See the Channel Matrix for supported values
});
from itpay_sdk import ItPayClient
client = ItPayClient(
api_key='sk_live_xxxxxxxxxxxxxxxx',
channel='alipay',
)
import "github.com/itpay-ai/itpay-go/itpay"
client := itpay.NewClient(&itpay.Config{
APIKey: "sk_live_xxxxxxxxxxxxxxxx",
Channel: "alipay",
})
Supported channels: alipay, wechat, promptpay, paynow, duitnow, vietqr, gcash, usdc. See the Channel Matrix for full details on region support and settlement currencies.
Step 3: Create a ServiceManifest
A ServiceManifest is your agent's public payment declaration — it tells the world what your service does, how much it costs, and which payment channels you accept. Every paying agent needs one.
Create a manifest by posting to the ItPay API:
import { ItPayClient } from '@itpay/mcp';
const client = new ItPayClient({
apiKey: 'sk_live_xxxxxxxxxxxxxxxx',
});
const manifest = await client.manifests.create({
name: 'Smart Summary',
description: 'AI-powered document summarization — upload any PDF and get concise summaries.',
payment_methods: {
one_time: true,
},
pricing: {
one_time: [
{ amount: 99, currency: 'USD', label: 'per summary' },
],
},
accepted_channels: ['alipay', 'wechat'],
qr_mode: 'dynamic',
settlement_currency: 'USD',
endpoint: 'https://api.myservice.ai/itpay/v1',
});
console.log(`Manifest created: ${manifest.id}`);
// → Manifest created: 01J7XYKZ1A2B3C4D5E6F7G8H9I
The response includes the manifest id, which you'll use in every subsequent payment request. Store it for later use.
Step 4: Accept a Payment
This is the core flow: create a PaymentIntent, generate a QR code, and wait for the human to scan and pay.
How the payment flow works (click to expand)
- Your agent creates a PaymentIntent via the ItPay API.
- ItPay routes the intent to the chosen channel and returns a QR code URL.
- Your agent displays the QR code to the human user.
- The human scans the QR code with their wallet app (e.g., Alipay, WeChat Pay).
- The wallet app shows the payment amount and asks the human to confirm.
- After confirmation, ItPay sends a webhook to your
endpointURL. - Your agent processes the webhook and delivers the service.
Here's the complete TypeScript example:
import { ItPayClient } from '@itpay/mcp';
import { randomUUID } from 'crypto';
const client = new ItPayClient({
apiKey: 'sk_live_xxxxxxxxxxxxxxxx',
channel: 'alipay',
});
async function requestPayment(): Promise<void> {
// 1. Create the PaymentIntent
const intent = await client.paymentIntents.create({
id: `pi_${randomUUID()}`, // Unique, idempotent key
service_id: '01J7XYKZ1A2B3C4D5E6F7G8H9I', // Your ServiceManifest ID
type: 'one_time',
amount: {
currency: 'CNY',
value: 699, // 6.99 CNY in minor units
},
description: 'AI document summary (42 pages)',
payer: {
agent_id: 'agent_cli_a1b2c3d4',
human_id: 'user_abc_789',
},
metadata: {
session_id: 'sess_xyz_456',
},
});
console.log(`Intent created: ${intent.id}`);
console.log(`Status: ${intent.status}`); // → "pending"
// 2. Generate the QR code
// The API returns a QRCharge with a scan URL.
const qrCharge = await client.qr.generate(intent.id);
console.log(`QR scan URL: ${qrCharge.scan_url}`);
console.log(`QR expires at: ${intent.expires_at}`);
// 3. Display the QR to the user (framework-specific)
// In a web UI: <img src={qrCharge.scan_url} alt="Pay with Alipay" />
// In a CLI: open the URL in the browser
// In a chat: send the image inline
console.log('\nWaiting for payment...');
// 4. Wait for webhook callback (see Step 5)
// The SDK provides a polling helper for development:
const result = await client.paymentIntents.waitForCompletion(intent.id, {
timeout: 300_000, // 5 minutes
pollInterval: 2_000, // poll every 2 seconds
});
if (result.status === 'succeeded') {
console.log('✓ Payment received!');
// Deliver the service...
} else {
console.log(`✗ Payment failed: ${result.status}`);
}
}
requestPayment().catch(console.error);
What happens at each step
| Step | Component | What occurs |
|---|---|---|
| 1 | paymentIntents.create() | ItPay validates the amount, channel, and service. Returns a pending intent. |
| 2 | qr.generate() | ItPay contacts the payment channel, generates a time-bound QR code, and returns the scan_url. Intent transitions to qr_generated. |
| 3 | User display | The user sees the QR code. They scan it with their wallet app. |
| 4 | Wallet app | The wallet shows ¥6.99 CNY and asks for confirmation. Intent → scanning → authorized. |
| 5 | Webhook | ItPay POSTs a signed payload to your endpoint. Your handler verifies and captures. |
Step 5: Verify Payment with a Webhook Handler
When a payment completes, ItPay sends a signed webhook POST to the endpoint URL you specified in your ServiceManifest. Your handler must:
- Verify the HMAC signature to confirm the webhook is from ItPay (and not an attacker).
- Idempotency-check the event ID to prevent duplicate processing.
- Capture or acknowledge the payment.
Here's a complete webhook handler in Python using Flask:
import os
import hmac
import hashlib
import json
from flask import Flask, request, jsonify
app = Flask(__name__)
# Must match the webhook secret from your ItPay dashboard
WEBHOOK_SECRET = os.environ.get('ITPAY_WEBHOOK_SECRET', 'whsec_xxxxxxxxxxxxxxxx')
PROCESSED_EVENTS = set() # Use Redis or DB in production
def verify_signature(payload: bytes, signature: str, timestamp: str) -> bool:
"""Verify the HMAC-SHA256 signature on the webhook payload."""
signed_payload = f"{timestamp}.{payload.decode('utf-8')}".encode('utf-8')
expected = hmac.new(
WEBHOOK_SECRET.encode('utf-8'),
signed_payload,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature)
@app.route('/itpay/v1/webhook', methods=['POST'])
def webhook():
# 1. Read headers
signature = request.headers.get('X-ItPay-Signature')
timestamp = request.headers.get('X-ItPay-Timestamp')
if not signature or not timestamp:
return jsonify({'error': 'Missing signature headers'}), 401
# 2. Verify signature
if not verify_signature(request.data, signature, timestamp):
return jsonify({'error': 'Invalid signature'}), 401
# 3. Parse event
event = request.get_json(force=True)
event_id = event['id']
event_type = event['type'] # e.g. "payment_intent.succeeded"
# 4. Idempotency check
if event_id in PROCESSED_EVENTS:
return jsonify({'status': 'already_processed'}), 200
PROCESSED_EVENTS.add(event_id)
# 5. Handle the event
if event_type == 'payment_intent.succeeded':
intent = event['data']
print(f"✓ Payment received! Intent: {intent['id']}")
print(f" Amount: {intent['amount']['value']} {intent['amount']['currency']}")
print(f" Channel: {intent['channel']}")
print(f" Metadata: {intent.get('metadata', {})}")
# TODO: Deliver the service to the user here
# - Look up session_id from intent['metadata']
# - Unlock the content or grant access
# - Update your internal database
elif event_type == 'payment_intent.failed':
intent = event['data']
print(f"✗ Payment failed: {intent['id']} — {intent.get('failure_reason', 'unknown')}")
elif event_type == 'payment_intent.expired':
intent = event['data']
print(f"⏰ Payment expired: {intent['id']}")
# 6. Acknowledge receipt (200 OK)
return jsonify({'status': 'received'}), 200
if __name__ == '__main__':
app.run(port=8080)
Testing the webhook locally
# Start your webhook handler
python webhook_handler.py
# Use ngrok to expose it to the internet
ngrok http 8080
# → Forwarding https://abc123.ngrok.io → http://localhost:8080
# Update your ServiceManifest's endpoint to the ngrok URL
# https://abc123.ngrok.io/itpay/v1/webhook
Once your endpoint is live, ItPay will deliver payment events to it in real time. You can also replay missed events from the dashboard.
Next Steps
You now have an agent that can accept QR payments end-to-end. Here's where to go from here:
| Resource | Description |
|---|---|
| API Reference | Full specification of all 9 core capabilities — broadcast, install, one-time pay, cumulative pay, subscribe, refund, void, KYC/KYB |
| MCP Integration | Connect your agent using the Model Context Protocol so payment tools are auto-discovered |
| Architecture Overview | Deep dive into the two-layer protocol design and four-party model |
| Core Objects | Complete reference for PaymentIntent, ServiceManifest, QRCharge, Subscription, and Invoice |
| SDK Documentation | TypeScript, Python, and Go SDK reference with full type definitions |
| Channel Matrix | Supported channels, regions, settlement currencies, and fees |
| GitHub | Open-source protocol specification and reference implementations |
What's next for your agent?
- Broadcast your manifest via MCP tool discovery so any ItPay-compatible agent can find and pay your service.
- Handle cumulative billing for usage-based pricing (e.g., per-token, per-request).
- Offer subscriptions for recurring access with plans and quotas.
- Integrate multiple channels so users in Thailand can pay via PromptPay, users in China via Alipay — all through the same integration.