{"id":87255,"plugin_id":"plugin_asdk_app_6accac05de5c81919f8f192011f3a125","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-11-09T12:08:01.869Z","digest":"bd689390be8e123909b418b52d08a47450f4bd5f60a59146b0a72f00aef383f8","against":null,"payload":{"description":"Integrate Intake over its stateless responses API so unstructured customer input (an email, support ticket, PDF, spreadsheet, CSV, or free text, including an inbound quote or purchase order) becomes one Cart, Quote Request, or Shopping List. Use when connecting that input to Intake (also called the Intake Agent), including outputType, file upload, and writing the created id back to the channel. Not the Merchant Center Intake UI, and not ongoing ERP, CRM, or transactional-email sync (see commercetools-integrations).","included_files":[{"relative_path":"references/call-responses.md","size_in_bytes":7283},{"relative_path":"references/choose-output.md","size_in_bytes":4204},{"relative_path":"references/email.md","size_in_bytes":3733},{"relative_path":"references/handle-outcome.md","size_in_bytes":6160},{"relative_path":"references/zendesk.md","size_in_bytes":4826},{"relative_path":"scripts/docs-search.mjs","size_in_bytes":26525},{"relative_path":"scripts/openApi-schemata.mjs","size_in_bytes":25619}],"name":"commercetools-intake","skill_md_contents":"---\nname: commercetools-intake\ndescription: \"Integrate Intake over its stateless responses API so unstructured customer input (an email, support ticket, PDF, spreadsheet, CSV, or free text, including an inbound quote or purchase order) becomes one Cart, Quote Request, or Shopping List. Use when connecting that input to Intake (also called the Intake Agent), including outputType, file upload, and writing the created id back to the channel. Not the Merchant Center Intake UI, and not ongoing ERP, CRM, or transactional-email sync (see commercetools-integrations).\"\nwhen_to_use:\n  - \"An inbound purchase-order email should become a Cart or Quote Request through the Intake API\"\n  - \"A Zendesk ticket, with its requester and attachments, should create a commercetools entity via POST /agents/intake/v1/responses\"\n  - \"A retried Intake call created a second Cart, or a mailbox integration got BusinessUnitUnresolved or MissingCustomerEmail\"\n  - \"Choosing Cart, Quote Request, or Shopping List for an unstructured order request\"\nmetadata:\n  contentType: SKILL\n  area:\n    - \"Integrations\"\n  docsSearch:\n    products:\n      - AI Hub\n      - Composable Commerce\n---\n\n# Intake\n\nCall [Intake](https://docs.commercetools.com/api/projects/intake.md) so a channel adapter can turn one unstructured request into one commercetools entity. The HTTP surface is a single stateless endpoint. Each call starts a fresh run and returns either a created entity or an error. It does not resume a previous run, so a follow-up email or ticket comment is not another turn of the same call.\n\nThe adapter owns three decisions Intake will not make: which entity to create, which Customer the message is for, and whether this inbound event is a new request or a reply to an entity already created.\n\n## Out of scope\n\n- Building or automating the [Merchant Center](https://docs.commercetools.com/merchant-center/ai-agents/intake.md) Intake UI. Use that UI once, before writing the adapter, to confirm the same prompt creates the entity. The UI can ask a clarifying question. This endpoint cannot.\n- Connect connectors, transactional email, and CRM sync. Those belong to [commercetools-integrations](../commercetools-integrations/SKILL.md).\n- Quote negotiation after a Quote Request exists (Staged Quote, Quote, Order). That is the [Quotes API](https://docs.commercetools.com/api/quotes-overview.md).\n\n## Workflow\n\n1. <!-- ct:docs-search:begin -->\n   **Docs search (required, run first)** — The first time you use this skill in a session you must run this before answering. It gathers the latest verified documentation as your primary grounding, filtered to the products this skill covers. Use this script for documentation search while working with this skill; the Knowledge MCP covers everything else. Always confirm details against retrieved documentation rather than the skill text alone:\n\n   ```bash\n   node \"<this skill's directory>/scripts/docs-search.mjs\" \\\n     --query \"Intake responses API Cart Quote Request Shopping List file upload\" \\\n     --app-name \"<host app: claude-code, claude-chat, cursor, codex, copilot — or the host's own name>\" \\\n     --model \"<current-model>\" \\\n     --commercetools-project-key \"<if known>\" \\\n     --commercetools-region \"<if known>\" \\\n     --limit 10\n   ```\n\n   Pass the commercetools project key and region (as in `api.{region}.commercetools.com`) only if already in your context; otherwise omit both. Never search files or ask the user for them.\n   <!-- ct:docs-search:end -->\n\n2. **Fetch the REST schema** before writing a request or parsing a response. Run:\n\n   ```bash\n   node scripts/openApi-schemata.mjs \\\n     --resource-name \"api-AgentResponsesSuccess\" \\\n     --app-name \"<host app: claude-code, claude-chat, cursor, codex, copilot — or the host's own name>\" \\\n     --model \"<current-model>\"\n   ```\n\n   The output is the OpenAPI specification for that resource. If the name is not recognized, the script prints valid names. Re-run with `api-Cart-write`, `api-QuoteRequest`, or `api-ShoppingList` when the follow-up is an update to the entity Intake created, not another Intake call.\n\n3. **Confirm the Project can accept the call.** Intake is enabled for the Project (otherwise `FeatureDisabled`). The API client has the `manage_intake_agent:{projectKey}` [scope](https://docs.commercetools.com/api/scopes.md#intake). Product Search is enabled (otherwise `ProductSearchNotEnabled`). The buyer already exists as a Customer. Intake looks a Customer up by email and does not create one.\n\n4. **Run the same prompt in Merchant Center before writing the adapter.** Paste the prompt and any file into [Merchant Center Intake](https://docs.commercetools.com/merchant-center/ai-agents/intake.md). A failure there is the Project, catalog, or Customer. A success there and a failure from the API is the request the integration sent. A success that needed a clarifying question does not count: the prompt that produced the entity is the prompt the API body must contain.\n\n5. **Choose `outputType`.** Read [choose-output.md](./references/choose-output.md). The field is required. Intake never infers it from the message.\n\n6. **Map the channel into one request.** Read [call-responses.md](./references/call-responses.md), then the channel file:\n   - Mailbox: [email.md](./references/email.md)\n   - Zendesk: [zendesk.md](./references/zendesk.md)\n   - Any other drop (a form, a drive folder, another helpdesk): the same mapping in [call-responses.md](./references/call-responses.md). A new channel is a new normalizer, not a new Intake contract.\n\n7. **Call once per new request, and remember that you did.** The endpoint has no idempotency key. Conditionally insert the channel's own id (email `Message-ID`, Zendesk ticket id) with the normalized request as queued work, acknowledge the delivery, then mark the row as a call with an unknown outcome immediately before the POST. On success, store that id against `threadId`, `entity.id`, and, for a Quote Request, `cartId`. Recovery may send a queued row that was never marked. It must not resend a marked row. A second POST creates a second entity.\n\n8. **Handle the outcome and write it back** using [handle-outcome.md](./references/handle-outcome.md). A `201` can still carry warnings. A `400` names what was missing. Do not answer a `400` by calling again with the same body.\n\n9. **Route a later message on the same thread by the stored outcome.** An entity already stored is updated with the normal Cart, Quote Request, or Shopping List APIs. A confirmed no-write failure (a `400` that created nothing) allows one corrected Intake attempt when the reply supplies the missing input. A pending queued row, a call with an unknown outcome, or a partial creation (`QuoteRequestCreationFailed` with `cartId`) is resolved from that stored state. Do not POST again to finish it.\n\n## Checklist\n\n- [ ] The same prompt created the entity in Merchant Center before the adapter was written. A clarifying question in that UI does not count\n- [ ] `outputType` was chosen by the integration, not left for Intake to guess\n- [ ] The prompt states the buyer's email, and for a Cart or Quote Request a shipping country, in plain text\n- [ ] A Shopping List name is stated in the prompt or a file. Intake does not invent one\n- [ ] `businessUnit` and `store` are passed as resource identifiers when the channel knows them\n- [ ] Uploads use the `files` part, at most 3 files, only allowed content types\n- [ ] The channel event id and the normalized request are stored as queued work before the webhook is acknowledged. A call is marked as an unknown outcome immediately before the POST, then stored against `entity.id` and `threadId`. Recovery sends unstarted work and does not resend a call that may have completed\n- [ ] Warnings and the specific `400` code are written back to the channel\n- [ ] A follow-up on the same email thread or ticket follows the stored outcome: update an existing entity, allow one corrected Intake attempt after a confirmed no-write failure when the reply supplies the missing input, and resolve a pending, unknown, or partial-creation outcome without a blind retry\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}