# Intake

**Convert unstructured customer input into a Cart, Quote Request, or Shopping List through the HTTP API.**

Intake is a commercetools [Add-On product](/offering/intake.md) that interprets unstructured input, such as emails, PDFs, spreadsheets, CSVs, and free text, and produces structured commerce objects you can review, edit, and act on. Intake uses the commercetools APIs as its tool surface, which means anything it creates remains a first-class resource in your Project. It is available through both the HTTP API and the [Merchant Center](/merchant-center/ai-agents/intake.md).

Intake accepts a natural-language prompt, file uploads, or both. It extracts line items and resolves the Customer, Business Unit, and Store from the input. It then creates a [Cart](/search.md?urn=ctp:api:type:Cart), [Quote Request](/search.md?urn=ctp:api:type:QuoteRequest), or [Shopping List](/search.md?urn=ctp:api:type:ShoppingList) in commercetools REST representation. The caller chooses which entity to create, then reviews and acts on the result using the standard commercetools APIs.

> **AI use:** This feature uses AI to analyze data you provide.
>
> **Your data:** We do not use your data to train models.
>
> **Opt-in:** To enable this feature, submit a [support request](https://support.commercetools.com/) and include the Project key.

## When to use Intake

Use Intake to:

- Convert a list of SKUs, ISBNs, or product names from an email into a Cart without entering each line manually.
- Convert a customer request from a CSV, PDF, or free-text email into a Cart or Quote Request with catalog matches, pricing, and customer context.
- Convert a product list from an email, spreadsheet, or order form into a Shopping List that the Customer can turn into a Cart later.
- Convert inbound emails or support tickets into commerce objects without implementing document parsing, product matching, and customer resolution.

## How Intake works

Intake follows this four-step flow:

1. **Input.** The caller provides free text or uploads a file through the HTTP API or the Merchant Center.
2. **AI interpretation.** Intake extracts identifiers (such as SKUs or product keys), quantities, customer context (email, currency, country), and any other relevant metadata from the input.
3. **Commerce object creation.** Intake matches extracted items against the catalog in the Project, resolves the Customer and, where applicable, applies pricing. It then creates a structured draft, such as a [Cart](/api/projects/carts.md), a [Quote Request](/api/projects/quote-requests.md), or a [Shopping List](/api/projects/shoppingLists.md), with any non-fatal issues returned as warnings.
4. **Review and action.** The caller reviews the draft and makes corrections. They then choose a next action, such as freezing the Cart, creating a draft Quote, or deleting and starting over.

### Tools used by Intake

Intake calls commercetools APIs through a fixed set of tools, which includes:

- **Customer search.** Finds Customers by email using GraphQL. Returns the Customer ID and addresses.
- **Product search.** Finds Products by name, key, Product Variant SKU, or Product Variant key using GraphQL. Returns the SKU, key, and pricing for all variants.

## Required information

Every request must include:

- `outputType`: whether to create a Cart, a Quote Request, or a Shopping List. Intake never infers the entity from the input.
- `locale`: a valid BCP-47 language tag, for example `en-US`.

The request must also include input that contains at least one Product reference (name, key, SKU, or Product Variant key). For `application/json` requests, provide a `prompt`. For `multipart/form-data` requests, provide a `prompt`, one or more files, or both.

The remaining information is read from the input, and what is mandatory depends on `outputType`:

| Information | Cart | Quote Request | Shopping List |
| --- | --- | --- | --- |
| Customer email address | Required | Required | Required |
| Shipping country, used for pricing and tax | Required | Required | Not used |
| Name for the Shopping List | Not applicable | Not applicable | Required |

Intake must also resolve the Business Unit and Store for the request, either from the input or from an explicit reference.

If a required value is missing or cannot be resolved, the request fails with a [`400` error](/api/projects/intake.md#error-codes). The response names the missing information: `RequiredField` for a missing request field, and codes such as `MissingCustomerEmail`, `MissingCountry`, `MissingShoppingListName`, `BusinessUnitUnresolved`, or `StoreUnresolved` for information that couldn't be found in the input.

### Shopping List name

When `outputType` is `ShoppingList`, the input must state the name to give the list, for example `Create a shopping list called "Q3 restock" for jane.doe@example.com with 12 of SKU ABC-123.`

Intake never invents a name. If the input doesn't contain one, no Shopping List is created and the request fails with a `400` error with the code [MissingShoppingListName](/search.md?urn=ctp:api:type:AgentMissingShoppingListNameError).

The name is stored as a [LocalizedString](/search.md?urn=ctp:api:type:LocalizedString) under the `locale` of the request. If the input also describes the list, that text is stored as the Shopping List `description` in the same way.

## Supported input

| Input type | Notes |
| --- | --- |
| Free text | A natural-language prompt, such as the body of an email, a message, or a note. |
| File upload | PDF, TXT, CSV, DOCX, XLSX, EML, Markdown, and HTML. Up to 3 files, 20 MB each. |

## Handling unmatched input

Intake creates the requested entity even when it cannot match every part of the input. Non-fatal issues are returned as [`warnings`](/api/projects/intake.md#warnings) alongside the `201` response:

- When every referenced Product is matched to your catalog, `warnings` is omitted.
- When one or more Products cannot be matched, a `ProductsNotFound` warning lists the unmatched identifiers. The caller can then address them, for example by editing the entity or asking the customer for more information.
- When an uploaded file cannot be parsed, a `FileNotProcessed` warning names the file.

If no line items can be extracted from the input at all, the request fails with a `NoLineItemsExtracted` error instead.

### Unpublished Products in a Shopping List

A Shopping List can contain Products that are not published, which Carts and Quote Requests cannot. Product Search doesn't index unpublished Products, so for `ShoppingList` requests each identifier that Product Search can't match is looked up a second time against staged Product data. That lookup is an exact match against the Product `key`, the Product Variant `sku` or `key`, or the Product name in the locale of the request or in a language configured for the Store or the Project. Partial names and misspellings don't match.

A line item resolved this way is added to the Shopping List with `published` set to `false`.

Store availability is validated by commercetools when the Shopping List is created. If the bound Store doesn't carry some of the requested Products, those Products are omitted, the Shopping List is created with the remaining items, and the omitted SKUs are reported in the `ProductsNotFound` warning. If no requested Product remains, the request fails with a [ShoppingListCreationFailed](/search.md?urn=ctp:api:type:AgentShoppingListCreationFailedError) error.

## Endpoints

Intake exposes a single, stateless endpoint. Each call starts a fresh workflow run and returns its terminal outcome: either a created entity or an error. Multi-turn conversation is not supported by this endpoint.

To call this endpoint, the Project must have Intake enabled, and you must use an API Client with the `manage_intake_agent:{projectKey}` [scope](/api/scopes.md#intake).

### Create a Cart, Quote Request, or Shopping List

[endpoint definition](/search.md?urn=ctp:api:endpoint:/{projectKey}/agents/intake/v1/responses:POST).

```bash title="Create a Shopping List from a prompt"
curl -X POST https://api.{region}.commercetools.com/{projectKey}/agents/intake/v1/responses 
  -H "Authorization: Bearer {token}" 
  -H "Content-Type: application/json" 
  -d '{
    "outputType": "ShoppingList",
    "locale": "en-US",
    "prompt": "Create a shopping list called \"Q3 restock\" for jane.doe@example.com with 12 of SKU ABC-123 and 4 of SKU XYZ-789."
  }'
```

#### Multipart form data

Send an [AgentResponsesPayload](/search.md?urn=ctp:api:type:AgentResponsesPayload) as a single `payload` part and attach files under `files` parts. Uploading a file under any other field name is rejected with an `InvalidField` error.

You can upload up to 3 files, 20 MB each. The allowed content types are:

- PDF (`application/pdf`)
- Plain text (`text/plain`)
- CSV (`text/csv`)
- DOCX (`application/vnd.openxmlformats-officedocument.wordprocessingml.document`)
- XLSX (`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`)
- EML (`message/rfc822`)
- Markdown (`text/markdown`)
- HTML (`text/html`)

```bash title="Create a Quote Request with an uploaded file"
curl -X POST https://api.{region}.commercetools.com/{projectKey}/agents/intake/v1/responses 
  -H "Authorization: Bearer {token}" 
  -F 'payload={"outputType":"QuoteRequest","locale":"en-US","prompt":"Quote for the attached purchase order."};type=application/json' 
  -F "files=@purchase-order.pdf"
```

## Error codes

Every workflow run is identified by a `threadId`, which is returned in the [AgentResponsesErrorResponse](/api/projects/intake.md#agentresponseserrorresponse) body on any error raised once the workflow has started. Errors that fail during request parsing, before the workflow starts, don't include it.

For the full list of Intake-specific error codes and their `400` and `500` responses, see [Intake errors](/api/errors.md#intake).

> The `ProductsNotFound` code appears as either a `400` error, when none of the requested Products could be matched to the catalog, or as a [warning](/api/projects/intake.md#warnings) on a successful `201` response, when only some Products couldn't be matched or are unavailable in the bound Store.

The codes `MissingShoppingListName` and `ShoppingListCreationFailed` only occur when `outputType` is `ShoppingList`, and `MissingCountry` and `QuoteRequestCreationFailed` never do.

## Next actions

The created entity is a standard commercetools [Cart](/api/projects/carts.md), [Quote Request](/api/projects/quote-requests.md), or [Shopping List](/api/projects/shoppingLists.md), so you can act on it with the regular APIs. For example, you can:

- Review and refine a Cart through the standard [Cart update actions](/api/projects/carts.md#update-actions).
- Create a [Quote Request](/api/projects/quote-requests.md) from a Cart that was created first.
- Refine a Shopping List through the standard [Shopping List update actions](/api/projects/shoppingLists.md#update-actions), then add its Line Items to a Cart.
- Delete the entity and start over.

Because each call is stateless, keep the returned `id`, and the `cartId` for a Quote Request, to reference the entity in follow-up API calls.

## Representations

#### AgentResponsesRequest

JSON body for an `application/json` request. `prompt` is required.

[type definition](/search.md?urn=ctp:api:type:AgentResponsesRequest).

#### AgentResponsesPayload

JSON `payload` part of a `multipart/form-data` request. `prompt` is optional when files are attached.

[type definition](/search.md?urn=ctp:api:type:AgentResponsesPayload).

#### AgentResponsesMultipartRequest

`multipart/form-data` body when files are attached.

[type definition](/search.md?urn=ctp:api:type:AgentResponsesMultipartRequest).

#### AgentResponsesOutputType

[type definition](/search.md?urn=ctp:api:type:AgentResponsesOutputType).

#### AgentResponsesSuccess

Successful `201` responses use a discriminated type based on `entityType`.

[type definition](/search.md?urn=ctp:api:type:AgentResponsesSuccess).

#### AgentResponsesCartSuccess

Returned when `outputType` is `Cart`.

[type definition](/search.md?urn=ctp:api:type:AgentResponsesCartSuccess).

#### AgentResponsesQuoteRequestSuccess

Returned when `outputType` is `QuoteRequest`.

[type definition](/search.md?urn=ctp:api:type:AgentResponsesQuoteRequestSuccess).

#### AgentResponsesShoppingListSuccess

Returned when `outputType` is `ShoppingList`.

[type definition](/search.md?urn=ctp:api:type:AgentResponsesShoppingListSuccess).

#### Warnings

Warnings use a [WarningObject](/search.md?urn=ctp:api:type:WarningObject) with a machine-readable `code`. See [Warnings](/api/types.md#warnings) for the full list, including [ProductsNotFound](/search.md?urn=ctp:api:type:AgentProductsNotFoundWarning) and [FileNotProcessed](/search.md?urn=ctp:api:type:AgentFileNotProcessedWarning), which are specific to Intake.

#### AgentResponsesErrorResponse

Except for `401` and `403` responses, errors use this envelope: a `statusCode`, a human-readable `message`, and one or more `errors`.

[type definition](/search.md?urn=ctp:api:type:AgentResponsesErrorResponse).

#### AgentResponsesAuthError

A `401` or `403` response uses the standard [AuthErrorResponse](/search.md?urn=ctp:api:type:AuthErrorResponse) shape (`statusCode`, `message`, `errors`, plus OAuth `error` / `error_description`) rather than the [AgentResponsesErrorResponse](/search.md?urn=ctp:api:type:AgentResponsesErrorResponse) envelope. Typical OAuth codes are `invalid_token` (`401`) and `insufficient_scope` (`403`).

[type definition](/search.md?urn=ctp:api:type:AgentResponsesAuthError).

## Related pages

- [Area overview page with navigation](/api.md)
- [Previous page: Order Search](/api/projects/order-search.md)
- [Search documentation and API specs](/search.md)