ACP Protocol
Agentic Commerce Protocol (ACP) — OpenAI's open standard for AI agent commerce. Product feeds, agentic checkout, and delegated payments for ChatGPT-native purchasing.
ACP is OpenAI's open standard developed in partnership with Stripe. Sardis implements it as a first-class protocol alongside AP2, UCP, and A2A.
Overview
ACP defines how AI agents discover products, initiate checkout sessions, and complete purchases using delegated payment credentials — without ever handling raw card numbers or bank details.
Sardis acts as the agent's payment backend for ACP flows, handling policy enforcement and payment token issuance.
Checkout Flow
Agent Merchant (ACP) Sardis
│ │ │
│ 1. GET /acp/manifest │ │
│ ─────────────────────▶ │ │
│ ◀─ product_feed[] │ │
│ │ │
│ 2. POST /acp/checkout │ │
│ ─────────────────────▶ │ │
│ ◀─ { session_id, url } │ │
│ │ │
│ 3. Authorize payment │ │
│ ─────────────────────────────────────────────────▶ │
│ │ ◀─ shared_token │
│ │ │
│ 4. POST /acp/pay │ │
│ ─────────────────────▶ │ │
│ { session_id, token } │ 5. Stripe charge ──▶ │
│ │ │
│ ◀─ { order_id, status } │ │
│ │ │
│ 6. Webhook: fulfilled │ │
│ ◀────────────────────── │REST Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /acp/manifest | Product feed discovery |
| POST | /acp/checkout | Create checkout session |
| POST | /acp/pay | Submit payment with shared token |
| GET | /acp/orders/:id | Order status and fulfillment |
| POST | /acp/webhooks | Fulfillment and refund events |
Python
from sardis import SardisClient
async with SardisClient(api_key="sk_...") as client:
# Discover products from ACP-compatible merchant
manifest = await client.acp.get_manifest(
merchant_url="https://shop.example.com/acp/manifest"
)
# Create checkout session
session = await client.acp.create_checkout(
merchant_url="https://shop.example.com",
items=[{"product_id": "prod_abc", "quantity": 1}],
)
# Sardis creates a delegated payment token
token = await client.acp.authorize_payment(
agent_id="shopping-agent",
session_id=session.id,
max_amount_minor=5000, # $50.00 cap
)
# Complete purchase
order = await client.acp.pay(
session_id=session.id,
payment_token=token.shared_token,
)
print(f"Order: {order.order_id} - {order.status}")TypeScript
import { SardisClient } from "@sardis/sdk";
const client = new SardisClient({ apiKey: "sk_..." });
// Discover products
const manifest = await client.acp.getManifest({
merchantUrl: "https://shop.example.com/acp/manifest",
});
// Create checkout session
const session = await client.acp.createCheckout({
merchantUrl: "https://shop.example.com",
items: [{ productId: "prod_abc", quantity: 1 }],
});
// Authorize with Sardis policy engine
const token = await client.acp.authorizePayment({
agentId: "shopping-agent",
sessionId: session.id,
maxAmountMinor: 5000,
});
// Complete purchase
const order = await client.acp.pay({
sessionId: session.id,
paymentToken: token.sharedToken,
});
console.log("Order:", order.orderId, order.status);Delegated Payments
ACP uses Stripe Shared Payment Tokens for delegated payments. Instead of sharing card numbers, Sardis generates a one-time token scoped to a specific checkout session and amount. The merchant charges the token through Stripe. The agent never sees raw payment credentials.
- Token scoped to session — cannot be reused for other purchases
- Amount-capped — token cannot exceed the authorized limit
- Policy-gated — Sardis spending policies enforced before token issuance
- Audit trail — every token issuance logged in Sardis ledger
Webhook Events
| Event | Description |
|---|---|
checkout.completed | Payment confirmed, order created |
order.fulfilled | Merchant fulfilled the order |
order.refunded | Full or partial refund issued |
payment.failed | Payment declined or token expired |
Sardis + ACP
┌─────────────┐ ┌───────────┐ ┌──────────────┐
│ AI Agent │────▶│ Sardis │────▶│ ACP Merchant │
└─────────────┘ └───────────┘ └──────────────┘
│
┌────┴────┐
│ Policy │ ← Check spending limits
│ Engine │ ← Verify merchant category
└────┬────┘
│
┌────┴────┐
│ Stripe │ ← Issue shared payment token
│ Token │ ← Scoped to session + amount
└─────────┘