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.
  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:
  /user:
    get:
      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
      parameters:
        - name: user_id
          in: query
          schema:
            type: string
      responses:
        '200':
          description: User found successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndUser'
    put:
      tags:
        - Users
      summary: Update User
      description: |
        Update an end-user by their ID.
      operationId: updateUser
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                user_id:
                  type: string
                  description: ID of the end-user in your system
                  example: user_123
                attributes:
                  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
      responses:
        '200':
          description: User updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndUser'
    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:
              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'
      responses:
        '201':
          description: End-user created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndUser'
  /agents:
    get:
      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
      responses:
        '200':
          description: Agents retrieved successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Agent'
              examples:
                example1:
                  summary: Multiple agents including Fin
                  value:
                    - id: agent_001
                      user_type: agent
                      name: Sarah Johnson
                      email: sarah.johnson@company.com
                      alias: 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: Fin
                      photo_url: https://example.com/avatars/fin.png
  /conversation:
    get:
      tags:
        - Conversations
      summary: Get Conversation
      description: >
        Used to load a known conversation from the customer's system. Used
        during ongoing synchronizations.
      operationId: getConversation
      parameters:
        - name: conversation_id
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Conversation found successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Conversation'
    put:
      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:
              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:
                  type: object
                  description: Attributes associated with the conversation
                  additionalProperties:
                    anyOf:
                      - type: string
                      - type: integer
                      - type: number
                      - type: boolean
                  example:
                    issue_type: Billing
                    priority: High
                status:
                  type: string
                  description: Conversation status
                  enum:
                    - open
                    - resolved
                    - closed
                    - ended
                  example: resolved
                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
      responses:
        '200':
          description: Conversation updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/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:
              type: object
              properties:
                title:
                  type: string
                  description: Conversation title (may be blank)
                  example: Question about pricing
                  nullable: true
                user_id:
                  type: string
                  description: ID of the end-user in your system
                  example: user_123
                object_id:
                  type: string
                  description: Unique identifier for the conversation in our system
                  example: '123456'
                initial_message:
                  type: object
                  properties:
                    conversation_id:
                      type: string
                      description: ID of the parent conversation
                      example: conv_456
                    message_type:
                      type: string
                      description: Type of message
                      enum:
                        - comment
                    body:
                      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>
                    author:
                      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
                    visibility:
                      type: string
                      description: Message visibility
                      enum:
                        - public
                        - private
                    attributes:
                      type: object
                      description: Attributes associated with the conversation
                      additionalProperties:
                        anyOf:
                          - type: string
                          - type: integer
                          - type: number
                          - type: boolean
                      example:
                        issue_type: Billing
                        priority: High
                    created_at:
                      type: string
                      format: date-time
                      description: ISO 8601 timestamp
                      example: '2025-10-27T14:30:00.000Z'
                    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'
      responses:
        '201':
          description: Conversation created successfully
          content:
            application/json:
              schema:
                type: object
                required:
                  - conversation
                  - initial_message
                properties:
                  conversation:
                    $ref: '#/components/schemas/Conversation'
                    description: The newly created conversation in your system.
                  initial_message:
                    $ref: '#/components/schemas/Message'
                    description: >-
                      The initial message in the conversation that was created
                      in your system.
  /messages:
    get:
      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
      parameters:
        - name: conversation_id
          description: The ID of the conversation in your system.
          in: query
          schema:
            type: string
        - name: after_id
          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.
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Messages retrieved successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Message'
              examples:
                example1:
                  summary: Multiple messages
                  value:
                    - 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: 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: []
    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:
              type: object
              properties:
                conversation_id:
                  type: string
                  description: ID of the parent conversation
                  example: conv_456
                message_type:
                  type: string
                  description: Type of message
                  enum:
                    - comment
                body:
                  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>
                author:
                  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
                visibility:
                  type: string
                  description: Message visibility
                  enum:
                    - public
                    - private
                created_at:
                  type: string
                  format: date-time
                  description: ISO 8601 timestamp
                  example: '2025-10-27T14:30:00.000Z'
                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'
      responses:
        '201':
          description: Message created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
  /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:
              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 when `event_type` is
                    `agent_typing`.
                  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`.
            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 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:
    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:
          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
          nullable: true
    Agent:
      type: object
      description: |
        Agent having a conversation with an end-user.
      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
          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
        alias:
          type: string
          description: Agent's display alias (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:
          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
        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:
          type: object
          description: Attributes associated with the conversation
          additionalProperties:
            anyOf:
              - type: string
              - type: integer
              - type: number
              - type: boolean
          example:
            issue_type: Billing
            priority: High
        assignee:
          $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
      required:
        - id
        - conversation_id
        - message_type
        - body
        - 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:
          type: string
          description: Type of message
          enum:
            - comment
        body:
          type: string
          description: Message content in HTML format
          example: >-
            <p>Thank you for reaching out! I'd be happy to explain our pricing
            plans.</p>
        author:
          oneOf:
            - $ref: '#/components/schemas/EndUser'
            - $ref: '#/components/schemas/Agent'
          description: The user who authored the message.
        visibility:
          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
        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
