Convova
API reference

Orders

The storefront: quote a cart, prove the buyer's email, create an order (returns a Stripe-hosted Checkout URL, or paid at once when free), cancel it, and poll order status by id. Tickets and add-ons are issued server-side once payment completes.

Quote a cart

POST
/events/{slug}/orders/quote

What the cart would cost right now — validates the seller, sales windows, prices, per-order and per-ticket caps, add-on attachment, and sold-out state, and computes every total server-side. Pure: no writes. tickets is one entry per ticket unit, each with its addOns. Rate-limited per IP.

Path Parameters

slug*string

The event's unique slug.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

curl -X POST "https://example.com/events/string/orders/quote" \  -H "Content-Type: application/json" \  -d '{    "tickets": [      {        "productId": "dcd53ddb-8104-4e48-8cc0-5df1088c6113",        "addOns": []      }    ]  }'
{  "data": {    "currency": "string",    "tickets": [      {        "productId": "dcd53ddb-8104-4e48-8cc0-5df1088c6113",        "name": "string",        "unitAmount": 0,        "discountAmount": 0,        "subtotal": 0,        "addOns": [          {            "productId": "dcd53ddb-8104-4e48-8cc0-5df1088c6113",            "name": "string",            "unitAmount": 0,            "discountAmount": 0,            "subtotal": 0          }        ]      }    ],    "couponCode": "string",    "subtotal": 0,    "discountTotal": 0,    "taxTotal": 0,    "total": 0  },  "error": null,  "pagination": {    "offset": 0,    "limit": 0,    "total": 0,    "hasMore": true  }}
POST
/events/{slug}/orders

Re-validates the cart, places the hold (quantity, capacity, promo code), and returns the Stripe-hosted Checkout URL to redirect the buyer to (card-only). A zero-total order skips Stripe and comes back paid. The buyer is the buyerToken from the checkout code, or the signed-in Convova session; without one the call is 401. The hold lasts 30 minutes; lightly capped per buyer email.

Path Parameters

slug*string

The event's unique slug.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/events/string/orders" \  -H "Content-Type: application/json" \  -d '{    "tickets": [      {        "productId": "dcd53ddb-8104-4e48-8cc0-5df1088c6113",        "addOns": []      }    ]  }'
{  "data": {    "orderId": "b3e1eced-f2bd-4d8c-9765-fbc9d1d222d5",    "checkoutUrl": "http://example.com",    "expiresAt": "2019-08-24T14:15:22Z",    "status": "pending"  },  "error": null,  "pagination": {    "offset": 0,    "limit": 0,    "total": 0,    "hasMore": true  }}
POST
/events/{slug}/checkout/start

Sends a code to the email so the buyer can prove it before any hold exists. One live code per email; a resend waits 60 seconds. Rate-limited per IP.

Path Parameters

slug*string

The event's unique slug.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

curl -X POST "https://example.com/events/string/checkout/start" \  -H "Content-Type: application/json" \  -d '{    "email": null  }'
{  "data": {    "sent": true  },  "error": null,  "pagination": {    "offset": 0,    "limit": 0,    "total": 0,    "hasMore": true  }}
POST
/events/{slug}/checkout/verify

Checks the code (three tries, ten minutes) and returns buyerToken, valid for one hour, to pass when creating the order.

Path Parameters

slug*string

The event's unique slug.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

curl -X POST "https://example.com/events/string/checkout/verify" \  -H "Content-Type: application/json" \  -d '{    "email": null,    "code": "string"  }'
{  "data": {    "buyerToken": "string",    "expiresAt": "2019-08-24T14:15:22Z"  },  "error": null,  "pagination": {    "offset": 0,    "limit": 0,    "total": 0,    "hasMore": true  }}

Release a pending order

POST
/events/{slug}/orders/{orderId}/cancel

The buyer left Stripe's page: the Checkout Session is expired and the hold released at once, instead of at the timer. A paid order is left alone.

Path Parameters

slug*string

The event's unique slug.

orderId*string

The order's id.

Formatuuid

Response Body

application/json

application/json

curl -X POST "https://example.com/events/string/orders/497f6eca-6276-4993-bfeb-53cbbbba6f08/cancel"
{  "data": {    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",    "status": "pending",    "currency": "string",    "subtotal": 0,    "discountTotal": 0,    "taxTotal": 0,    "total": 0,    "items": [      {        "description": "string",        "unitAmount": 0,        "quantity": 1,        "subtotal": 0      }    ],    "ticketCount": 0,    "expiresAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z"  },  "error": null,  "pagination": {    "offset": 0,    "limit": 0,    "total": 0,    "hasMore": true  }}
POST
/events/{slug}/coupons/validate

Same computation as the quote with couponCode required: returns the discounted quote, or a 400 with one message, "This code can't be used", for every kind of refusal. Advisory — the code is re-checked and reserved with the hold at order creation. Rate-limited per IP.

Path Parameters

slug*string

The event's unique slug.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

curl -X POST "https://example.com/events/string/coupons/validate" \  -H "Content-Type: application/json" \  -d '{    "tickets": [      {        "productId": "dcd53ddb-8104-4e48-8cc0-5df1088c6113",        "addOns": []      }    ]  }'
{  "data": {    "currency": "string",    "tickets": [      {        "productId": "dcd53ddb-8104-4e48-8cc0-5df1088c6113",        "name": "string",        "unitAmount": 0,        "discountAmount": 0,        "subtotal": 0,        "addOns": [          {            "productId": "dcd53ddb-8104-4e48-8cc0-5df1088c6113",            "name": "string",            "unitAmount": 0,            "discountAmount": 0,            "subtotal": 0          }        ]      }    ],    "couponCode": "string",    "subtotal": 0,    "discountTotal": 0,    "taxTotal": 0,    "total": 0  },  "error": null,  "pagination": {    "offset": 0,    "limit": 0,    "total": 0,    "hasMore": true  }}

Get order status

GET
/events/{slug}/orders/{orderId}

Status + totals + grouped line snapshots for one order. The unguessable order id is the read capability; no buyer PII is returned. status is pending | paid | expired | refunded (a pending order past expiresAt reads as expired).

Path Parameters

slug*string

The event's unique slug.

orderId*string

The order's id.

Formatuuid

Response Body

application/json

application/json

curl -X GET "https://example.com/events/string/orders/497f6eca-6276-4993-bfeb-53cbbbba6f08"
{  "data": {    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",    "status": "pending",    "currency": "string",    "subtotal": 0,    "discountTotal": 0,    "taxTotal": 0,    "total": 0,    "items": [      {        "description": "string",        "unitAmount": 0,        "quantity": 1,        "subtotal": 0      }    ],    "ticketCount": 0,    "expiresAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z"  },  "error": null,  "pagination": {    "offset": 0,    "limit": 0,    "total": 0,    "hasMore": true  }}