@opencommerceprotocol/bridge-acp
v1.0.0
Published
Open Commerce Protocol — ACP (Agent Commerce Protocol) checkout bridge
Maintainers
Readme
@opencommerceprotocol/bridge-acp
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.
Installation
npm install @opencommerceprotocol/bridge-acpACP Endpoints
When 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 |
Express Middleware
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)
}));Framework-Agnostic Handlers
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'Hono Example
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);
});ACPMiddlewareConfig
| 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) |
ACPSession
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;
}Session Lifecycle
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 sessionRequest / Response Types
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;
}Production Considerations
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
});OCP Manifest Declaration
Declare your ACP endpoint in the OCP manifest to make it discoverable:
{
"bridge": {
"acp": "https://mystore.com/acp"
}
}