openapi: 3.0.3
info:
  version: 0.0.1
  title: Fin Custom Helpdesk API
  description: >
    The Fin Custom Helpdesk API allows you to integrate your custom helpdesk
    with Fin through a standardized set of API endpoints and webhooks.


    Note that the names of the endpoints are set by the custom helpdesk's API.
    They do not need to conform to the names given in this API spec (e.g.
    `create_message`).


    ## **FAQ**


    **Q: Can POST be used for all API requests instead of GET?**


    **A:** Yes. All endpoints now support POST requests.


    **Q: Must field names use snake_case or can camelCase be used?**


    **A:** snake_case is required. The format of the responses outlined in the
    documentation must be followed, including the snake_case key names. Intercom
    cannot support different naming conventions for different customers.


    ---


    ## **Message & Idempotency**


    **Q: Does create_message API provide a unique message ID for idempotency?**


    **A:** Yes. An `object_id` field is available on all `create` type requests:
    `create_message`, `create_conversation`, and `create_user`. This represents
    the ID of the object in the Intercom system.


    **Q: Do message APIs support attachments?**


    **A:** Yes, attachments are supported. The format of attachments is outlined
    in the Messages section of the API docs.


    Messages can contain:

    - Text body only (no attachments)

    - Attachments only (no text body - body can be null or empty string)

    - Both text body and attachments


    However, a message cannot be completely empty - it must have either a body
    or at least one attachment.


    **Q: What HTML is supported in message content?**


    **A:** The following HTML tags are supported in the Message object:


    - Paragraphs: `<p>`

    - Headings: `<h1>`, `<h2>` (note: h3-h6 appear as h2)

    - Text formatting: `<b>` (bold), `<i>` (italic)

    - Links: `<a>`

    - Images: `<img>` (can be linked)

    - Line breaks: `<br>`

    - Code blocks: `<code>`

    - Lists: `<ul>` (unordered), `<ol>` (ordered)


    Example HTML:


    ```html

    <!-- Headings (h1–h6) -->

    <h1>Heading 1</h1>

    <h2>Heading 2</h2>

    <h3>Heading 3</h3>

    <h4>Heading 4</h4>

    <h5>Heading 5</h5>

    <h6>Heading 6</h6>


    <!-- Paragraphs with inline formatting and link -->

    <p>
      Normal paragraph with <a href="https://example.com">a link</a>, <b>bold</b>,
      <i>italic</i>, and a line break<br />right here.
    </p>


    <!-- Image and linked image -->

    <img src="https://placehold.co/600x400/png" alt="Example image" />

    <a href="https://example.com"
      ><img src="https://placehold.co/200x120/png" alt="Linked image"
    /></a>


    <!-- Lists: unordered, ordered-->

    <ul>
      <li>Unordered item 1</li>
      <li>Unordered item 2</li>
    </ul>


    <ol>
      <li>Ordered item 1</li>
      <li>Ordered item 2</li>
    </ol>


    <!-- Code block -->

    <code> console.log('hello world!'); </code>

    ```


    ---


    ## **Agent & Conversation Management**


    **Q: Does the get_agent API need conversation ID parameters?**


    **A:** No. `get_agent` is only used during initial Fin configuration to
    select which agent represents Fin in the external system. You can return a
    single hardcoded bot agent here.


    **Q: How will Intercom inform us that a human agent needs to join a
    conversation?**


    **A:** Intercom sends an `update_conversation` call with `assignee_id` set
    to null.


    ---


    ## **Attributes & Data Structure**


    **Q: Are conversation-level attributes separate from user attributes?**


    **A:** Yes. Structure is:


    ```json

    {
      "conversation": {
        "attributes": {
          // conversation-specific data like locale, topic, sentiment, order_id
        },
        "user": {
          "id": "...",
          "type": "end-user",
          "name": "...",
          "attributes": {
            // user-specific custom attributes
          }
        }
      }
    }

    ```


    **Q: When EndUser attributes change, will update_conversation be called?**


    **A:** Yes. Conversation and user state is synchronized on each
    inbound/outbound event (new messages, user data updates via workflows, for
    example an Email Collector step, etc.).


    ---


    ## **Request Verification**


    **Q: How do I verify that incoming requests are genuine?**


    **A:** We provide two extra headers on our requests to your servers:

    - `X-Fin-Request-Timestamp` - This is the timestamp of the request (in
    seconds since epoch). You may use this to reject requests that are too old.

    - `X-Fin-Signature` - This is the SHA256 HMAC signature of
    `{timestamp}:{request_body}`. You may use this to verify the authenticity of
    the request from us.


    Note as there is no body for GET requests, we instead sign:
    `{timestamp}:{request_params_sorted_alphabetically}`.


    The HMAC key used to validate the signature is found in your deployment
    settings.


    ---


    ## **Connecting Fin to your endpoints**


    **1** - Navigate to the Deploy > Fin Messenger section in your Fin
    Workspace.


    <a href="/static/images/standalone-chd-1.png" target="_blank"><img
    src="/static/images/standalone-chd-1.png" alt="standalone-chd-1" /></a>


    **2** - You can give your integration a name to identify it. We will support
    multiple different connections later (e.g. for multiple different sub-brands
    you may have)


    Please note that "Channel type" is currently static with the value "Fin
    messenger". We will support other channel types at a later time.


    Make note of the *Identifier* value you are given here. This is the
    identifer you must use in your webhooks back to the Fin system.


    **3** - Configure your API endpoint URLs. What these endpoints are for and
    the request/response format is described in the rest of these docs.


    <a href="/static/images/standalone-chd-3.png" target="_blank"><img
    src="/static/images/standalone-chd-3.png" alt="standalone-chd-3" /></a>


    **4** - Set up authentication for your endpoints. By default we use OAuth
    for this. Choose the "OAuth token settings" option and configure the OAuth
    connection with your server.


    Note, you may whitelist Intercom's IP address ranges based on the
    [documentation
    here](https://developers.intercom.com/docs/webhooks#which-ip-addresses-should-i-add-to-my-allowlist-for-intercom-webhooks)


    <a href="/static/images/standalone-chd-4.png" target="_blank"><img
    src="/static/images/standalone-chd-4.png" alt="standalone-chd-4" /></a>


    <a href="/static/images/standalone-chd-5.png" target="_blank"><img
    src="/static/images/standalone-chd-5.png" alt="standalone-chd-5" /></a>


    **5** - Note the webhook secret generated for you. This must be provided in
    the X-Webhook-Key header in webhook requests to the Fin system.


    <a href="/static/images/standalone-chd-6.png" target="_blank"><img
    src="/static/images/standalone-chd-6.png" alt="standalone-chd-6" /></a>


    **6** - Choose a agent from your system to attribute Fin's replies to.


    When Fin generate a response for the customer, we will use the ID of the
    agent chosen here when creating messages in your system.


    <a href="/static/images/standalone-chd-7.png" target="_blank"><img
    src="/static/images/standalone-chd-7.png" alt="standalone-chd-7" /></a>


    **7** - Finally, when you've configured your workflow and installed the Fin
    Messenger you're ready to activate Fin.


    <a href="/static/images/standalone-chd-8.png" target="_blank"><img
    src="/static/images/standalone-chd-8.png" alt="standalone-chd-8" /></a>
  contact:
    name: Intercom Developer Support
    url: https://developers.intercom.com
  x-logo:
    url: https://www.intercom.com/favicon.ico
servers:
  - url: https://helpdesk.example.com/api/fin
    description: Your Custom Helpdesk API (replace with your actual domain)
tags:
  - name: Users
    description: Manage end-users in your helpdesk system
  - name: Agents
    description: Manage agents in your helpdesk system
  - name: Conversations
    description: Manage conversations between end-users and agents
  - name: Messages
    description: Manage messages within conversations
  - name: Webhooks
    description: Notify Fin when conversations change
security:
  - BearerAuth: []
paths:
  /get_user:
    post:
      tags:
        - Users
      summary: Get User
      description: >
        Retrieve an end-user by their ID.


        Used to load an end-user from the customer's system. We will call this
        during synchronization to get the latest data about the end-user to
        drive the Fin workflows and tasks correctly.

        If using the Fin messenger with a logged in and verified end-user, we
        will load the end- user when they start a new conversation.
      operationId: getUser
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GetUserRequest'
      responses:
        '200':
          description: Find a user by their ID
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndUserResponse'
              examples:
                userFound:
                  $ref: '#/components/examples/UserFoundExample'
                userNotFound:
                  $ref: '#/components/examples/UserNotFoundExample'
  /update_user:
    post:
      tags:
        - Users
      summary: Update User
      description: Update an end-user by their ID.
      operationId: updateUser
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: User updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndUserResponse'
              examples:
                userUpdated:
                  $ref: '#/components/examples/UserFoundExample'
                userNotFound:
                  $ref: '#/components/examples/UserNotFoundExample'
  /create_user:
    post:
      tags:
        - Users
      summary: Create User
      description: >
        When an end-user starts a conversation in the Fin Messenger and there is
        no information about them in the third party we request a new record be
        created.
      operationId: createUser
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: End-user created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndUser'
              examples:
                userCreated:
                  $ref: '#/components/examples/UserCreatedExample'
                badRequest:
                  $ref: '#/components/examples/UserCreationBadRequestExample'
  /get_agents:
    post:
      tags:
        - Agents
      summary: Get Agents
      description: >
        The customer must choose an Agent from within their own system to act as
        Fin.


        When we tell the customer about responses from Fin, the author ID will
        be the agent chosen to act as Fin.
      operationId: getAgents
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: Agents retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentsResponse'
              examples:
                agentsFound:
                  $ref: '#/components/examples/AgentsFoundExample'
                noAgents:
                  $ref: '#/components/examples/NoAgentsExample'
  /get_conversation:
    post:
      tags:
        - Conversations
      summary: Get Conversation
      description: >-
        Used to load a known conversation from the customer's system. Used
        during ongoing synchronizations.
      operationId: getConversation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GetConversationRequest'
      responses:
        '200':
          description: Conversation found successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConversationResponse'
              examples:
                conversationFound:
                  $ref: '#/components/examples/ConversationFoundExample'
                conversationNotFound:
                  $ref: '#/components/examples/ConversationNotFoundExample'
  /update_conversation:
    post:
      tags:
        - Conversations
      summary: Update Conversation
      description: >-
        Called at the end of a synchronization run to push the latest derived
        data into the Customer's system.
      operationId: updateConversation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateConversationRequest'
      responses:
        '200':
          description: Conversation updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConversationResponse'
              examples:
                conversationUpdated:
                  $ref: '#/components/examples/ConversationUpdatedExample'
                conversationNotFound:
                  $ref: '#/components/examples/ConversationNotFoundExample'
  /create_conversation:
    post:
      tags:
        - Conversations
      summary: Create Conversation
      description: >
        Called when a new conversation has been created via the Fin Messenger.

        Note we provide the initial message from the conversation as we know
        many help desks require this to be provided when creating a
        conversation.

        The response requires both the conversation object and the message
        object so that these can be mapped correctly to their Fin equivalents.
      operationId: createConversation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateConversationRequest'
      responses:
        '200':
          description: Conversation created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateConversationResponse'
              examples:
                conversationCreated:
                  $ref: '#/components/examples/ConversationCreatedExample'
                badRequest:
                  $ref: '#/components/examples/ConversationCreationBadRequestExample'
  /get_messages:
    post:
      tags:
        - Messages
      summary: Get Messages
      description: >
        Called during synchronization to pull in the messages from the
        conversation in your system.

        Messages which have already been synchronized will be ignored. New
        messages will be pulled into Fin's version of the Conversation.
      operationId: getMessages
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GetMessagesRequest'
      responses:
        '200':
          description: Messages retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessagesResponse'
              examples:
                messagesFound:
                  $ref: '#/components/examples/MessagesFoundExample'
                noMessages:
                  $ref: '#/components/examples/NoMessagesExample'
  /create_message:
    post:
      tags:
        - Messages
      summary: Create Message
      description: >
        Used during synchronization to push new messages into your helpdesk.
        These messages may come from either the end-user or Fin.

        Note that the author of the Fin messages will be the agent selected to
        represent Fin on initial setup of the integration.
      operationId: createMessage
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateMessageRequest'
      responses:
        '201':
          description: Message created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
              examples:
                messageCreated:
                  $ref: '#/components/examples/MessageCreatedExample'
                badRequest:
                  $ref: '#/components/examples/MessageCreationBadRequestExample'
  /custom_helpdesk_conversation_event/{integration_id}:
    post:
      parameters:
        - name: integration_id
          in: path
          schema:
            type: string
          required: true
          description: >-
            The ID of your integration. You can find this in the Fin Deployment
            UI.
          example: a3c729d4e8f6b15c
      tags:
        - Webhooks
      summary: Notify Fin of Conversation Events
      description: >
        This endpoint handles two distinct use cases depending on whether an
        `event_type` is provided:


        ## 1. Conversation Synchronization (default behavior)


        When you **omit the `event_type` field**, Fin will synchronize the
        conversation by pulling the latest data from your endpoints. Use this
        when:

        - An agent sends a message

        - The conversation state changes (status, assignee, etc.)

        - Any other conversation data changes that Fin should know about


        **Example payload:**

        ```json

        {
          "conversation_id": "conv_456"
        }

        ```


        ## 2. Agent Typing Indicator


        When you set `event_type` to `agent_typing`, Fin will display a typing
        indicator to the end-user in the Fin Messenger. **No synchronization
        occurs** - this is purely a real-time UI update.


        Use this when an agent starts typing a response in your helpdesk. The
        typing indicator automatically dismisses after a few seconds.


        **Important:** When using `event_type: "agent_typing"`, the `data.agent`
        field is **required** and must include the agent's `id`, `user_type`,
        `name`, and `email`.


        **Example payload:**

        ```json

        {
          "conversation_id": "conv_456",
          "event_type": "agent_typing",
          "data": {
            "agent": {
              "id": "agent_001",
              "user_type": "agent",
              "name": "Sarah Johnson",
              "email": "sarah.johnson@company.com"
            }
          }
        }

        ```
      operationId: customHelpdeskConversationEvent
      servers:
        - url: https://api.intercom.io/hooks/standalone
          description: Fin Webhook US Endpoint
        - url: https://api.eu.intercom.io/hooks/standalone
          description: Fin Webhook EU Endpoint
        - url: https://api.au.intercom.io/hooks/standalone
          description: Fin Webhook AU Endpoint
      security:
        - WebhookSignature: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookConversationEventRequest'
            examples:
              conversation_sync:
                summary: Conversation Synchronization
                value:
                  conversation_id: conv_456
              agent_typing:
                summary: Agent Typing Indicator
                value:
                  conversation_id: conv_456
                  event_type: agent_typing
                  data:
                    agent:
                      id: agent_001
                      user_type: agent
                      name: Sarah Johnson
                      email: sarah.johnson@company.com
      responses:
        '204':
          description: Webhook accepted
        '400':
          description: >
            Invalid payload. Common causes:

            - `event_type` is `agent_typing` but `data.agent` is missing or
            invalid

            - `data.agent` is missing required fields (`id`, `user_type`,
            `name`, `email`)
        '401':
          description: Invalid or missing webhook signature
        '404':
          description: Custom helpdesk integration not found
components:
  securitySchemes:
    BearerAuth:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://helpdesk.fin.com/api/auth/oauth/token
          scopes:
            read: Read access to the API (example)
            write: Write access to the API (example)
      description: OAuth2 access token configured in Fin Deployment UI
    WebhookSignature:
      type: apiKey
      in: header
      name: X-Webhook-Key
      description: >-
        Webhook key for the custom helpdesk integration. Obtained from Fin
        Deployment UI.
  schemas:
    GetUserRequest:
      type: object
      properties:
        user_id:
          type: string
          description: ID of the end-user in your system
          example: user_123
    UpdateUserRequest:
      type: object
      properties:
        user_id:
          type: string
          description: ID of the end-user in your system
          example: user_123
        attributes:
          $ref: '#/components/schemas/CustomAttributes'
    CreateUserRequest:
      type: object
      properties:
        name:
          type: string
          description: User's name (may not be known at creation time)
          example: Jane Doe
          nullable: true
        email:
          type: string
          format: email
          description: User's email (may not be known at creation time)
          example: jane.doe@example.com
          nullable: true
        object_id:
          type: string
          description: Unique identifier for the user in our system
          example: '123456'
        attributes:
          allOf:
            - $ref: '#/components/schemas/CustomAttributes'
            - nullable: true
    GetConversationRequest:
      type: object
      properties:
        conversation_id:
          type: string
          description: ID of the conversation in your system
          example: conv_456
    UpdateConversationRequest:
      type: object
      properties:
        conversation_id:
          type: string
          description: ID of the conversation to update
          example: conv_456
        title:
          type: string
          description: Conversation title
          example: Pricing inquiry - resolved
          nullable: true
        tags:
          type: array
          description: >-
            List of tags associated with the conversation in your system. Can be
            used to power routing within the Fin workflow among other things.
          items:
            type: string
          example:
            - pricing
            - sales
        attributes:
          $ref: '#/components/schemas/ConversationAttributes'
        status:
          $ref: '#/components/schemas/ConversationStatus'
        assignee_id:
          type: string
          description: >-
            Agent ID (Fin agent). Set to null when handing over to a human
            agent.
          example: agent_fin
        last_user_read_at:
          type: string
          format: date-time
          description: When user last read the conversation
          example: '2025-10-27T15:45:00.000Z'
          nullable: true
        user:
          $ref: '#/components/schemas/UserBasic'
    CreateConversationRequest:
      type: object
      properties:
        title:
          type: string
          description: Conversation title (may be blank)
          example: Question about pricing
          nullable: true
        user:
          $ref: '#/components/schemas/UserBasic'
        object_id:
          type: string
          description: Unique identifier for the conversation in our system
          example: '123456'
        attributes:
          $ref: '#/components/schemas/ConversationAttributes'
        initial_message:
          $ref: '#/components/schemas/MessageInput'
    GetMessagesRequest:
      type: object
      properties:
        conversation_id:
          type: string
          description: ID of the conversation in your system
          example: conv_456
        after_id:
          type: string
          description: >-
            ID of the last seen message ID from the external system. As an
            optimization, the external service may choose to return only
            messages created after this.
          example: msg_101
    CreateMessageRequest:
      allOf:
        - $ref: '#/components/schemas/MessageInput'
        - type: object
          properties:
            conversation_id:
              type: string
              description: ID of the parent conversation
              example: conv_456
    WebhookConversationEventRequest:
      type: object
      required:
        - conversation_id
      properties:
        conversation_id:
          type: string
          description: ID of the conversation in your system
          example: conv_456
        event_type:
          type: string
          description: >
            Optional. The type of event that occurred.


            - **Omitted or null**: Fin will synchronize the conversation by
            pulling the latest data from your endpoints.

            - `agent_typing`: Displays a typing indicator to the end-user. No
            synchronization occurs. Requires `data.agent` to be provided.
          enum:
            - agent_typing
        data:
          type: object
          description: |
            Additional event data. Required fields depend on the `event_type`:
            - For `agent_typing`: the `agent` field is required.
          properties:
            agent:
              $ref: '#/components/schemas/Agent'
              description: >
                The agent who is typing. **Required** when `event_type` is
                `agent_typing`.

                Must include: `id`, `user_type` (must be "agent"), `name`, and
                `email`.
    EndUserResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/EndUser'
        error:
          $ref: '#/components/schemas/ProblemDetails'
          nullable: true
    AgentsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Agent'
        error:
          $ref: '#/components/schemas/ProblemDetails'
          nullable: true
    ConversationResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Conversation'
        error:
          $ref: '#/components/schemas/ProblemDetails'
          nullable: true
    CreateConversationResponse:
      type: object
      properties:
        data:
          type: object
          required:
            - conversation
            - message
          properties:
            conversation:
              $ref: '#/components/schemas/Conversation'
              description: The newly created conversation in your system.
            message:
              $ref: '#/components/schemas/Message'
              description: >-
                The initial message in the conversation that was created in your
                system.
        error:
          $ref: '#/components/schemas/ProblemDetails'
          nullable: true
    MessagesResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Message'
        error:
          $ref: '#/components/schemas/ProblemDetails'
          nullable: true
    MessageResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Message'
        error:
          $ref: '#/components/schemas/ProblemDetails'
          nullable: true
    EndUser:
      type: object
      description: End user having a conversation with Fin or with an agent.
      required:
        - id
        - user_type
      properties:
        id:
          type: string
          description: Unique identifier for the user in your system
          example: user_123456
          nullable: false
        user_type:
          type: string
          description: Type of user
          enum:
            - end_user
          nullable: false
        name:
          type: string
          description: User's display name
          example: Jane Doe
          nullable: true
        email:
          type: string
          format: email
          description: User's email address
          example: jane.doe@example.com
          nullable: true
        photo_url:
          type: string
          format: uri
          description: URL to user's avatar/profile picture (displayed in Fin Messenger)
          example: https://example.com/avatars/jane.jpg
          nullable: true
        attributes:
          allOf:
            - $ref: '#/components/schemas/CustomAttributes'
            - nullable: true
    Agent:
      type: object
      description: Agent having a conversation with an end-user.
      required:
        - id
        - user_type
        - name
        - email
      properties:
        id:
          type: string
          description: Unique identifier for the user in your system
          example: agent_123456
        user_type:
          type: string
          description: Type of user
          enum:
            - agent
        name:
          type: string
          description: User's display name
          example: Jane Doe
        email:
          type: string
          format: email
          description: User's email address
          example: jane.doe@example.com
        photo_url:
          type: string
          format: uri
          description: URL to user's avatar/profile picture (displayed in Fin Messenger)
          example: https://example.com/avatars/jane.jpg
          nullable: true
        alias_name:
          type: string
          description: Agent's display alias_name (shown to end-users instead of real name)
          example: Support Jane
          nullable: true
    Conversation:
      type: object
      required:
        - id
        - status
        - user
        - created_at
        - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for the conversation in your system
          example: conv_456
        status:
          $ref: '#/components/schemas/ConversationStatus'
        user:
          $ref: '#/components/schemas/EndUser'
        title:
          type: string
          description: Conversation title or subject
          example: Question about pricing plans
          nullable: true
        tags:
          type: array
          description: >-
            List of tags associated with the conversation in your system. Can be
            used to power routing within the Fin workflow among other things.
          items:
            type: string
          example:
            - pricing
            - sales
          nullable: true
        attributes:
          $ref: '#/components/schemas/ConversationAttributes'
        assignee:
          allOf:
            - $ref: '#/components/schemas/Agent'
            - nullable: true
              description: >-
                Currently assigned agent (null if unassigned) in your system.
                Fin typically does not attempt to handle conversations assigned
                to a human agent. If your system allows for multiple agents to
                be assigned to a conversation you may choose to return any one
                of these agents.
        created_at:
          type: string
          format: date-time
          description: When the conversation was created (ISO 8601 UTC)
          example: '2025-10-27T14:30:00.000Z'
        updated_at:
          type: string
          format: date-time
          description: When the conversation was last updated (ISO 8601 UTC)
          example: '2025-10-27T15:45:00.000Z'
    Message:
      type: object
      description: >
        A message in a conversation. Either `body` or `attachments` (or both)
        must be provided.

        A message cannot be empty - it must contain either text content or at
        least one attachment.
      required:
        - id
        - conversation_id
        - message_type
        - author
        - visibility
        - created_at
      properties:
        id:
          type: string
          description: Unique identifier for the message in your system
          example: msg_001
        conversation_id:
          type: string
          description: ID of the parent conversation
          example: conv_456
        message_type:
          $ref: '#/components/schemas/MessageType'
        body:
          allOf:
            - $ref: '#/components/schemas/HtmlMessageBody'
            - description: >-
                Message content in HTML format. Can be null or empty if
                attachments are provided.
              nullable: true
        author:
          oneOf:
            - $ref: '#/components/schemas/EndUser'
            - $ref: '#/components/schemas/Agent'
          description: The user who authored the message.
        visibility:
          $ref: '#/components/schemas/MessageVisibility'
        created_at:
          type: string
          format: date-time
          description: When the message was created (ISO 8601 UTC)
          example: '2025-10-27T14:35:00.000Z'
        attachments:
          type: array
          description: Files attached to the message
          items:
            $ref: '#/components/schemas/Attachment'
    Attachment:
      type: object
      properties:
        url:
          type: string
          format: uri
          description: >
            URL where the attachment can be accessed.

            Must be HTTPS. Consider using signed URLs with expiration for
            sensitive files.
          example: https://example.com/files/pricing-guide.pdf
        filetype:
          type: string
          description: File type/extension.
          example: pdf
        filename:
          type: string
          description: Display name for the file
          example: Pricing Guide 2025
    ProblemDetails:
      type: object
      description: >
        The error returned by the API. This is an RFC 7807 problem details
        object: <https://www.rfc-editor.org/rfc/rfc7807.html>.
      properties:
        type:
          type: string
          description: A URI reference that identifies the problem type.
        title:
          type: string
          description: A short, human-readable summary of the problem type.
        status:
          type: integer
          description: >-
            The HTTP status code generated by the origin server for this
            occurrence of the problem.
        detail:
          type: string
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem.
        instance:
          type: string
          description: >-
            A URI reference that identifies the specific occurrence of the
            problem.
    CustomAttributes:
      type: object
      description: Attributes associated with the end-user
      additionalProperties:
        anyOf:
          - type: string
          - type: integer
          - type: number
          - type: boolean
          - type: string
            format: date-time
            description: ISO 8601 timestamp
            example: '2025-10-27T14:30:00.000Z'
      example:
        plan_type: enterprise
        signup_date: '2024-01-15'
        is_premium: true
    ConversationAttributes:
      type: object
      description: Attributes associated with the conversation
      additionalProperties:
        anyOf:
          - type: string
          - type: integer
          - type: number
          - type: boolean
      example:
        issue_type: Billing
        priority: High
    ConversationStatus:
      type: string
      description: |
        Current conversation status:
        - `open` - Conversation is actively ongoing with the end-user
        - `resolved` - Conversation is resolved by Fin
        - `closed` - Conversation is finished/archived
        - `ended` - Conversation is ended by the end-user or agent
      enum:
        - open
        - resolved
        - closed
        - ended
      example: resolved
    MessageType:
      type: string
      description: Type of message
      enum:
        - comment
      example: comment
    MessageVisibility:
      type: string
      description: |
        Who can see the message:
        - `public` - Visible to end-users (appears in Fin Messenger)
        - `private` - Only visible to agents (internal notes)
      enum:
        - public
        - private
      example: public
    HtmlMessageBody:
      type: string
      description: |
        Message content in HTML format.

        Supported HTML tags are:
        - Paragraphs `<p>`
        - Heading 1, Heading 2 `<h1>` `<h2>` (note h3 to h6 appears as a h2)
        - Bold `<b>`
        - Italic `<i>`
        - Links `<a>`
        - Images `<img>` (can be linked)
        - Line breaks `<br>`
        - Code blocks `<code>`
        - Unordered lists `<ul>`
        - Ordered lists `<ol>`
      example: <p>Hi! I'd like to know more about your pricing plans.</p>
    UserBasic:
      type: object
      description: Basic user information for requests
      properties:
        id:
          type: string
          description: Unique identifier for the user in your system
          example: user_123456
        name:
          type: string
          description: User's display name
          example: Jane Doe
        email:
          type: string
          format: email
          description: User's email address
          example: jane.doe@example.com
        photo_url:
          type: string
          format: uri
          description: URL to user's avatar/profile picture (displayed in Fin Messenger)
          example: https://example.com/avatars/jane.jpg
        user_type:
          type: string
          description: Type of user
          enum:
            - end_user
          example: end_user
        attributes:
          allOf:
            - $ref: '#/components/schemas/CustomAttributes'
            - nullable: true
    MessageInput:
      type: object
      description: >
        Message input fields for creation. Either `body` or `attachments` (or
        both) must be provided.

        A message cannot be empty - it must contain either text content or at
        least one attachment.
      properties:
        message_type:
          $ref: '#/components/schemas/MessageType'
        body:
          allOf:
            - $ref: '#/components/schemas/HtmlMessageBody'
            - description: >-
                Message content in HTML format. Can be null or empty if
                attachments are provided.
              nullable: true
        author:
          $ref: '#/components/schemas/MessageAuthor'
        visibility:
          $ref: '#/components/schemas/MessageVisibility'
        object_id:
          type: string
          description: Unique identifier for the message in our system
          example: '123456'
        attachments:
          type: array
          description: Array of attachments (can be empty)
          items:
            $ref: '#/components/schemas/Attachment'
    MessageAuthor:
      type: object
      description: The user who authored the message
      properties:
        id:
          type: string
          description: Unique identifier for the user in your system
          example: user_123456
        user_type:
          type: string
          description: Type of user
          enum:
            - end_user
            - agent
        name:
          type: string
          description: User's display name
          example: Jane Doe
        email:
          type: string
          format: email
          description: User's email address
          example: jane.doe@example.com
        photo_url:
          type: string
          format: uri
          description: URL to user's avatar/profile picture (displayed in Fin Messenger)
          example: https://example.com/avatars/jane.jpg
  examples:
    UserFoundExample:
      summary: User found
      value:
        data:
          id: user_123
          name: John Doe
          email: john.doe@example.com
          photo_url: https://example.com/avatars/john.jpg
          user_type: end_user
          attributes:
            plan_type: enterprise
            signup_date: '2024-01-15'
            is_premium: true
    UserNotFoundExample:
      summary: User not found
      value:
        data: {}
        error:
          type: https://example.com/probs/no-user-found
          title: No user found
          status: 404
          detail: No user found with the given ID
          instance: >-
            https://example.com/errors/2025-01-18/550e8400-e29b-41d4-a716-446655440000
    UserCreatedExample:
      summary: End-user created successfully
      value:
        data:
          id: user_123456
          name: Jane Doe
          email: jane.doe@example.com
          photo_url: https://example.com/avatars/jane.jpg
          user_type: end_user
          attributes:
            plan_type: enterprise
            signup_date: '2024-01-15'
            is_premium: true
    UserCreationBadRequestExample:
      summary: Bad Request
      value:
        data: {}
        error:
          type: https://example.com/probs/bad-request
          title: Email is required
          status: 400
          detail: Email is required to create a user
          instance: >-
            https://example.com/errors/2025-01-18/550e8400-e29b-41d4-a716-446655440000
    AgentsFoundExample:
      summary: Multiple agents including Fin
      value:
        data:
          - id: agent_001
            user_type: agent
            name: Sarah Johnson
            email: sarah.johnson@company.com
            alias_name: Support Sarah
            photo_url: https://example.com/avatars/sarah.jpg
          - id: agent_fin
            user_type: agent
            name: Fin AI Assistant
            email: fin@company.com
            alias_name: Fin
            photo_url: https://example.com/avatars/fin.png
    NoAgentsExample:
      summary: No agents found
      value:
        data: []
    ConversationFoundExample:
      summary: Conversation found successfully
      value:
        data:
          id: conv_456
          title: Question about pricing
          status: ended
          user:
            id: user_123
            name: Jane Doe
            email: jane.doe@example.com
            photo_url: https://example.com/avatars/jane.jpg
            user_type: end_user
            attributes:
              plan_type: enterprise
              signup_date: '2024-01-15'
              is_premium: true
          tags:
            - pricing
            - sales
          attributes:
            issue_type: Billing
            priority: High
          assignee:
            id: agent_fin
            name: Fin AI Assistant
            email: fin@company.com
            alias_name: Fin
            photo_url: https://example.com/avatars/fin.png
            user_type: agent
          created_at: '2025-10-27T14:30:00.000Z'
          updated_at: '2025-10-27T14:30:00.000Z'
    ConversationNotFoundExample:
      summary: Conversation not found
      value:
        data: {}
        error:
          type: https://example.com/probs/no-conversation-found
          title: No conversation found
          status: 404
          detail: No conversation found with the given ID
          instance: >-
            https://example.com/errors/2025-01-18/550e8400-e29b-41d4-a716-446655440000
    ConversationUpdatedExample:
      summary: Conversation updated successfully
      value:
        data:
          id: conv_456
          title: Pricing inquiry - resolved
          status: ended
          user:
            id: user_123
            name: Jane Doe
            email: jane.doe@example.com
            photo_url: https://example.com/avatars/jane.jpg
            user_type: end_user
            attributes:
              plan_type: enterprise
              signup_date: '2024-01-15'
              is_premium: true
          tags:
            - pricing
            - sales
          assignee:
            id: agent_fin
            name: Fin AI Assistant
            email: fin@company.com
            alias_name: Fin
            photo_url: https://example.com/avatars/fin.png
            user_type: agent
          created_at: '2025-10-27T14:30:00.000Z'
          updated_at: '2025-10-27T14:30:00.000Z'
    ConversationCreatedExample:
      summary: Conversation created successfully
      value:
        data:
          conversation:
            id: conv_456
            status: open
            title: Question about pricing
            user:
              id: user_123
              name: Jane Doe
              email: jane.doe@example.com
              photo_url: https://example.com/avatars/jane.jpg
              user_type: end_user
              attributes:
                plan_type: enterprise
                signup_date: '2024-01-15'
                is_premium: true
            tags:
              - pricing
              - sales
            attributes:
              issue_type: Billing
              priority: High
            assignee:
              id: agent_fin
              name: Fin AI Assistant
              email: fin@company.com
              alias_name: Fin
              photo_url: https://example.com/avatars/fin.png
              user_type: agent
            created_at: '2025-10-27T14:30:00.000Z'
            updated_at: '2025-10-27T14:30:00.000Z'
          message:
            id: msg_123
            conversation_id: conv_456
            message_type: comment
            body: <p>Hi! I'd like to know more about your pricing plans.</p>
            author:
              id: user_123456
              user_type: end_user
              name: Jane Doe
              email: jane.doe@example.com
              photo_url: https://example.com/avatars/jane.jpg
              attributes:
                plan_type: enterprise
                signup_date: '2024-01-15'
                is_premium: true
            visibility: public
            created_at: '2025-10-27T14:30:00.000Z'
            attachments:
              - url: https://example.com/files/pricing-guide.pdf
                filetype: pdf
                filename: Pricing Guide 2025
    ConversationCreationBadRequestExample:
      summary: Bad Request
      value:
        data: {}
        error:
          type: https://example.com/probs/bad-request
          title: Initial message is required
          status: 400
          detail: Initial message is required to create a conversation
          instance: >-
            https://example.com/errors/2025-01-18/550e8400-e29b-41d4-a716-446655440000
    MessagesFoundExample:
      summary: Multiple messages
      value:
        data:
          - id: msg_101
            conversation_id: conv_456
            message_type: comment
            body: <p>Thank you for reaching out! I'd be happy to help.</p>
            author:
              id: agent_fin
              user_type: agent
              name: Fin AI Assistant
              email: fin@company.com
              alias_name: Fin
              photo_url: https://example.com/avatars/fin.png
            visibility: public
            created_at: '2025-10-27T14:35:00.000Z'
            attachments: []
          - id: msg_102
            conversation_id: conv_456
            message_type: comment
            body: <p>Great! Can you tell me about the Enterprise plan?</p>
            author:
              id: user_123
              user_type: end_user
              name: Jane Doe
              email: jane@example.com
              photo_url: https://example.com/avatars/jane.jpg
              attributes:
                attribute_1_name: attribute_1_value
                attribute_2_name: attribute_2_value
            visibility: public
            created_at: '2025-10-27T14:37:00.000Z'
            attachments: []
    NoMessagesExample:
      summary: No messages
      value:
        data: []
    MessageWithOnlyAttachmentsExample:
      summary: Message with only attachments (no text body)
      value:
        data:
          - id: msg_103
            conversation_id: conv_456
            message_type: comment
            body: null
            author:
              id: user_123
              user_type: end_user
              name: Jane Doe
              email: jane@example.com
              photo_url: https://example.com/avatars/jane.jpg
            visibility: public
            created_at: '2025-10-27T14:40:00.000Z'
            attachments:
              - url: https://example.com/files/screenshot.png
                filetype: png
                filename: Error Screenshot
              - url: https://example.com/files/log-file.txt
                filetype: txt
                filename: Application Log
    MessageCreatedExample:
      summary: Message created successfully
      value:
        data:
          id: msg_123
          conversation_id: conv_456
          message_type: comment
          body: <p>Hi! I'd like to know more about your pricing plans.</p>
          author:
            id: user_123456
            user_type: end_user
            name: Jane Doe
            email: jane.doe@example.com
            photo_url: https://example.com/avatars/jane.jpg
            attributes:
              plan_type: enterprise
              signup_date: '2024-01-15'
              is_premium: true
          visibility: public
          created_at: '2025-10-27T14:30:00.000Z'
          attachments:
            - url: https://example.com/files/pricing-guide.pdf
              filetype: pdf
              filename: Pricing Guide 2025
    MessageCreationBadRequestExample:
      summary: Bad Request
      value:
        data: {}
        error:
          type: https://example.com/probs/bad-request
          title: Conversation ID is required
          status: 400
          detail: Conversation ID is required to create a message
          instance: >-
            https://example.com/errors/2025-01-18/550e8400-e29b-41d4-a716-446655440000
