Shared Payment Tokens (SPT)

Shared Payment Tokens enable secure, time-limited payment delegation from agents to merchants using Stripe's Agentic Commerce Protocol.

Overview

SPTs allow an agent to authorize a merchant to charge a specific amount within a defined time window, without sharing the underlying payment method.

Key Features:

  • ⏱️ Time-limited (default: 5 minutes)
  • Amount-scoped (exact or maximum)
  • Single-use tokens
  • Merchant-specific
  • Full audit trail

How It Works

MERMAID
sequenceDiagram
    Agent->>AutopayOS: Create SPT for merchant
    AutopayOS->>Stripe: Issue token
    Stripe-->>AutopayOS: issued_token
    AutopayOS-->>Agent: SPT ID
    Agent->>Merchant: Share SPT
    Merchant->>Stripe: Create PaymentIntent with SPT
    Stripe-->>Merchant: Payment confirmed
    Stripe->>AutopayOS: Webhook: token.used

Implementation

Step 1: Create SPT

TypeScript
const spt = await client.spt.create({
  merchantDomain: 'shop.example.com',
  amount: 49.99,
  currency: 'USD',
  expiresIn: 300, // 5 minutes
  mandate: {
    intentId: 'intent_123',
    cartId: 'cart_456',
    paymentId: 'payment_789',
  },
});

console.log(spt.id); // spt_abc123

Step 2: Agent Shares Token

The agent provides the SPT ID to the merchant via A2A protocol:

TypeScript
await agent.sendMessage({
  to: 'merchant.example.com',
  type: 'payment.authorization',
  body: {
    sptId: spt.id,
    amount: 49.99,
    orderId: 'order_123',
  },
});

Step 3: Merchant Charges

Merchant creates a PaymentIntent using the SPT:

TypeScript
// Merchant backend
const payment = await stripe.paymentIntents.create({
  amount: 4999,
  currency: 'usd',
  payment_method_options: {
    shared_payment: {
      issued_token: spt.id,
    },
  },
  application_fee_amount: 150, // 3% platform fee
});

Step 4: Handle Webhooks

AutopayOS receives webhook events from Stripe:

TypeScript
// Webhook: shared_payment.issued_token.used
{
  "type": "shared_payment.issued_token.used",
  "data": {
    "id": "spt_abc123",
    "payment_intent": "pi_xyz789"
  }
}

SPT Lifecycle

  1. ACTIVE - Token created, ready to use
  2. USED - Token consumed by merchant
  3. EXPIRED - Token exceeded time limit
  4. REVOKED - Token manually canceled

Security Considerations

Do:

  • Validate merchant domain before creating SPT
  • Set shortest possible expiration time
  • Link SPT to AP2 mandates for audit trail
  • Monitor webhook events for fraud detection

Don't:

  • Reuse SPT IDs
  • Share SPTs over insecure channels
  • Create SPTs without user consent
  • Skip merchant verification

Monitoring

Check SPT status programmatically:

TypeScript
const status = await client.spt.getStatus(sptId);

console.log({
  status: status.status,      // ACTIVE | USED | EXPIRED | REVOKED
  createdAt: status.createdAt,
  usedAt: status.usedAt,
  expiresAt: status.expiresAt,
});

Admin Operations

Support teams can manage SPTs via admin endpoints:

Bash
# List all active SPTs
GET /admin/spt?status=ACTIVE

# Revoke a token
POST /admin/spt/:id/revoke

# Get statistics
GET /admin/spt/stats/overview

Best Practices

  1. Short Expiration - Use 5 minutes or less
  2. Exact Amounts - Specify exact amount when possible
  3. Mandate Linking - Always link to AP2 mandates
  4. Error Handling - Handle EXPIRED gracefully
  5. Webhook Verification - Verify Stripe webhook signatures

Troubleshooting

Token expired before merchant could charge:

  • Increase expiration time to 10 minutes
  • Optimize merchant checkout flow
  • Pre-create SPT during cart review

Payment declined:

  • Check user has sufficient balance
  • Verify payment method is active
  • Review policy restrictions

Merchant can't find token:

  • Ensure SPT ID transmitted correctly
  • Check merchant is using granted_token API
  • Verify network connectivity

Further Reading