ACP (Agent Commerce Protocol) checkout bridge for the Open Commerce Protocol. Provides Express/Hono-compatible middleware that exposes ACP-compatible REST endpoints for agent-initiated checkout flows.
npm install @opencommerceprotocol/bridge-acpWhen mounted at /acp, the bridge provides:
| Method | Path | Description |
|---|---|---|
POST |
/acp/checkout |
Create a checkout session |
GET |
/acp/checkout/:id |
Get session status |
POST |
/acp/checkout/:id/complete |
Mark session as complete |
DELETE |
/acp/checkout/:id |
Cancel a session |
import express from 'express';
import { createACPExpressMiddleware } from '@opencommerceprotocol/bridge-acp';
import manifest from './.well-known/ocp.json';
const app = express();
app.use(express.json());
app.use('/acp', createACPExpressMiddleware({
ocpManifest: manifest,
checkoutUrl: 'https://mystore.com/checkout',
sessionTtlMs: 30 * 60 * 1000, // 30 minutes (default)
}));Use createACPHandlers to adapt the bridge to any HTTP framework:
import { createACPHandlers } from '@opencommerceprotocol/bridge-acp';
import type { ACPRequest, ACPResponse } from '@opencommerceprotocol/bridge-acp';
const handlers = createACPHandlers({
ocpManifest: manifest,
checkoutUrl: 'https://mystore.com/checkout',
});
// handlers is: Record<string, (req: ACPRequest, res: ACPResponse) => Promise<void>>
// Keys: 'POST /checkout', 'GET /checkout/:id', 'POST /checkout/:id/complete', 'DELETE /checkout/:id'import { Hono } from 'hono';
import { createACPHandlers } from '@opencommerceprotocol/bridge-acp';
const app = new Hono();
const handlers = createACPHandlers({ ocpManifest: manifest, checkoutUrl: '/checkout' });
app.post('/acp/checkout', async (c) => {
let response: Response | null = null;
const handler = handlers['POST /checkout'];
if (!handler) return c.json({ error: 'Not implemented' }, 500);
await handler(
{ method: 'POST', path: '/checkout', params: {}, body: await c.req.json() },
{
status: (code) => ({ json: (data) => { response = c.json(data, code as never); } }) as never,
json: (data) => { response = c.json(data); },
}
);
return response ?? c.json({ error: 'Internal error' }, 500);
});| Option | Type | Required | Default | Description |
|---|---|---|---|---|
ocpManifest |
OCPManifest |
Yes | — | OCP manifest |
handlers |
Partial<OCPHandlers> |
No | — | Custom tool handlers |
checkoutUrl |
string |
Yes | — | Base URL for checkout redirects |
sessionTtlMs |
number |
No | 1800000 |
Session TTL in milliseconds (30 min) |
interface ACPSession {
id: string;
status: 'pending' | 'active' | 'complete' | 'failed' | 'expired';
checkout_url: string;
created_at: string; // ISO 8601
expires_at: string; // ISO 8601
items?: Array<{ product_id: string; quantity: number; price: number }>;
total?: number;
currency?: string;
}POST /acp/checkout → { status: 'pending', checkout_url: '...' }
↓ (user completes checkout)
POST /acp/checkout/:id/complete → { status: 'complete' }
GET /acp/checkout/:id → poll for current status
DELETE /acp/checkout/:id → cancel the session
interface ACPRequest {
method: string;
path: string;
params: Record<string, string>; // path params, e.g. { id: 'sess-123' }
body: unknown;
}
interface ACPResponse {
status: (code: number) => ACPResponse; // chainable
json: (data: unknown) => void;
}The default implementation uses an in-memory session store. For production, replace with a persistent store:
import { createACPHandlers } from '@opencommerceprotocol/bridge-acp';
// Extend or wrap createACPHandlers with your Redis/DB session store
const handlers = createACPHandlers({
ocpManifest: manifest,
checkoutUrl: process.env.CHECKOUT_URL!,
sessionTtlMs: 60 * 60 * 1000, // 1 hour
});Declare your ACP endpoint in the OCP manifest to make it discoverable:
{
"bridge": {
"acp": "https://mystore.com/acp"
}
}