@checkoutkit/server
v0.2.0
Published
Merchant-side protocol engine for the Agentic Commerce Protocol
Maintainers
Readme
@checkoutkit/server
The merchant side of the Agentic Commerce Protocol. Implement one interface; the engine handles the protocol.
pnpm add @checkoutkit/serverimport { createAcpServer } from "@checkoutkit/server";
const acp = createAcpServer({
backend: {
async createSession(input, ctx) { /* price items, compute totals */ },
async getSession(id, ctx) { /* return null when unknown */ },
async updateSession(id, patch, ctx) { /* re-price */ },
async completeSession(id, payment, ctx) { /* charge, create order */ },
async cancelSession(id, input, ctx) { /* release the cart */ },
},
auth: { verifyAgent: (req) => lookupAgent(req.headers.get("Authorization")) },
signature: { hmacKeys: [process.env.ACP_HMAC_KEY!] },
basePath: "/acp",
});createAcpServer returns (req: Request) => Promise<Response>, so the same
backend runs on Node, Bun, Deno, Cloudflare Workers and Vercel Edge. Framework
adapters are thin wrappers: @checkoutkit/express, @checkoutkit/next,
@checkoutkit/hono.
What it enforces for you
- HMAC request signatures, constant-time, with a replay window and key rotation
- Idempotency: required key,
409in-flight,422conflict, replay marked withIdempotent-Replayed - State transitions — completing a
not_ready_for_paymentsession is rejected before your backend is called - Totals arithmetic and response schema validation
- API-Version negotiation and spec-shaped errors
Anything your backend throws that is not an AcpError becomes an opaque 500, and
payment tokens are redacted from every diagnostic path.
Running more than one instance? The default idempotency store is in-memory, so
a retry landing on another replica charges twice. Use @checkoutkit/redis.
CheckoutKit is an independent community implementation of the Agentic Commerce Protocol. It is not affiliated with, sponsored by, or endorsed by OpenAI or Stripe.
Part of CheckoutKit · Apache-2.0
