---
title: "Create a checkout session"
method: POST
path: "/v1/checkout-sessions"
tags: ["Checkout Sessions"]
---

# Create a checkout session

`POST /v1/checkout-sessions`

Create a product-based checkout session

## Request body

- union
  - object — Checkout with a fixed cart of product items.
    - `billing_currency` string, nullable — Optional checkout billing currency. If omitted, defaults to product pricing currency.
    - `allowed_payment_method_types` string[], nullable — Optional list of allowed payment methods.
    - `cancel_url` string, uri, nullable — Where to send the customer if they cancel or abandon the checkout. Returned on the checkout so the hosted page can route back to it.
    - `return_url` string, uri, nullable — Deprecated alias for `success_url`, kept for backward compatibility. If both are set, `success_url` wins.
    - `success_url` string — Where to redirect the customer after a successful payment. Bachs appends `?checkout_id=<id>`. This is the primary success-redirect field.
    - `customer` union, required — Customer details for the checkout session.
      - ExistingCustomerRequest
        - `customer_id` string, required — Existing customer ID.
      - NewCustomerRequest
        - `email` string, email, required — Customer email address.
        - `name` string, required — Customer full name.
        - `phone_number` string, nullable — Customer phone number.
    - `metadata` object, nullable — Optional metadata (max 20 keys, max 10KB total).
    - `product_cart` ProductItemRequest[], required — List of product items to include in this checkout session. Mutually exclusive with `product_collection_id`.
      - `product_id` string, required — Product ID to include in checkout.
      - `quantity` integer — Number of units for the product item.
      - `amount` string, nullable — Optional custom amount override for CUSTOM-priced products.
    - `product_collection_id` string — ID of a product collection to use for this checkout session. The customer selects a product from the collection. Mutually exclusive with `product_cart`.
    - `reference` string, nullable — Optional client reference (unique per organization). If not provided, one will be auto-generated. Used for idempotency and tracking.
    - `expires_in_minutes` integer — Minutes until the checkout session expires. Defaults to 60. After expiry the checkout URL is invalid.
  - object — Checkout from a product collection (customer selects a product).
    - `billing_currency` string, nullable — Optional checkout billing currency. If omitted, defaults to product pricing currency.
    - `allowed_payment_method_types` string[], nullable — Optional list of allowed payment methods.
    - `cancel_url` string, uri, nullable — Where to send the customer if they cancel or abandon the checkout. Returned on the checkout so the hosted page can route back to it.
    - `return_url` string, uri, nullable — Deprecated alias for `success_url`, kept for backward compatibility. If both are set, `success_url` wins.
    - `success_url` string — Where to redirect the customer after a successful payment. Bachs appends `?checkout_id=<id>`. This is the primary success-redirect field.
    - `customer` union, required — Customer details for the checkout session.
      - ExistingCustomerRequest
        - `customer_id` string, required — Existing customer ID.
      - NewCustomerRequest
        - `email` string, email, required — Customer email address.
        - `name` string, required — Customer full name.
        - `phone_number` string, nullable — Customer phone number.
    - `metadata` object, nullable — Optional metadata (max 20 keys, max 10KB total).
    - `product_cart` ProductItemRequest[] — List of product items to include in this checkout session. Mutually exclusive with `product_collection_id`.
      - `product_id` string, required — Product ID to include in checkout.
      - `quantity` integer — Number of units for the product item.
      - `amount` string, nullable — Optional custom amount override for CUSTOM-priced products.
    - `product_collection_id` string, required — ID of a product collection to use for this checkout session. The customer selects a product from the collection. Mutually exclusive with `product_cart`.
    - `reference` string, nullable — Optional client reference (unique per organization). If not provided, one will be auto-generated. Used for idempotency and tracking.
    - `expires_in_minutes` integer — Minutes until the checkout session expires. Defaults to 60. After expiry the checkout URL is invalid.

## Response `201`

Success - Checkout session created successfully

- CreateCheckoutSessionResponse — Response containing checkout session details and hosted checkout URL.
  - `checkout_id` string — Unique identifier for the underlying checkout.
  - `checkout_url` string, uri — Hosted checkout URL where your customer can complete payment.
  - `status` 'OPEN' | 'COMPLETED' | 'EXPIRED' | 'CANCELLED' — Current checkout status. New sessions start in `OPEN`. `OPEN`: Awaiting customer payment. New sessions start here. `COMPLETED`: Payment succeeded. This is a terminal state. `EXPIRED`: The session window elapsed before payment. This is a terminal state. `CANCELLED`: Canceled before completion. This is a terminal state.
  - `expires_at` string, date-time — ISO 8601 timestamp indicating when the checkout will expire. After this time, customers cannot complete payment through this checkout.
  - `created_at` string, date-time — ISO 8601 timestamp indicating when the checkout was created.

## Other responses

- `400` — Bad Request - Validation errors or invalid request format. Check the `details` object for field-specific validation errors. Common causes: missing required fields, invalid data types, values outside allowed ranges, or invalid formats.
- `401` — Unauthorized - Invalid, missing, or expired API key. Verify your API key is correctly formatted and included in the Authorization header as `Bearer sk_sandbox_...` or `Bearer sk_live_...`. Check that your key hasn't been revoked.
- `403` — Forbidden - API key does not have permission for the requested resource. Verify you're using the correct organization's API key and that you're not trying to access another organization's data.
- `404` — Not Found - The requested resource does not exist. Verify the resource ID is correct and that it belongs to your organization.
- `429` — Too Many Requests - Rate limit exceeded. Standard tier allows 100 requests per minute per API key. Wait a few seconds before retrying. Check X-RateLimit-Reset header for when the window resets.
- `500` — Internal Server Error - An unexpected error occurred while processing the request. Retry with exponential backoff. If the issue persists, contact support with your request context.

---

[API](https://skmtc.dev/bachs/apis/bachs-api.md) · [All operations](https://skmtc.dev/bachs/apis/bachs-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/bachs/bachs-api/revisions/f29efa8a22df/schema)
