curl -X POST "https://www.gomry.com/api/v1/checkout_sessions" \
-H "X-API-KEY: your_api_key" \
-H "Content-Type: application/json" \
-H "API-Version: 2025-09-12" \
-H "Timestamp: 2026-09-10T12:00:00Z" \
-H "Signature: base64-hmac-sha256" \
-H "Idempotency-Key: 8f14e45f-ea0c-4b9f-9c2a-1d3e5f7a9b0c" \
-d '{
"items": [{ "id": "TktAbCdEfGhIjKlMnOpQ", "quantity": 2 }],
"buyer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"attendee_answers": [
{ "question_id": "QstAbCdEfGhIjKlMnOpQ", "value": "Vegetarian" }
]
}'
import crypto from "crypto";
const body = JSON.stringify({
items: [{ id: "TktAbCdEfGhIjKlMnOpQ", quantity: 2 }],
buyer: { name: "Ada Lovelace", email: "ada@example.com" },
});
const timestamp = new Date().toISOString();
const signature = crypto
.createHmac("sha256", process.env.GOMRY_ACP_SIGNING_SECRET)
.update(`${timestamp}.${body}`)
.digest("base64");
const res = await fetch("https://www.gomry.com/api/v1/checkout_sessions", {
method: "POST",
headers: {
"X-API-KEY": process.env.GOMRY_API_KEY,
"Content-Type": "application/json",
"API-Version": "2025-09-12",
Timestamp: timestamp,
Signature: signature,
"Idempotency-Key": crypto.randomUUID(),
},
body, // the exact string that was signed
});
const session = await res.json();
{
"id": "acp_sess_AbCdEfGhIjKlMnOpQrSt",
"buyer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"payment_provider": {
"provider": "stripe",
"supported_payment_methods": ["card"]
},
"status": "ready_for_payment",
"currency": "usd",
"line_items": [
{
"id": "li_1",
"item": { "id": "TktAbCdEfGhIjKlMnOpQ", "quantity": 2 },
"base_amount": 15800,
"discount": 0,
"subtotal": 15800,
"tax": 0,
"total": 16790
}
],
"fulfillment_address": null,
"fulfillment_option_id": "digital",
"fulfillment_options": [
{
"type": "digital",
"id": "digital",
"title": "Digital ticket",
"subtitle": "Delivered by email",
"subtotal": 0,
"tax": 0,
"total": 0
}
],
"totals": [
{ "type": "items_base_amount", "display_text": "Tickets", "amount": 15800 },
{ "type": "fee", "display_text": "Service fee", "amount": 990 },
{ "type": "total", "display_text": "Total", "amount": 16790 }
],
"messages": [],
"links": [
{ "type": "terms_of_use", "url": "https://www.gomry.com/terms" },
{ "type": "privacy_policy", "url": "https://www.gomry.com/privacy" }
]
}
{
"id": "acp_sess_AbCdEfGhIjKlMnOpQrSt",
"status": "not_ready_for_payment",
"messages": [
{
"type": "error",
"code": "missing",
"param": "buyer.name",
"content_type": "plain",
"content": "A buyer name is required to issue a ticket."
}
]
}
Checkout Sessions
Create Checkout Session
Open an ACP checkout session for one event’s tickets
POST
/
checkout_sessions
curl -X POST "https://www.gomry.com/api/v1/checkout_sessions" \
-H "X-API-KEY: your_api_key" \
-H "Content-Type: application/json" \
-H "API-Version: 2025-09-12" \
-H "Timestamp: 2026-09-10T12:00:00Z" \
-H "Signature: base64-hmac-sha256" \
-H "Idempotency-Key: 8f14e45f-ea0c-4b9f-9c2a-1d3e5f7a9b0c" \
-d '{
"items": [{ "id": "TktAbCdEfGhIjKlMnOpQ", "quantity": 2 }],
"buyer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"attendee_answers": [
{ "question_id": "QstAbCdEfGhIjKlMnOpQ", "value": "Vegetarian" }
]
}'
import crypto from "crypto";
const body = JSON.stringify({
items: [{ id: "TktAbCdEfGhIjKlMnOpQ", quantity: 2 }],
buyer: { name: "Ada Lovelace", email: "ada@example.com" },
});
const timestamp = new Date().toISOString();
const signature = crypto
.createHmac("sha256", process.env.GOMRY_ACP_SIGNING_SECRET)
.update(`${timestamp}.${body}`)
.digest("base64");
const res = await fetch("https://www.gomry.com/api/v1/checkout_sessions", {
method: "POST",
headers: {
"X-API-KEY": process.env.GOMRY_API_KEY,
"Content-Type": "application/json",
"API-Version": "2025-09-12",
Timestamp: timestamp,
Signature: signature,
"Idempotency-Key": crypto.randomUUID(),
},
body, // the exact string that was signed
});
const session = await res.json();
{
"id": "acp_sess_AbCdEfGhIjKlMnOpQrSt",
"buyer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"payment_provider": {
"provider": "stripe",
"supported_payment_methods": ["card"]
},
"status": "ready_for_payment",
"currency": "usd",
"line_items": [
{
"id": "li_1",
"item": { "id": "TktAbCdEfGhIjKlMnOpQ", "quantity": 2 },
"base_amount": 15800,
"discount": 0,
"subtotal": 15800,
"tax": 0,
"total": 16790
}
],
"fulfillment_address": null,
"fulfillment_option_id": "digital",
"fulfillment_options": [
{
"type": "digital",
"id": "digital",
"title": "Digital ticket",
"subtitle": "Delivered by email",
"subtotal": 0,
"tax": 0,
"total": 0
}
],
"totals": [
{ "type": "items_base_amount", "display_text": "Tickets", "amount": 15800 },
{ "type": "fee", "display_text": "Service fee", "amount": 990 },
{ "type": "total", "display_text": "Total", "amount": 16790 }
],
"messages": [],
"links": [
{ "type": "terms_of_use", "url": "https://www.gomry.com/terms" },
{ "type": "privacy_policy", "url": "https://www.gomry.com/privacy" }
]
}
{
"id": "acp_sess_AbCdEfGhIjKlMnOpQrSt",
"status": "not_ready_for_payment",
"messages": [
{
"type": "error",
"code": "missing",
"param": "buyer.name",
"content_type": "plain",
"content": "A buyer name is required to issue a ticket."
}
]
}
Create Checkout Session
Opens a checkout session and returns a priced cart.Requires
checkout: write, an allowlisted partner key, and a signed request. See Agentic Commerce.Headers
string
2025-09-12. Always send it. A different value is refused with unsupported_api_version; an absent one is treated as the current version.string
required
Base64 HMAC-SHA256 over
{timestamp}.{raw_body}.string
required
RFC 3339, within 5 minutes of our clock.
string
Recommended. Echoed back on the response.
Body
array
required
1–20 lines.
Show Item
Show Item
string
required
A ticket type id from
ticket_types[].id on the catalog detail endpoint. Not an event id.integer
required
1–50, subject to the tier’s own
max_per_order.object
Show Buyer
Show Buyer
string
required
Required by Gomry, though optional in the ACP spec. A ticket is admission for a named person: it prints the attendee’s name and the door list is read by a human. A nameless ticket is technically valid and useless at the door.
string
required
Where the ticket is delivered.
string
Optional.
ready_for_payment without it.array
Up to 50 answers to the event’s registration questions. A Gomry extension to ACP: additive and optional, so a conforming client that never sends it still works — but an event with required questions reports them as blocking messages until they arrive.
object
Accepted for spec conformance. ACP is shaped for physical goods; a ticket does not ship. Stored for the record, never used to fulfil — except for posted tickets, where it is required.
Unknown fields are rejected with
400 invalid_body, not ignored. A body carrying something like card_number must fail loudly rather than be quietly accepted into our logs. No field on this API ever carries a card number.Response
201 with a checkout session.
Read status first:
| Status | What to do |
|---|---|
not_ready_for_payment | Read messages[], fix what is missing, then update the session. |
ready_for_payment | Proceed to complete. |
One session, one event
All items must belong to the same event and the same currency. Mixing them returnsmultiple_events or currency_mismatch. Sell two events as two sessions.
curl -X POST "https://www.gomry.com/api/v1/checkout_sessions" \
-H "X-API-KEY: your_api_key" \
-H "Content-Type: application/json" \
-H "API-Version: 2025-09-12" \
-H "Timestamp: 2026-09-10T12:00:00Z" \
-H "Signature: base64-hmac-sha256" \
-H "Idempotency-Key: 8f14e45f-ea0c-4b9f-9c2a-1d3e5f7a9b0c" \
-d '{
"items": [{ "id": "TktAbCdEfGhIjKlMnOpQ", "quantity": 2 }],
"buyer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"attendee_answers": [
{ "question_id": "QstAbCdEfGhIjKlMnOpQ", "value": "Vegetarian" }
]
}'
import crypto from "crypto";
const body = JSON.stringify({
items: [{ id: "TktAbCdEfGhIjKlMnOpQ", quantity: 2 }],
buyer: { name: "Ada Lovelace", email: "ada@example.com" },
});
const timestamp = new Date().toISOString();
const signature = crypto
.createHmac("sha256", process.env.GOMRY_ACP_SIGNING_SECRET)
.update(`${timestamp}.${body}`)
.digest("base64");
const res = await fetch("https://www.gomry.com/api/v1/checkout_sessions", {
method: "POST",
headers: {
"X-API-KEY": process.env.GOMRY_API_KEY,
"Content-Type": "application/json",
"API-Version": "2025-09-12",
Timestamp: timestamp,
Signature: signature,
"Idempotency-Key": crypto.randomUUID(),
},
body, // the exact string that was signed
});
const session = await res.json();
{
"id": "acp_sess_AbCdEfGhIjKlMnOpQrSt",
"buyer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"payment_provider": {
"provider": "stripe",
"supported_payment_methods": ["card"]
},
"status": "ready_for_payment",
"currency": "usd",
"line_items": [
{
"id": "li_1",
"item": { "id": "TktAbCdEfGhIjKlMnOpQ", "quantity": 2 },
"base_amount": 15800,
"discount": 0,
"subtotal": 15800,
"tax": 0,
"total": 16790
}
],
"fulfillment_address": null,
"fulfillment_option_id": "digital",
"fulfillment_options": [
{
"type": "digital",
"id": "digital",
"title": "Digital ticket",
"subtitle": "Delivered by email",
"subtotal": 0,
"tax": 0,
"total": 0
}
],
"totals": [
{ "type": "items_base_amount", "display_text": "Tickets", "amount": 15800 },
{ "type": "fee", "display_text": "Service fee", "amount": 990 },
{ "type": "total", "display_text": "Total", "amount": 16790 }
],
"messages": [],
"links": [
{ "type": "terms_of_use", "url": "https://www.gomry.com/terms" },
{ "type": "privacy_policy", "url": "https://www.gomry.com/privacy" }
]
}
{
"id": "acp_sess_AbCdEfGhIjKlMnOpQrSt",
"status": "not_ready_for_payment",
"messages": [
{
"type": "error",
"code": "missing",
"param": "buyer.name",
"content_type": "plain",
"content": "A buyer name is required to issue a ticket."
}
]
}

