ASG Card Documentation

x402-powered virtual card issuance for AI agents on Stellar. Pay with USDC, get a card in seconds.

Base URL https://api.asgcard.dev

Overview

ASG Card exposes a REST API with five classes of endpoints:

TypeAuthDescription
Public None Health check, pricing, tiers
Paid (x402) USDC payment on Stellar via x402 Create/fund cards
Wallet-signed Ed25519 signature Card management

SDK

The official client SDK wraps the raw x402 flow (402 → parse challenge → pay USDC → retry with proof) into one-liner methods. No need to handle the payment handshake yourself.

Install

bash
npm install @asgcard/sdk

Quick Start

typescript
import { ASGCardClient } from '@asgcard/sdk';

const client = new ASGCardClient({
  privateKey: '<stellar_secret_seed>',
  baseUrl: 'https://api.asgcard.dev',
  rpcUrl: 'https://mainnet.sorobanrpc.com',
});

// One line — SDK handles payment automatically
const card = await client.createCard({
  amount: 10,       // $10 tier
  nameOnCard: 'AI AGENT',
  email: 'agent@example.com',
});

console.log(card.details); // { cardNumber, cvv, expiry, … }

Configuration

ParameterTypeRequiredDefaultDescription
privateKey string One of two Stellar secret seed (for signing)
walletAdapter WalletAdapter One of two Stellar wallet adapter (publicKey + signTransaction)
baseUrl string No https://api.asgcard.dev API base URL
rpcUrl string No https://horizon.stellar.org Stellar Horizon or RPC endpoint
timeout number No 60000 Request timeout in milliseconds

Methods

client.createCard(params): Promise<CardResult>

Create a virtual card. Pays USDC automatically.

FieldTypeValues
amountnumber10 | 25 | 50 | 100 | 200 | 500
nameOnCardstringName embossed on card
emailstringDelivery email
typescript
const result = await client.createCard({
  amount: 50,
  nameOnCard: 'AI AGENT',
  email: 'agent@example.com',
});

client.fundCard(params): Promise<FundResult>

Fund an existing card.

FieldTypeValues
amountnumber10 | 25 | 50 | 100 | 200 | 500
cardIdstringUUID of existing card
typescript
const result = await client.fundCard({
  amount: 25,
  cardId: 'card-uuid',
});

client.getTiers(): Promise<TierResponse>

Get pricing tiers and fee breakdown (no payment required).

client.health(): Promise<HealthResponse>

Check if the ASG Card API is reachable.

client.address: string

The Stellar wallet address being used for payments.


Error Handling

typescript
import {
  ASGCardClient,
  InsufficientBalanceError,
  PaymentError,
  ApiError,
  TimeoutError,
} from '@asgcard/sdk';

try {
  const card = await client.createCard({ amount: 50, nameOnCard: 'AI', email: 'a@b.com' });
} catch (error) {
  if (error instanceof InsufficientBalanceError) {
    console.log(`Need ${error.required}, have ${error.available}`);
  } else if (error instanceof PaymentError) {
    console.log(`Payment failed: ${error.message}, tx: ${error.txHash}`);
  } else if (error instanceof ApiError) {
    console.log(`Server error ${error.status}:`, error.body);
  } else if (error instanceof TimeoutError) {
    console.log('Request timed out');
  }
}
ClassFieldsWhen
InsufficientBalanceErrorrequired, availableUSDC balance < required
PaymentErrormessage, txHash?Stellar tx failed
ApiErrorstatus, bodyServer returned non-2xx
TimeoutErrormessageRequest exceeded timeout

Low-Level x402 Utilities

For full control over the payment flow:

typescript
import {
  parseChallenge,
  checkBalance,
  executePayment,
  buildPaymentPayload,
  buildPaymentTransaction,
  handleX402Payment,
} from '@asgcard/sdk';
FunctionSignatureDescription
parseChallenge (input: unknown) → X402Accept Parse 402 challenge, returns first accepted method
checkBalance (params) → Promise<void> Throws InsufficientBalanceError if USDC < required
executePayment (params) → Promise<string> Sends USDC on Stellar, returns txHash
buildPaymentPayload (accepted, signedXDR) → string Builds base64-encoded X-PAYMENT header value
buildPaymentTransaction (params) → Promise<string> Build + sign a Soroban SAC USDC transfer
handleX402Payment (params) → Promise<string> Full cycle: parse → pay → build proof

How It Works

Sequence diagram showing the SDK flow:

MCP Server

The @asgcard/mcp-server package exposes 9 tools via the Model Context Protocol, enabling AI agents to manage ASG Card programmatically.

npm: @asgcard/mcp-server  |  GitHub: mcp-server/
No env vars needed: The MCP server reads your Stellar key from ~/.asgcard/wallet.json automatically. Run asgcard wallet create once, and all MCP clients pick it up.

Agent Quick Start

One command — creates wallet, configures MCP, installs skill:

bash
npx @asgcard/cli onboard -y

First-Class Clients

One-click installer included:

bash
asgcard install --client codex      # OpenAI Codex
asgcard install --client claude     # Claude Code
asgcard install --client cursor     # Cursor

Compatible Agent Runtimes

OpenClaw, Manus, Perplexity Computer, and other MCP-compatible agents work via manual config or the bundled SDK:

Codex (~/.codex/config.toml):

toml
[mcp_servers.asgcard]
command = "npx"
args = ["-y", "@asgcard/mcp-server"]

Cursor / generic MCP (mcp.json):

json
{
  "mcpServers": {
    "asgcard": {
      "command": "npx",
      "args": ["-y", "@asgcard/mcp-server"]
    }
  }
}

SDK / direct API: Use @asgcard/sdk for agents without MCP support.


Tools

All 9 tools exposed by the MCP server:

ToolDescriptionAuth
get_wallet_statusUse FIRST — wallet address, USDC balance, readinessNone
create_cardCreate a virtual MasterCard with a specified tier (10–500 USD)x402
fund_cardAdd funds to an existing cardx402
list_cardsList all cards owned by the walletWallet
get_cardGet card summary (balance, status)Wallet
get_card_detailsRetrieve PAN, CVV, expiryWallet + Nonce
freeze_cardTemporarily block all transactionsWallet
unfreeze_cardRe-enable a frozen cardWallet
get_pricingView pricing tiers and feesNone

Example — create a card via your AI agent:

Just ask your AI agent: "Create a $25 ASG Card for agent ALPHA with email agent@example.com" — the MCP server handles x402 payment, wallet signing, and card creation automatically.

Agent Skill (x402)

The CLI bundles a product-owned asgcard skill that is automatically installed during asgcard onboard.

Bundled (first-class): asgcard onboard installs the skill to ~/.agents/skills/asgcard/
Compatible runtimes: For OpenClaw, Manus, custom LLM pipelines — use the x402-payments-skill or call the SDK/API directly.

CLI

The @asgcard/cli package provides a terminal interface for ASG Card — onboard, create, fund, freeze, and inspect virtual cards from your command line.

npm: @asgcard/cli  |  GitHub: cli/

Install

bash
npm install -g @asgcard/cli

Agent Quick Start:

bash
# Full onboarding (wallet + MCP + skill)
asgcard onboard -y

# Then install for your client:
asgcard install --client codex      # or claude, cursor

# Or step by step:
asgcard wallet create
asgcard wallet info
asgcard card:create -a 10 -n "AGENT ALPHA" -e agent@example.com

Commands

CommandDescription
asgcard wallet createGenerate new Stellar keypair, save to ~/.asgcard/wallet.json
asgcard wallet importImport an existing Stellar secret key
asgcard wallet infoShow public key, USDC balance, deposit instructions
asgcard install --client <c>Configure MCP for codex, claude, or cursor
asgcard onboard [-y]Full onboarding: wallet + MCP + skill + next step
asgcard doctorDiagnose setup (key, API, RPC, balance, MCP configs)
asgcard loginConfigure Stellar private key (legacy)
asgcard whoamiDisplay wallet public key
asgcard cardsList all cards for the wallet
asgcard card <id>Show card summary (balance, status)
asgcard card:details <id>Retrieve PAN, CVV, expiry (nonce-protected)
asgcard card:createCreate a new card (x402 payment)
asgcard card:fund <id>Top up an existing card
asgcard card:freeze <id>Freeze a card
asgcard card:unfreeze <id>Unfreeze a card
asgcard pricingView pricing and fee tiers
asgcard healthCheck API health status

Authentication

ASG Card uses two authentication modes depending on the endpoint.

x402 Payment Flow

Paid endpoints (POST /cards/create/tier/:amount, POST /cards/fund/tier/:amount) use the x402 protocol on Stellar. The flow has 4 steps:

Step 1 — Request without payment

bash
curl -X POST https://api.asgcard.dev/cards/create/tier/10 \
  -H "Content-Type: application/json" \
  -d '{"nameOnCard": "AGENT ALPHA", "email": "agent@example.com"}'

Step 2 — Receive 402 with payment instructions

The server responds with HTTP 402 and a challenge JSON:

json
{
  "x402Version": 2,
  "resource": {
    "url": "https://api.asgcard.dev/cards/create/tier/10",
    "description": "Create ASG Card with $10 load",
    "mimeType": "application/json"
  },
  "accepts": [{
    "scheme": "exact",
    "network": "stellar:pubnet",
    "asset": "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75",
    "amount": "172000000",
    "payTo": "GAHYHA55RTD2J4LAVJILTNHWMF2H2YVK5QXLQT3CHCJSVET3VRWPOCW6",
    "maxTimeoutSeconds": 300,
    "extra": { "areFeesSponsored": true }
  }]
}
FieldDescription
schemeAlways "exact"
network"stellar:pubnet"
assetUSDC SAC on Stellar mainnet
amountAmount in atomic USDC (7 decimals). 1 USDC = 10,000,000
payToASG Treasury public key
maxTimeoutSecondsPayment window (300s)

Step 3 — Agent pays USDC on Stellar

Parse the accepts array and send the specified USDC amount to the payTo address on Stellar, then proceed with facilitator verification if enabled.

Step 4 — Retry with X-PAYMENT header

Re-send the original request with an X-PAYMENT header containing base64-encoded JSON (x402 PaymentPayload):

json
{
  "x402Version": 2,
  "accepted": {
    "scheme": "exact",
    "network": "stellar:pubnet"
  },
  "payload": {
    "transaction": "<BASE64_STELLAR_TX_ENVELOPE>"
  }
}
Transport: X-PAYMENT: base64(JSON) — the SDK handles this automatically. The facilitator verifies and settles the transaction.

Wallet Signature — Free Endpoints

Wallet-signed endpoints (card management) require Ed25519 signature authentication.

Required Headers

HeaderDescription
X-WALLET-ADDRESSStellar public key
X-WALLET-SIGNATUREEd25519 detached signature
X-WALLET-TIMESTAMPUnix timestamp (seconds)

Signature Protocol

text
message = "asgcard-auth:<unixTimestamp>"
algorithm = Ed25519 detached
validity window = ±5 minutes
typescript
const timestamp = Math.floor(Date.now() / 1000);
const message = `asgcard-auth:${timestamp}`;

// wallet.signMessage should return detached Ed25519 signature bytes
const signature = await wallet.signMessage(new TextEncoder().encode(message));

const response = await fetch('https://api.asgcard.dev/cards', {
  headers: {
    'X-WALLET-ADDRESS': wallet.publicKey,
    'X-WALLET-SIGNATURE': Buffer.from(signature).toString('base64'),
    'X-WALLET-TIMESTAMP': String(timestamp),
  },
});

Pricing

Pricing is served by GET /pricing and reflected in the tables below.

All amounts are in USD. 1 USDC = 10,000,000 atomic units (Stellar uses 7 decimal places).

Card Creation

Creating a new virtual card includes the card load amount plus fees.

LoadIssuance FeeTopUp FeeASG FeeTotalEndpoint
Loading pricing from GET /pricing

Card Funding

Adding funds to an existing card — no issuance fee.

Fund AmountTopUp FeeASG FeeTotalEndpoint
Loading pricing from GET /pricing

Endpoints

Public Endpoints

No authentication required.

GET /health

Health check. No authentication required.

Response 200:
json
{
  "status": "ok",
  "timestamp": "2026-02-11T14:00:00.000Z",
  "version": "1.0.0"
}
GET /pricing

Returns full pricing breakdown for all creation and funding tiers.

Response 200:
json
{
  "creation": {
    "tiers": [{
      "loadAmount": 10,
      "totalCost": 17.2,
      "issuanceFee": 3.0,
      "topUpFee": 2.2,
      "ourFee": 2.0,
      "endpoint": "/cards/create/tier/10"
    }]
  },
  "funding": {
    "tiers": [{
      "fundAmount": 10,
      "totalCost": 14.2,
      "topUpFee": 2.2,
      "ourFee": 2.0,
      "endpoint": "/cards/fund/tier/10"
    }]
  }
}
GET /cards/tiers

Returns available tiers with endpoints and detailed fee breakdowns.

Response 200:
json
{
  "creation": [{
    "loadAmount": 10,
    "totalCost": 17.2,
    "endpoint": "/cards/create/tier/10",
    "breakdown": {
      "cardLoad": 10,
      "issuanceFee": 3,
      "topUpFee": 2.2,
      "ourFee": 2,
      "buffer": 0
    }
  }],
  "funding": [{
    "fundAmount": 10,
    "totalCost": 14.2,
    "endpoint": "/cards/fund/tier/10",
    "breakdown": {
      "fundAmount": 10,
      "topUpFee": 2.2,
      "ourFee": 2
    }
  }]
}

These endpoints require USDC payment via the x402 protocol on Stellar. See Authentication → x402 Payment Flow.

POST /cards/create/tier/:amount

Create a new virtual card loaded with the specified tier amount.

Available tiers: 10, 25, 50, 100, 200, 500

Request body:
FieldTypeRequiredDescription
nameOnCardstringYesMin 1 char
emailstringYesValid email
Response 201 Created:
json
{
  "success": true,
  "card": {
    "cardId": "550e8400-e29b-41d4-a716-446655440000",
    "nameOnCard": "AGENT ALPHA",
    "balance": 10,
    "status": "active",
    "createdAt": "2026-02-11T14:00:00.000Z"
  },
  "payment": {
    "amountCharged": 17.2,
    "txHash": "<stellar_tx_hash>",
    "network": "stellar"
  },
  "detailsEnvelope": {
    "cardNumber": "5395000000007890",
    "expiryMonth": 12,
    "expiryYear": 2028,
    "cvv": "123",
    "billingAddress": {
      "street": "123 Main St",
      "city": "San Francisco",
      "state": "CA",
      "zip": "94105",
      "country": "US"
    },
    "oneTimeAccess": true,
    "expiresInSeconds": 300,
    "note": "Store securely. Use GET /cards/:id/details with X-AGENT-NONCE for subsequent access."
  }
}
POST /cards/fund/tier/:amount

Add funds to an existing card.

Request body:
FieldTypeRequiredDescription
cardIdstringYesUUID of existing card
Response 200 OK:
json
{
  "success": true,
  "cardId": "550e8400-e29b-41d4-a716-446655440000",
  "fundedAmount": 25,
  "newBalance": 35.0,
  "payment": {
    "amountCharged": 29.5,
    "txHash": "<stellar_tx_hash>",
    "network": "stellar"
  }
}

Wallet-Signed Endpoints

These endpoints are free but require wallet signature authentication. See Authentication → Wallet Signature.

GET /cards

List all cards owned by the authenticated wallet.

Response 200:
json
{
  "cards": [{
    "cardId": "550e8400-e29b-41d4-a716-446655440000",
    "nameOnCard": "AGENT ALPHA",
    "lastFour": "7890",
    "balance": 10.0,
    "status": "active",
    "createdAt": "2026-02-11T14:00:00.000Z"
  }]
}
GET /cards/:cardId

Get detailed info for a specific card.

Response 200:
json
{
  "card": {
    "cardId": "550e8400-e29b-41d4-a716-446655440000",
    "nameOnCard": "AGENT ALPHA",
    "email": "agent@example.com",
    "balance": 8.5,
    "initialAmountUsd": 10,
    "status": "active",
    "createdAt": "2026-02-11T14:00:00.000Z",
    "updatedAt": "2026-02-11T15:30:00.000Z"
  }
}
GET /cards/:cardId/details

Retrieve sensitive card details — full card number, CVV, expiry, and billing address. See Agent-First Details for the full protocol.

Requires X-AGENT-NONCE header (UUID v4). Rate limited to 5 unique nonces per card per hour. Returns 409 on replay, 403 if owner revoked access.
Required Headers:
HeaderDescription
X-WALLET-ADDRESSStellar public key
X-WALLET-SIGNATUREEd25519 detached signature
X-WALLET-TIMESTAMPUnix timestamp (seconds)
X-AGENT-NONCEUUID v4 — unique per request, anti-replay
Response 200:
json
{
  "details": {
    "cardNumber": "5395000000007890",
    "expiryMonth": 12,
    "expiryYear": 2028,
    "cvv": "123",
    "billingAddress": {
      "street": "123 Main St",
      "city": "San Francisco",
      "state": "CA",
      "zip": "94105",
      "country": "US"
    }
  }
}
Error Responses:
CodeWhenBody
403Owner revoked details access{"error":"Details access revoked by card owner"}
409Nonce already used (replay){"error":"Nonce already used (replay detected)","code":"REPLAY_REJECTED"}
429Rate limit exceeded{"error":"Card details rate limit exceeded (5 requests / hour)"}
POST /cards/:cardId/freeze

Freeze a card. Blocks all transactions until unfrozen.

Response 200:
json
{
  "success": true,
  "cardId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "frozen"
}
POST /cards/:cardId/unfreeze

Unfreeze a previously frozen card.

Response 200:
json
{
  "success": true,
  "cardId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "active"
}

Agent-First Details Access

ASG Card uses an agent-first model for sensitive card data. Card details (number, CVV, expiry) are delivered via two mechanisms designed for autonomous agents.

Details Envelope

When a card is created via POST /cards/create/tier/:amount, the 201 response includes a detailsEnvelope field with full card details:

json
{
  "success": true,
  "card": { "cardId": "...", "status": "active" },
  "payment": { "txHash": "...", "network": "stellar" },
  "detailsEnvelope": {
    "cardNumber": "5395000000007890",
    "expiryMonth": 12,
    "expiryYear": 2028,
    "cvv": "123",
    "billingAddress": {
      "street": "123 Main St",
      "city": "San Francisco",
      "state": "CA",
      "zip": "94105",
      "country": "US"
    },
    "oneTimeAccess": true,
    "expiresInSeconds": 300
  }
}
One-time access: The detailsEnvelope is returned only in the initial 201 response. It is not stored server-side. Agents should persist card details securely on their side.

GET /cards/:cardId/details

If the agent loses the initial envelope, card details can be retrieved via GET /cards/:cardId/details using wallet signature authentication plus a unique nonce.

Required Headers

HeaderTypeDescription
X-WALLET-ADDRESSstringStellar public key (G...)
X-WALLET-SIGNATUREstringEd25519 detached signature (base64)
X-WALLET-TIMESTAMPstringUnix timestamp (seconds)
X-AGENT-NONCEstringUUID v4 — must be unique per request
typescript
import { v4 as uuid } from 'uuid';

const nonce = uuid();
const timestamp = Math.floor(Date.now() / 1000);
const message = `asgcard-auth:${timestamp}`;
const signature = await wallet.signMessage(new TextEncoder().encode(message));

const res = await fetch('https://api.asgcard.dev/cards/<cardId>/details', {
  headers: {
    'X-WALLET-ADDRESS': wallet.publicKey,
    'X-WALLET-SIGNATURE': Buffer.from(signature).toString('base64'),
    'X-WALLET-TIMESTAMP': String(timestamp),
    'X-AGENT-NONCE': nonce,
  },
});

if (res.status === 409) {
  // Nonce replay detected — generate a new UUID and retry
}
if (res.status === 403) {
  // Card owner has revoked details access
}

Nonce & Anti-Replay (409)

Every call to GET /cards/:cardId/details requires a fresh X-AGENT-NONCE (UUID v4). If a nonce has already been used for the same card, the server returns:

json
HTTP/1.1 409 Conflict
{
  "error": "Nonce already used (replay detected)",
  "code": "REPLAY_REJECTED"
}

This prevents replay attacks and ensures each details retrieval is intentional. Combined with the 5-request-per-hour rate limit per card, this protects cardholder data.


Revoke / Restore

Card owners can control whether agents (or themselves, via the portal) can retrieve card details:

ActionEndpointEffect
Revoke POST /cards/:cardId/revoke-details Blocks all future GET /details → returns 403
Restore POST /cards/:cardId/restore-details Re-enables GET /details access

Both endpoints require wallet signature authentication (same headers as card management). Revoked status returns:

json
HTTP/1.1 403 Forbidden
{
  "error": "Details access revoked by card owner"
}

Errors

All non-2xx responses return:

json
{ "error": "Human-readable error message" }
HTTP CodeWhenExample
400 Unsupported tier, invalid body {"error":"Unsupported tier amount"}
401 Invalid wallet auth or X-Payment proof {"error":"Invalid wallet signature"}
402 x402 challenge (no X-Payment header) Challenge JSON (see x402 Flow)
403 Details access revoked by card owner {"error":"Details access revoked by card owner"}
404 Card not found {"error":"Card not found"}
409 Nonce replay detected {"error":"Nonce already used (replay detected)","code":"REPLAY_REJECTED"}
429 Details endpoint rate limit {"error":"Card details rate limit exceeded (5 requests / hour)"}
500 Unexpected internal error {"error":"Internal server error"}

Rate Limits

EndpointLimitWindow
GET /cards/:cardId/details5 requests per card1 hour
All other endpointsStandard per-IP limits apply

Exceeding a rate limit returns 429 Too Many Requests. If the response includes a Retry-After header, wait the indicated duration before retrying.

Architecture

Request Lifecycle

End-to-end sequence for a paid card creation via x402.


Runtime Components

Internal routing and middleware layout of the ASG Card API.