Skip to content

Agentic Checkout Spec

Merchants integrate with OpenAI's checkout flow by implementing the Agentic Checkout Spec

Building with the Agentic Commerce Protocol is open to all. Instant Checkout in ChatGPT is currently available to approved partners. To apply to participate in Instant Checkout, fill out this form here.

Overview

Enable merchants to run end-to-end checkout flows inside ChatGPT while keeping orders, payments, and compliance on their existing commerce stack.

How it works

  1. Create session (REST). ChatGPT calls your POST /checkout_sessions to start a session with cart contents and buyer context; your response must include a rich, authoritative cart state.
  2. Update session (REST). As the user changes items, shipping, or discounts, ChatGPT calls POST /checkout_sessions/{checkout_session_id}; each response returns the full cart state for display and validation.
  3. Order events (webhooks). Your system publishes order lifecycle events (e.g., order.created, order.updated) to the provided webhook so ChatGPT stays in sync with fulfillment-grade truth.
  4. Complete checkout (REST). ChatGPT finalizes via POST /checkout_sessions/{checkout_session_id}/complete; you confirm order creation and return the final cart and order identifiers.
  5. Optionally, cancel checkouts using POST /checkout_sessions/{checkout_session_id}/cancel and get checkout information with GET /checkout_sessions/{checkout_session_id}.
  6. Payments on your rails. You process payment with your existing PSP; if using Delegated Payments, accept the token and apply your normal authorization/capture flow.

Key points

  • Required endpoints. Implement create, update, and complete checkout session REST endpoints; all responses must return a rich cart state (items, pricing, taxes/fees, shipping, discounts, totals, status).
  • Authoritative webhooks. Emit order events to the provided webhook to keep state consistent across retries and edge cases.
  • Keep payments where they are. Use your current PSP and settlement processes; integrate Delegated Payments only if applicable.
  • Security and robustness. Authenticate every request, verify signatures, enforce idempotency, validate inputs, and support safe retries.
  • Certify integration. Pass conformance checks (schema, error codes, rate limits, webhook delivery) to ensure reliable in-ChatGPT checkout.

Checkout session

For users to place an order through ChatGPT, you must create, update and complete a Checkout session. This Checkout session holds information about items to be purchased, fulfillment information, and payment information.

As the user progresses through the checkout flow the Checkout session will be updated and move between various states.

The response to update calls, should return all checkout options, messages, and errors to be displayed to the user. Once the customer clicks "Buy", the checkout session is completed with a selected payment method.

State diagram showing order states

REST endpoints

Merchants must implement the following five endpoints to place orders on behalf of ChatGPT users.

In the future, the Agentic Checkout Spec will support MCP servers.

Common features of all endpoints

All endpoints must use HTTPS and return JSON.

Request headers

All endpoints will be called with the following headers set:

FieldDescriptionExample Value
AuthorizationAPI Key used to make requestsBearer api_key_123
Accept-LanguageThe preferred locale for content like messages and errorsen-US
User-AgentInformation about the client making this requestChatGPT/2.0 (Mac OS X 15.0.1; arm64; build 0)
Idempotency-KeyKey used to ensure requests are idempotentidempotency_key_123
Request-IdUnique key for each request for tracing purposesrequest_id_123
Content-TypeType of request contentapplication/json
SignatureBase64 encoded signature of the request bodyeyJtZX...
TimestampFormatted as an RFC 3339 string2025-09-25T10:30:00Z
API-VersionAPI version2025-09-12

Response headers

FieldDescriptionExample Value
Idempotency-KeyIdempotency key passed in the requestidempotency_key_123
Request-IdRequest ID passed in the requestrequest_id_123

POST /checkout_sessions

Call direction: OpenAI -> Merchant

This is the initial call to create a checkout session. The call will contain information about the items the customer wishes to purchase and should return line item information, along with any messages or errors to be displayed to the customer. It should always return a checkout session id. All responses should be returned with a 201 status.

Request

FieldTypeRequiredDescriptionValidation
buyerBuyerNoOptional information about the buyer.None
itemsList[Item]YesThe initial list of items to initiate the checkout session.Should be a non empty list
fulfillment_addressAddressNoOptional fulfillment address if present.None

Response

FieldTypeRequiredDescriptionValidation
idStringYesUnique id that identifies the checkout session. This id will be used to update the checkout session in subsequent calls.None
buyerBuyerNoBuyer information, if providedNone
payment_providerPaymentProviderYesPayment provider that will be used to complete this transaction.None
statusString enumYesCurrent status of the checkout session. Possible values are: not_ready_for_payment ready_for_payment completed canceledNone
currencyStringYesCurrency code as per the ISO 4217 standardShould follow the ISO 4217 standard in lower case
line_itemsList[LineItem]YesList of items and computed costs.None
fulfillment_addressAddressNoAddress to ship items to.None
fulfillment_optionsList[FulfillmentOption]YesAll available fulfillment options and associated costs.None
fulfillment_option_idStringNoId of the selected fulfillment option.None
totalsList[Total]YesList of totals.None
messagesList[Message]YesList of informational and error messages to be displayed to the customer.None
linksList[Link]YesList of links (e.g. ToS/privacy policy/etc.) to be displayed to the customer.None

Examples

  1. Creating a checkout session with a single item and quantity. No fulfillment address is provided, so the checkout cannot be completed.
json
POST Request to /checkout_sessions

{
   "items": [
       {
           "id": "item_123",
           "quantity": 1
       }
   ]
}
json
Response

{
   "id": "checkout_session_123",
   "payment_provider": {
       "provider": "stripe",
       "supported_payment_methods": ["card"]
   },
   "status": "in_progress",
   "currency": "usd",
   "line_items": [
       {
           "id": "line_item_123",
           "item": {
               "id": "item_123",
               "quantity": 1
           },
           "base_amount": 300,
           "discount": 0,
           "subtotal": 300,
           "tax": 30,
           "total": 330
       }
   ],
   "totals": [
       {
           "type": "items_base_amount",
           "display_text": "Item(s) total",
           "amount": 300
       },
       {
           "type": "subtotal",
           "display_text": "Subtotal", 
           "amount": 300
       },
       {
           "type": "tax",
           "display_text": "Tax",
           "amount": "0.30"
       },
       {
           "type": "total",
           "display_text": "Total",
           "amount": 330
       }
   ],
   "fulfillment_options": [],
   "messages": [
       {
           "type": "error",
           "code": "out_of_stock",
           "path": "$.line_items[0]",
           "content_type": "plain",
           "content": "This item is not available for sale.",
       }
   ],
   "links": [
       {
           "type": "terms_of_use",
           "url": "https://www.testshop.com/legal/terms-of-use"
       }
   ]
}
  1. Creating a checkout session with a single item and quantity, and a provided fulfillment address. Since a fulfillment address is provided, taxes are returned as well. Fulfillment options are also available, and the cheapest one is selected by default. Any messages to show to the customer based on their fulfillment address (e.g. CA 65 warning) are also returned.
json
POST Request to /checkout_sessions

{
   "items": [
       {
           "id": "item_456",
           "quantity": 1
       }
   ],
   "fulfillment_address": {
       "name": "test",
       "line_one": "1234 Chat Road",
       "line_two": "Apt 1",
       "city": "San Francisco",
       "state": "CA",
       "postal_code": "94105",
       "country": "US"
   }
}
markdown
### POST `/checkout_sessions/{checkout_session_id}`

Call direction: OpenAI -> Merchant

This endpoint will be called on checkout session updates, such as a change in fulfillment address or fulfillment option. The endpoint should return updated costs, new options (e.g. new fulfillment options based on update in fulfillment address), and any new errors.

#### Request

| Field | Type | Required | Description | Validation |
|-------|------|----------|-------------|------------|
| buyer | Buyer | No | Optional information about the buyer. | None |
| items | List[Item] | No | Optional list of updated items to be purchased. | None |
| fulfillment_address | Address | No | Newly added or updated fulfillment address specified by the customer. | None |
| fulfillment_option_id | String | No | Id of the fulfillment option specified by the customer. | None |

#### Response

| Field | Type | Required | Description | Validation |
|-------|------|----------|-------------|------------|
| id | String | Yes | Unique id that identifies the checkout session. This id will be used to update the checkout session in subsequent calls. | None |
| buyer | Buyer | No | Buyer information, if provided | None |
| status | String enum | Yes | Current status of the checkout session. Possible values are: `not_ready_for_payment` `ready_for_payment completed canceled` | None |
| currency | String | Yes | Currency code as per the ISO 4217 standard | Should follow the ISO 4217 standard in lower case |
| line_items | List[LineItem] | Yes | List of items and computed costs. | None |
| fulfillment_address | Address | No | Address to ship items to. | None |
| fulfillment_options | List[FulfillmentOption] | Yes | All available fulfillment options and associated costs. | None |
| fulfillment_option_id | String | No | Id of the selected fulfillment option. | None |
| totals | List[Total] | Yes | List of totals. | None |
| messages | List[Message] | Yes | List of informational and error messages to be displayed to the customer. | None |
| links | List[Link] | Yes | List of links (e.g. ToS/privacy policy/etc.) to be displayed to the customer. | None |

#### Example

Updating the fulfillment option updates the checkout session totals.

```json
POST Request to /checkout_sessions/checkout_session_123

{
   "fulfillment_option_id": "fulfillment_option_456"
}
json
Response

{
   "id": "checkout_session_123",
   "status": "ready_for_payment", 
   "currency": "usd",
   "line_items": [
       {
           "id": "line_item_456",
           "item": {
               "id": "item_456",
               "quantity": 1
           },
           "base_amount": 300,
           "discount": 0,
           "subtotal": 0,
           "tax": 30,
           "total": 330
       }
   ],
   "fulfillment_address": {
       "name": "test",
       "line_one": "1234 Chat Road",
       "line_two": "Apt 101",
       "city": "San Francisco", 
       "state": "CA",
       "country": "US",
       "postal_code": "94131"
   },
   "fulfillment_option_id": "fulfillment_option_456",
   "totals": [
       {
           "type": "items_base_amount",
           "display_text": "Item(s) total",
           "amount": 300
       },
       {
           "type": "subtotal",
           "display_text": "Subtotal",
           "amount": 300
       },
       {
           "type": "tax",
           "display_text": "Tax",
           "amount": 30
       },
       {
           "type": "fulfillment",
           "display_text": "Fulfillment",
           "amount": 500
       },
       {
           "type": "total",
           "display_text": "Total",
           "amount": 830
       }
   ],
   "fulfillment_options": [
       {
           "type": "shipping",
           "id": "fulfillment_option_123",
markdown
           "title": "Standard",
           "subtitle": "Arrives in 4-5 days",
           "carrier": "USPS",
           "earliest_delivery_time": "2025-10-12T07:20:50.52Z", 
           "latest_delivery_time": "2025-10-13T07:20:50.52Z",
           "subtotal": 100,
           "tax": 0,
           "total": 100
       },
       {
           "type": "shipping",
           "id": "fulfillment_option_456",
           "title": "Express",
           "subtitle": "Arrives in 1-2 days",
           "carrier": "USPS",
           "earliest_delivery_time": "2025-10-09T07:20:50.52Z",
           "latest_delivery_time": "2025-10-10T07:20:50.52Z",
           "subtotal": 500,
           "tax": 0,
           "total": 500
       }
   ],
   "messages": [],
   "links": [
       {
           "type": "terms_of_use",
           "url": "https://www.testshop.com/legal/terms-of-use"
       }
   ]
}

POST /checkout_sessions/{checkout_session_id}/complete

Call direction: OpenAI -> Merchant

The endpoint will be called with the payment method to complete the purchase. It is expected that the checkout session will be completed and an order will be created after this call. Any errors that prevent this from happening should be returned in the response.

Request

FieldTypeRequiredDescriptionValidation
buyerBuyerNoOptional information about the buyer.None
payment_dataPaymentDataYesPayment data used to complete the checkout session.None

Response

FieldTypeRequiredDescriptionValidation
idStringYesUnique id that identifies the checkout session. This id will be used to update the checkout session in subsequent calls.None
buyerBuyerYesBuyer informationNone
statusString enumYesCurrent status of the checkout session. Possible values are: not_ready_for_payment ready_for_payment completed canceledNone
currencyStringYesCurrency code as per the ISO 4217 standardShould follow the ISO 4217 standard in lower case
line_itemsList[LineItem]YesList of items and computed costs.None
fulfillment_addressAddressNoAddress to ship items to.None
fulfillment_optionsList[FulfillmentOption]YesAll available fulfillment options and associated costs.None
fulfillment_option_idStringYesId of the selected fulfillment option.None
totalsList[Total]YesList of totals.None
orderOrderYesOrder that is created after the checkout session completes.None
messagesList[Message]YesList of informational and error messages to be displayed to the customer.None
linksList[Link]YesList of links (e.g. ToS/privacy policy/etc.) to be displayed to the customer.None

Example

Completing the checkout session with an encrypted payload representing the payment method.

json
POST Request to /checkout_sessions/checkout_session_123/complete

{
   "buyer": {
       "first_name": "John",
       "last_name": "Smith", 
       "email": "[email protected]",
       "phone_number": "15552003434"
   },
   "payment_data": {
       "token": "spt_123",
       "provider": "stripe",
       "billing_address": {
           "name": "test",
           "line_one": "1234 Chat Road",
           "line_two": "Apt 101",
           "city": "San Francisco",
           "state": "CA",
           "country": "US",
           "postal_code": "94131"
       }
   }
}
json
Response

{
   "id": "checkout_session_123",
   "buyer": {
       "first_name": "John",
       "last_name": "Smith",
       "email": "[email protected]",
       "phone_number": "15552003434"
   },
   "status": "completed",
   "currency": "usd",
   "line_items": [
       {
           "id": "line_item_456",
           "item": {
               "id": "item_456",
               "quantity": 1
           },
           "base_amount": 300,
           "discount": 0,
           "subtotal": 300,
           "tax": 30,
           "total": 330
       }
   ],
   "fulfillment_address": {
       "name": "test",
       "line_one": "1234 Chat Road",
       "line_two": "Apt 101", 
       "city": "San Francisco",
       "state": "CA",
       "country": "US",
       "postal_code": "94131"
   },
   "fulfillment_option_id": "fulfillment_option_123",
   "totals": [
       {
           "type": "items_base_amount",
           "display_text": "Item(s) total",
           "amount": 300
       },
       {
           "type": "subtotal",
           "display_text": "Subtotal",
           "amount": 300
       },
       {
           "type": "tax",
           "display_text": "Tax",
           "amount": 30
       },
       {
           "type": "fulfillment",
           "display_text": "Fulfillment",
           "Amount": 100
       },
       {
           "type": "total",
           "display_text": "Total",
           "amount": 430
       }
   ],
   "fulfillment_options": [
       {
           "type": "shipping",
           "id": "fulfillment_option_123",
           "title": "Standard",
           "subtitle": "Arrives in 4-5 days",
           "carrier": "USPS",
           "earliest_delivery_time": "2025-10-12T07:20:50.52Z",
           "latest_delivery_time": "2025-10-13T07:20:50.52Z",
           "subtotal": 100,
           "tax": 0,
           "total": 100
       },
       {
           "type": "shipping",
           "id": "fulfillment_option_456",
           "title": "Express",
           "subtitle": "Arrives in 1-2 days",
           "carrier": "USPS",
           "earliest_delivery_time": "2025-10-09T07:20:50.52Z",
           "latest_delivery_time": "2025-10-10T07:20:50.52Z",
           "subtotal": 500,
           "tax": 0,
           "total": 500
       }
   ],
   "messages": [],
   "links": [
       {
           "type": "terms_of_use",
           "url": "https://www.testshop.com/legal/terms-of-use"
       }
   ]
}

POST /checkout_sessions/{checkout_session_id}/cancel

This endpoint will be used to cancel a checkout session, if it can be canceled. If the checkout session cannot be canceled (e.g. if the checkout session is already canceled or completed), then the server should send back a response with status 405. Any checkout session with a status that is not equal to completed or canceled should be cancelable.

Request

None

Response

FieldTypeRequiredDescriptionValidation
idStringYesUnique id that identifies the checkout session. This id will be used to update the checkout session in subsequent calls.None
buyerBuyerNoBuyer information, if providedNone
statusString enumYesCurrent status of the checkout session. Possible values are: not_ready_for_payment ready_for_payment completed canceledNone
currencyStringYesCurrency code as per the ISO 4217 standardShould follow the ISO 4217 standard in lower case
line_itemsList[LineItem]YesList of items and computed costs.None

| fulfillment_address | Address | No | Address to ship items to. | None | | fulfillment_options | List[FulfillmentOption] | Yes | All available fulfillment options and associated costs. | None | | fulfillment_option_id | String | No | Id of the selected fulfillment option. | None | | totals | List[Total] | Yes | List of totals. | None | | messages | List[Message] | Yes | List of informational and error messages to be displayed to the customer. | None | | links | List[Link] | Yes | List of links (e.g. ToS/privacy policy/etc.) to be displayed to the customer. | None |

GET /checkout_sessions/{checkout_session_id}

This endpoint is used to return update to date information about the checkout session. If the checkout session is not found, then the server should return a response with status 404.

Request

None

Response

FieldTypeRequiredDescriptionValidation
idStringYesUnique id that identifies the checkout session. This id will be used to update the checkout session in subsequent calls.None
buyerBuyerNoBuyer information, if providedNone
statusString enumYesCurrent status of the checkout session. Possible values are: not_ready_for_payment ready_for_payment completed canceledNone
currencyStringYesCurrency code as per the ISO 4217 standardShould follow the ISO 4217 standard in lower case
line_itemsList[LineItem]YesList of items and computed costs.None
fulfillment_addressAddressNoAddress to ship items to.None
fulfillment_optionsList[FulfillmentOption]YesAll available fulfillment options and associated costs.None
fulfillment_option_idStringNoId of the selected fulfillment option.None
totalsList[Total]YesList of totals.None
messagesList[Message]YesList of informational and error messages to be displayed to the customer.None
linksList[Link]YesList of links (e.g. ToS/privacy policy/etc.) to be displayed to the customer.None

Response Errors

If the server is unable to return a 201 response, then it should return an error of the following shape with a 4xx/5xx status.

Error

FieldTypeRequiredDescription
typeString enumYesError type. Possible values are: invalid_request
codeString enumYesError code. Possible values are: request_not_idempotent
messageStringYesHuman‑readable description of the error.
paramStringNoJSONPath referring to the offending request body field, if applicable.

[Continued in next part due to length...]

FieldTypeRequiredDescriptionValidation
dataString enumYesType of data. For order data, the value should be orderNone
checkout_session_idStringYesID that identifies the checkout session that created this order.None
permalink_urlStringYesURL that points to the order. Customers should be able to visit this URL and provide at most their email address to view order details.None
statusString enumYesString representing the latest status of the order. Possible values are: created manual_review confirmed canceled shipped fulfilledNone
refundsList[Refund]YesList of refunds that have been issued for the order.None

Refund

FieldTypeRequiredDescriptionValidation
typeString enumYesString representing the type of refund. Possible values are: store_credit original_paymentNone
amountintegerYesInteger representing total amount of money refunded.Should be >= 0

Released under the Apache 2.0 License.