---
title: "Create a hosted checkout link"
method: POST
path: "/api/v1/checkout_links"
tags: ["Agentic checkout (hosted link)"]
---

# Create a hosted checkout link

`POST /api/v1/checkout_links`

## Request

- Base URL: `https://www.adadiamonds.com`
- URL: `https://www.adadiamonds.com/api/v1/checkout_links`
- Auth: one of:
  - none
  - API key in header `X-Ada-Api-Key`
  - OAuth 2 (authorization code, authorization URL `https://www.adadiamonds.com/oauth/authorize`, token URL `https://www.adadiamonds.com/api/oauth/token`; client credentials, token URL `https://www.adadiamonds.com/api/oauth/token`, scopes: `catalog:read`, `content:read`)

Assemble a cart from product-feed item ids (`diamond:<report number>`, `setting:<slug>`, `jewelry:<slug>`) and get back a Stripe-hosted checkout URL the buyer opens to pay; no card data passes through the agent. Requires the shipping address (tax and shipping are priced into the link); buyer email is optional and collected on the payment page when missing. Anonymous callers are allowed, and an anonymous or production-credential request without `env: "sandbox"` creates a LIVE, payable Stripe Checkout session; a sandbox credential or `env: "sandbox"` returns a simulated link and creates no Stripe session. (The MCP `create_checkout_link` tool differs: anonymous MCP calls default to sandbox and need `env: "production"` for a live link.) Links expire after 24 hours. On payment, the order flows through the standard pipeline (order confirmation email, jeweler follow-up on size and metal).

## Headers

- `Idempotency-Key` string
- `Request-Id` string

## Request body

- CheckoutLinkCreateRequest
  - `items` AcpItem[], required: A complete engagement ring is one setting item plus one diamond item.
    - `id` string, required: diamond:<id>, setting:<slug>, or jewelry:<slug>
    - `quantity` integer: Diamonds are unique stones; quantity must be 1.
  - `shipping_address` AcpAddress, required
    - `name` string
    - `line_one` string, required
    - `line_two` string
    - `city` string, required
    - `state` string, required: ISO 3166-2 region code, e.g. NY
    - `country` string, required: ISO 3166-1 alpha-2
    - `postal_code` string, required
    - `phone_number` string: E.164
  - `buyer` object
    - `email` string: Optional; Stripe collects it on the payment page when missing.
    - `full_name` string
    - `phone_number` string
  - `env` 'production' | 'sandbox': sandbox returns a simulated link and never touches Stripe. Omitted on this REST endpoint, anonymous and production-credential calls default to production and create a live, payable Stripe session.

## Response `200`

The cart needs more input; `problems[]` lists what is missing and `url` is null.

- CheckoutLink
  - `object` 'checkout_link', required
  - `id` string, required: Session id, `link_<uuid>`.
  - `url` string, nullable, required: Stripe-hosted checkout URL; null while `state` is `needs_input`.
  - `simulated` boolean, required: True in sandbox: nothing is payable.
  - `expires_at` string, date-time, nullable
  - `state` 'ready' | 'needs_input', required
  - `currency` string
  - `totals` object, required: All cents: items_base_amount, discount, subtotal, fulfillment, tax, total.
  - `line_items` object[]
  - `messages` object[]
  - `problems` object[]: Blocking problems when `state` is `needs_input`.

## Other responses

- `201`: A payable link was created; `url` is the Stripe-hosted checkout page.
- `400`: Malformed body, unknown item id, or an unavailable product.

---

[API](https://skmtc.dev/adadiamonds/apis/ada-diamonds-agent-api.md) · [All operations](https://skmtc.dev/adadiamonds/apis/ada-diamonds-agent-api/llms.txt) · [OpenAPI document](https://skmtc.dev/adadiamonds/apis/ada-diamonds-agent-api/revisions/2b2ed3201815?raw)
