From 9b48edb39903ae09d8efa6dcb821f95b7b6c6f15 Mon Sep 17 00:00:00 2001 From: mckenna Date: Wed, 17 Jun 2026 17:04:44 +0100 Subject: [PATCH 1/4] Add /fin/escalate endpoint to Preview spec Documents the shipped POST /fin/escalate endpoint (Preview): request/response schema, the escalated reason emitted via the API, and the escalate capability type. Mirrors the developer-docs spec. Co-Authored-By: Claude Opus 4.8 (1M context) --- descriptions/0/api.intercom.io.yaml | 155 +++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 3 deletions(-) diff --git a/descriptions/0/api.intercom.io.yaml b/descriptions/0/api.intercom.io.yaml index cad1e59..257a359 100644 --- a/descriptions/0/api.intercom.io.yaml +++ b/descriptions/0/api.intercom.io.yaml @@ -22344,7 +22344,7 @@ paths: properties: type: type: string - description: The kind of capability — `procedure` for a runnable procedure, or a static action such as `reply` or `ask`. + description: The kind of capability — `procedure` for a runnable procedure, or a static action such as `reply`, `ask`, or `escalate`. example: procedure id: type: string @@ -22966,6 +22966,149 @@ paths: order_id: '98765' settings: email: true + "/fin/escalate": + post: + summary: Escalate to a human + parameters: + - name: Intercom-Version + in: header + schema: + "$ref": "#/components/schemas/intercom_version" + tags: + - Fin Agent + operationId: escalateFinConversation + description: | + Hand a conversation off to a human teammate. If you use the Intercom Helpdesk, the + handoff lands in your team inbox. + + Provide either `conversation_id` or `user`: + + - `conversation_id` — escalate an existing agent conversation. By default, Fin summarises + the conversation and opens a new Helpdesk conversation that carries the summary as an + internal note; the original agent conversation is not reassigned. Configure an escalation + Operator Workflow to change this default. + - `user` — escalate on behalf of a user with no prior agent conversation. A new Helpdesk + conversation is created for the teammate. Include an optional `message` for its first + message. + + In both cases the optional `context` is attached as an internal note (supplied by your + orchestrating agent, not generated by Fin) alongside any summary. + + You are notified over the existing webhook or SSE channel with an `escalated` status + followed by `complete`. The `complete` status signals that Fin is done; it does not close + the conversation, which remains open in the human inbox. + responses: + '200': + description: Conversation escalated successfully + content: + application/json: + examples: + Existing conversation: + value: + conversation_id: ext-123 + status: escalated + sse_subscription_url: 'https://primary-realtime.intercom-messenger.com/event-stream?channels=fin_agent_api:app123:ext-123&accessToken=eyJhbG...&rewind=2m' + New conversation: + value: + intercom_conversation_id: '987654321' + status: escalated + schema: + type: object + properties: + conversation_id: + type: string + description: The external ID of the conversation. Returned when you escalate an existing conversation by `conversation_id` (echoed back). When you escalate a `user`, a new conversation is created and only `intercom_conversation_id` is returned. + example: ext-123 + intercom_conversation_id: + type: string + description: The internal Intercom conversation ID. Returned when a new conversation was created for the escalation. + example: '987654321' + sse_subscription_url: + type: string + description: | + Optional. A URL to subscribe to Server-Sent Events (SSE) for this conversation, if SSE is enabled. The access token is a JWT with a 3-minute TTL. The token is revoked when Fin sets the conversation to complete status. Includes a `rewind` window so a subscriber that connects after the escalation is processed can still receive the `escalated` and `complete` events. + example: 'https://primary-realtime.intercom-messenger.com/event-stream?channels=fin_agent_api:app123:ext-123&accessToken=eyJhbG...&rewind=2m' + status: + type: string + enum: + - escalated + description: The resulting status of the conversation. + example: escalated + '400': + description: Bad Request + content: + application/json: + examples: + Neither identifier provided: + value: + type: error.list + request_id: b68959ea-6328-4f70-83cb-e7913dba1542 + errors: + - code: parameter_invalid + message: Either conversation_id or user must be provided + Conversation not found: + value: + type: error.list + request_id: b68959ea-6328-4f70-83cb-e7913dba1542 + errors: + - code: parameter_invalid + message: Conversation not found + schema: + "$ref": "#/components/schemas/error" + '401': + description: Unauthorized + content: + application/json: + examples: + Unauthorized: + value: + type: error.list + request_id: b68959ea-6328-4f70-83cb-e7913dba1542 + errors: + - code: unauthorized + message: Access Token Invalid + schema: + "$ref": "#/components/schemas/error" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + conversation_id: + type: string + description: The external ID of the conversation to escalate. Provide this or `user`. + example: ext-123 + user: + "$ref": "#/components/schemas/fin_agent_user" + message: + type: string + maxLength: 10000 + description: Optional first message for the new conversation, used only when escalating on behalf of a `user`. Defaults to "Requesting human support". + example: I'd like to speak to a human about my refund. + context: + type: string + maxLength: 10000 + description: Optional context for the receiving teammate explaining why the conversation is being escalated. Attached as an internal note, never shown to the user. + example: Customer is requesting a refund and is frustrated. + oneOf: + - required: + - conversation_id + - required: + - user + examples: + Escalate an existing conversation: + value: + conversation_id: ext-123 + context: Customer is requesting a refund and is frustrated. + Escalate on behalf of a user: + value: + user: + id: '123456' + name: John Doe + email: john.doe@example.com + message: I need help with my billing issue "/fin/start": post: summary: Start a conversation with Fin @@ -32926,13 +33069,19 @@ components: description: | Optional. A human-readable explanation of why the conversation was escalated. Only present when status is 'escalated'. - Possible values include: + + When you escalate deterministically with `/fin/escalate`, the reason is always + "Escalation requested via API". + + The following reasons are legacy — they apply to Fin-decided escalations in + conversational mode (`/fin/start`, and `/fin/reply` on a conversation that was + started conversationally): - "Escalation requested by user" - "Escalation rule: {rule_name}" - "Escalation rule matched" - "Routed to team" - "Conversation finished without resolution" - example: Escalation requested by user + example: Escalation requested via API created_at_ms: type: string format: date-time From cd118ca952f3f2d5286857934a5e322b2318f23e Mon Sep 17 00:00:00 2001 From: mckenna Date: Thu, 18 Jun 2026 02:39:07 +0100 Subject: [PATCH 2/4] Note escalate message field is shown to the end-user Mirrors developer-docs review feedback: the `message` field is visible to the end-user, unlike the internal-only `context`. Co-Authored-By: Claude Opus 4.8 (1M context) --- descriptions/0/api.intercom.io.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/descriptions/0/api.intercom.io.yaml b/descriptions/0/api.intercom.io.yaml index 257a359..5e70ea4 100644 --- a/descriptions/0/api.intercom.io.yaml +++ b/descriptions/0/api.intercom.io.yaml @@ -23085,7 +23085,7 @@ paths: message: type: string maxLength: 10000 - description: Optional first message for the new conversation, used only when escalating on behalf of a `user`. Defaults to "Requesting human support". + description: Optional first message for the new conversation, used only when escalating on behalf of a `user`. Shown to the end-user (unlike `context`, which is an internal note), so don't include sensitive orchestration data. Defaults to "Requesting human support". example: I'd like to speak to a human about my refund. context: type: string From e91f44757aab96ffa5ed0b0ef638ea154d3eb800 Mon Sep 17 00:00:00 2001 From: mckenna Date: Thu, 18 Jun 2026 11:00:48 +0100 Subject: [PATCH 3/4] Warn against credentials/personal data in escalate context Aligns the context param description with the guide's security note. Co-Authored-By: Claude Opus 4.8 (1M context) --- descriptions/0/api.intercom.io.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/descriptions/0/api.intercom.io.yaml b/descriptions/0/api.intercom.io.yaml index 5e70ea4..b9c3c3b 100644 --- a/descriptions/0/api.intercom.io.yaml +++ b/descriptions/0/api.intercom.io.yaml @@ -23090,7 +23090,7 @@ paths: context: type: string maxLength: 10000 - description: Optional context for the receiving teammate explaining why the conversation is being escalated. Attached as an internal note, never shown to the user. + description: Optional context for the receiving teammate explaining why the conversation is being escalated. Attached as an internal note, never shown to the user. Avoid including credentials or unnecessary personal data — the note is visible to any teammate with access to the conversation. example: Customer is requesting a refund and is frustrated. oneOf: - required: From 2822f5f5619cf55a31a7086425e6072553f92e5b Mon Sep 17 00:00:00 2001 From: mckenna Date: Wed, 1 Jul 2026 17:09:12 +0100 Subject: [PATCH 4/4] Sync /fin/escalate spec with shipped contract message is now a {author, body} object (author restricted to user) that seeds the new conversation; the context parameter is removed. Escalation always summarises the source into a new human-facing conversation and leaves the source untouched. Document the new mutual-exclusivity validations (conversation_id vs user; message not allowed with conversation_id). Co-Authored-By: Claude Opus 4.8 (1M context) --- descriptions/0/api.intercom.io.yaml | 67 ++++++++++++++++++----------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/descriptions/0/api.intercom.io.yaml b/descriptions/0/api.intercom.io.yaml index b9c3c3b..f5cc97a 100644 --- a/descriptions/0/api.intercom.io.yaml +++ b/descriptions/0/api.intercom.io.yaml @@ -22978,21 +22978,17 @@ paths: - Fin Agent operationId: escalateFinConversation description: | - Hand a conversation off to a human teammate. If you use the Intercom Helpdesk, the - handoff lands in your team inbox. + Hand a conversation off to a human teammate. Fin summarises the conversation and opens a + new human-facing conversation that carries the summary; the original agent conversation is + left untouched. If you use the Intercom Helpdesk, the handoff lands in your team inbox. - Provide either `conversation_id` or `user`: + Provide either `conversation_id` or `user` — not both: - - `conversation_id` — escalate an existing agent conversation. By default, Fin summarises - the conversation and opens a new Helpdesk conversation that carries the summary as an - internal note; the original agent conversation is not reassigned. Configure an escalation - Operator Workflow to change this default. - - `user` — escalate on behalf of a user with no prior agent conversation. A new Helpdesk - conversation is created for the teammate. Include an optional `message` for its first - message. - - In both cases the optional `context` is attached as an internal note (supplied by your - orchestrating agent, not generated by Fin) alongside any summary. + - `conversation_id` — escalate an existing agent conversation. Fin summarises it into the new + human-facing conversation. Configure an escalation Operator Workflow to customise routing. + - `user` — escalate on behalf of a user with no prior agent conversation. Include an optional + `message` (authored by the user) to seed the new conversation; its content is summarised + into the handoff. `message` cannot be combined with `conversation_id`. You are notified over the existing webhook or SSE channel with an `escalated` status followed by `complete`. The `complete` status signals that Fin is done; it does not close @@ -23046,6 +23042,20 @@ paths: errors: - code: parameter_invalid message: Either conversation_id or user must be provided + Both identifiers provided: + value: + type: error.list + request_id: b68959ea-6328-4f70-83cb-e7913dba1542 + errors: + - code: parameter_invalid + message: Provide either conversation_id or user, not both + Message provided with conversation_id: + value: + type: error.list + request_id: b68959ea-6328-4f70-83cb-e7913dba1542 + errors: + - code: parameter_invalid + message: message can only be provided when creating a new conversation Conversation not found: value: type: error.list @@ -23083,15 +23093,23 @@ paths: user: "$ref": "#/components/schemas/fin_agent_user" message: - type: string - maxLength: 10000 - description: Optional first message for the new conversation, used only when escalating on behalf of a `user`. Shown to the end-user (unlike `context`, which is an internal note), so don't include sensitive orchestration data. Defaults to "Requesting human support". - example: I'd like to speak to a human about my refund. - context: - type: string - maxLength: 10000 - description: Optional context for the receiving teammate explaining why the conversation is being escalated. Attached as an internal note, never shown to the user. Avoid including credentials or unnecessary personal data — the note is visible to any teammate with access to the conversation. - example: Customer is requesting a refund and is frustrated. + type: object + description: Optional opening message for the new conversation, used only when escalating on behalf of a `user`. Its body is shown to the end-user and summarised into the handoff, so don't include sensitive orchestration data. Cannot be combined with `conversation_id`. Defaults to "Requesting human support". + properties: + author: + type: string + enum: + - user + description: Who the message is from. Only `user` is supported. + example: user + body: + type: string + maxLength: 10000 + description: The message text. + example: I'd like to speak to a human about my refund. + required: + - author + - body oneOf: - required: - conversation_id @@ -23101,14 +23119,15 @@ paths: Escalate an existing conversation: value: conversation_id: ext-123 - context: Customer is requesting a refund and is frustrated. Escalate on behalf of a user: value: user: id: '123456' name: John Doe email: john.doe@example.com - message: I need help with my billing issue + message: + author: user + body: I need help with my billing issue "/fin/start": post: summary: Start a conversation with Fin