ACP
Use @bnomei/emdash-mika/acp for ACP projection helpers.
ACP support lives in one server-only package subpath. It maps Mika sellables, cart quotes, checkout previews, and checkout starts into ACP-shaped feeds, session responses, and webhook payloads. It does not register Astro routes by itself; the host chooses where to mount the HTTP handlers and how to protect them.
Important surfaces include:
MIKA_ACP_API_VERSION;MIKA_ACP_DEFAULT_SESSION_PREFIX;createMikaAcpProductFeed();createMikaAcpFileUploadRows();serializeMikaAcpFileUploadRows();serializeMikaAcpProductFeed();validateMikaAcpProductFeed();createMikaAcpCheckoutHandlers();createMemoryMikaAcpSessionStore();MikaAcpSessionStore;MikaAcpIdempotencyClaim;acpCheckoutSessionFromState();createMikaAcpOrderWebhookEvent();signMikaAcpWebhook().
Production ACP endpoints need official ACP request-header handling, host-owned auth, durable session storage with atomic idempotency coordination, and provider settlement.
Do not use this subpath as a hosted ACP server, OAuth issuer, payment rail, or public tool authorization layer. It is a helper layer for host-owned endpoints.
MIKA_ACP_API_VERSION is currently 2025-09-12. MIKA_ACP_DEFAULT_SESSION_PREFIX is acp_checkout. Mika exports handlers, serializers, and stores; it does not register an Astro route tree or enforce an API-version header by itself.
Feed Helpers
Section titled “Feed Helpers”| Helper | Role |
|---|---|
createMikaAcpProductFeed() |
Projects product inputs plus Mika SellableDTO arrays into an ACP product feed with variants derived from active prices. |
validateMikaAcpProductFeed() |
Checks required product/variant fields, URLs, and non-negative integer price amounts. |
serializeMikaAcpProductFeed() |
Validates and pretty-prints the feed as JSON. It throws on the first validation issue. |
createMikaAcpFileUploadRows() |
Flattens active sellable prices into ACP file-upload merchant feed rows with decimal major-unit price strings such as 19.99 USD. |
serializeMikaAcpFileUploadRows() |
Serializes file-upload rows as newline-delimited JSON. |
Feed input comes from host product pages or EmDash entries plus Mika sellables. The helpers do not crawl the storefront or invent catalog content.
Structured MikaAcpVariant.price.amount values stay as Mika minor-unit integer
amounts. File-upload row price values are rendered as decimal major-unit
strings with an ISO currency suffix because merchant-feed ingestion expects that
format.
Checkout Handlers
Section titled “Checkout Handlers”createMikaAcpCheckoutHandlers() returns five request handlers:
| Handler | Role |
|---|---|
create(request) |
Creates an ACP checkout session, reconciles cart items, stores session state, and returns a session response. |
update(request, checkoutSessionId) |
Updates buyer, items, fulfillment address, or fulfillment option before checkout starts. |
complete(request, checkoutSessionId) |
Validates delegated Stripe payment data, previews checkout, and calls api.checkout.start(). |
get(request, checkoutSessionId) |
Reads stored session state and projects it with current quote/checkout status. |
cancel(request, checkoutSessionId) |
Cancels stored state and calls api.checkout.cancel() when a Mika checkout exists. |
The handlers require either apiKey or signatureSecret. Without one,
createMikaAcpCheckoutHandlers() throws rather than exposing checkout sessions.
If apiKey is present, requests must use Authorization: Bearer <apiKey>. If
signatureSecret is present, requests must include Mika’s helper-specific
Signature: <base64 hmac-sha256> and Signature-Timestamp headers. The HMAC
payload is canonicalized as uppercase method, pathname plus search, SHA-256 hash
of the raw body, and timestamp joined with newlines. The timestamp must parse
and be within Mika’s five-minute tolerance. Treat that signature mode as
host-owned protection around Mika’s helper, not as a claim about OpenAI’s public
ACP request headers.
Body-bearing handlers (create, update, complete, and cancel) require an
Idempotency-Key header. get authenticates but does not require idempotency.
The session store must coordinate retries with claimIdempotencyKey(),
bindIdempotencyKey(), and releaseIdempotencyKey().
createMikaAcpCheckoutHandlers() asserts those atomic methods before returning
handlers. The in-memory store is for development and tests; production hosts
need durable storage.
Host endpoints that implement OpenAI ACP should validate API-Version against
MIKA_ACP_API_VERSION before dispatching to these handlers; Mika exports the
constant but does not enforce the header by itself.
The idempotency store key includes request method and pathname. For create(),
same-key retries replay the originally created session even though the handler
mints a fresh candidate session id before claiming the key. For complete(),
Mika serializes by session with acp_complete_lock:<checkoutSessionId> so
concurrent completion attempts with distinct request keys do not double-authorize
payment.
Session Projection
Section titled “Session Projection”acpCheckoutSessionFromState() converts a stored MikaAcpSessionRecord, a Mika
cart quote, optional checkout status, seller links, and optional order URL into
an ACP checkout session response. Status is derived from the checkout status,
stored session status, and quote validity.
complete() currently accepts delegated Stripe payment data only. The body must
include payment_data.token and payment_data.provider: "stripe". The handler
writes Stripe delegated payment metadata into Mika checkout custom fields before
calling api.checkout.start().
Update and cancel respect terminal state: item changes are rejected after
checkout starts, completed sessions cannot be canceled, and canceled sessions
cannot be completed or updated. cancel() calls api.checkout.cancel() for a
bound Mika checkout id and ignores provider 404 only.
Webhook Helpers
Section titled “Webhook Helpers”createMikaAcpOrderWebhookEvent() builds order_created or order_updated
payloads containing a checkout session id, permalink URL, status, and refund
array. signMikaAcpWebhook() returns headers with <merchantName>-Signature
and Content-Type: application/json.
The host owns delivery, retry policy, secret storage, settlement verification, and any provider-specific compliance rules.
External References
Section titled “External References”- OpenAI Agentic Commerce for the commerce protocol family Mika projects into.
- OpenAI commerce specs for the official Product Feed and Checkout specs.
- OpenAI Checkout Spec for checkout session endpoint semantics and official request headers.
- OpenAI Products API spec for product feed API expectations.
- OpenAI production guide for production feed, checkout, payment, and compliance considerations.
Source Anchors
Section titled “Source Anchors”- ⓟ
../emdash-mika/src/acp.ts - ⓟ
../emdash-mika/src/stripe.ts