> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fuseai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# A contact's activity timeline

> The contact's activity timeline as the app's activity drawer shows it, newest first: campaign emails sent and replies received, LinkedIn invitations and messages, dialer calls with their transcript, recording, disposition and the notes the rep saved, activity logged by a connected CRM, and campaign steps still scheduled to go out (`scheduledAt` set, `sentAt` null). Every entry carries the same keys whatever the channel, so `channel` tells you which of them are filled: email rows carry `subject`, `body`, `from` and `to`; LinkedIn rows carry the message text in `body` and the profile in `linkedinUrl`; call rows carry `phoneNumber`, `direction`, `callTranscript`, `callRecordingUrl`, `callDisposition`, and the call notes — not a message — in `body`. Page with `limit` (1-100, default 100) and `cursor`: copy `nextCursor` from the previous page and stop when it is null. `limit` bounds the page of history; the first page can carry a few entries on top of it (campaign steps still scheduled, and LinkedIn activity, neither of which pages on its own), so read `activities.length` rather than assuming `limit`. Free to call.

Errors:
- `404` `CONTACT_NOT_FOUND` — No contact with that id exists.
- `422` `VALIDATION_FAILED` — The path, query or body failed validation; `param` names the offending field and `message` says why.
- `429` `RATE_LIMITED` — More than 120 requests per minute or 10,000 per day on the contacts bucket, which every /business/contacts endpoint shares; retry after Retry-After.
- `500` `UNEXPECTED_ERROR` — The timeline could not be assembled; quote request_id to support.

Requires one of the following token scopes: contacts.



## OpenAPI

````yaml /openapi.json get /business/contacts/{contactId}/activities
openapi: 3.1.0
info:
  title: Fuse Business API
  version: 1.0.0
  description: >-
    External API for lists, campaigns, prospect search and contacts.
    Authenticate with your API token as HTTP Basic. All paths are under /api/v1.
servers:
  - url: https://api.tryfuse.ai/api/v1
    description: Production
security:
  - basicAuth: []
tags:
  - name: Lists
  - name: Custom columns
  - name: Smart columns
  - name: Exports
  - name: Campaigns
  - name: Knowledge hubs
  - name: Analytics
  - name: Website intent
  - name: Account
  - name: Prospect search
  - name: Campaign steps
  - name: Scheduled sends
  - name: Campaign templates
  - name: Agents
  - name: Research
  - name: Company search
  - name: Saved searches
  - name: Folders
  - name: Contacts
paths:
  /business/contacts/{contactId}/activities:
    get:
      tags:
        - Contacts
      summary: A contact's activity timeline
      description: >-
        The contact's activity timeline as the app's activity drawer shows it,
        newest first: campaign emails sent and replies received, LinkedIn
        invitations and messages, dialer calls with their transcript, recording,
        disposition and the notes the rep saved, activity logged by a connected
        CRM, and campaign steps still scheduled to go out (`scheduledAt` set,
        `sentAt` null). Every entry carries the same keys whatever the channel,
        so `channel` tells you which of them are filled: email rows carry
        `subject`, `body`, `from` and `to`; LinkedIn rows carry the message text
        in `body` and the profile in `linkedinUrl`; call rows carry
        `phoneNumber`, `direction`, `callTranscript`, `callRecordingUrl`,
        `callDisposition`, and the call notes — not a message — in `body`. Page
        with `limit` (1-100, default 100) and `cursor`: copy `nextCursor` from
        the previous page and stop when it is null. `limit` bounds the page of
        history; the first page can carry a few entries on top of it (campaign
        steps still scheduled, and LinkedIn activity, neither of which pages on
        its own), so read `activities.length` rather than assuming `limit`. Free
        to call.


        Errors:

        - `404` `CONTACT_NOT_FOUND` — No contact with that id exists.

        - `422` `VALIDATION_FAILED` — The path, query or body failed validation;
        `param` names the offending field and `message` says why.

        - `429` `RATE_LIMITED` — More than 120 requests per minute or 10,000 per
        day on the contacts bucket, which every /business/contacts endpoint
        shares; retry after Retry-After.

        - `500` `UNEXPECTED_ERROR` — The timeline could not be assembled; quote
        request_id to support.


        Requires one of the following token scopes: contacts.
      operationId: listContactActivities
      parameters:
        - name: contactId
          in: path
          required: true
          description: >-
            Id of the contact: the row id from GET
            /business/lists/{listId}/rows, or the contactId returned by POST
            /business/contacts/resolve.
          schema:
            type: string
            description: >-
              Id of the contact: the row id from GET
              /business/lists/{listId}/rows, or the contactId returned by POST
              /business/contacts/resolve.
        - name: limit
          in: query
          required: false
          description: >-
            Maximum number of activities per page, 1-100 (default 100). It
            bounds the page of history; the first page can carry a few entries
            on top of it (campaign steps still scheduled, and LinkedIn activity,
            neither of which pages on its own), so read `activities.length`
            rather than assuming `limit`.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 100
            description: >-
              Maximum number of activities per page, 1-100 (default 100). It
              bounds the page of history; the first page can carry a few entries
              on top of it (campaign steps still scheduled, and LinkedIn
              activity, neither of which pages on its own), so read
              `activities.length` rather than assuming `limit`.
        - name: cursor
          in: query
          required: false
          description: >-
            Opaque cursor copied from the previous page's `nextCursor` (max 500
            characters). Omit it for the first page.
          schema:
            type: string
            minLength: 1
            maxLength: 500
            description: >-
              Opaque cursor copied from the previous page's `nextCursor` (max
              500 characters). Omit it for the first page.
      responses:
        '200':
          description: Success
          headers:
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests permitted in the current window.
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests remaining in the current window.
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the current window resets.
          content:
            application/json:
              schema:
                type: object
                required:
                  - contactId
                  - activities
                  - nextCursor
                properties:
                  contactId:
                    type: string
                    description: Id of the contact.
                  activities:
                    type: array
                    description: >-
                      One page of the timeline, newest first, with any campaign
                      steps still scheduled pinned at the top. The first page
                      can hold a few entries more than `limit`.
                    items:
                      type: object
                      description: >-
                        One timeline entry. Every key is present on every entry;
                        which of them are filled depends on `channel`.
                      required:
                        - id
                        - channel
                        - status
                        - direction
                        - campaignId
                        - subject
                        - body
                        - sentAt
                        - receivedAt
                        - scheduledAt
                        - from
                        - to
                        - linkedinUrl
                        - phoneNumber
                        - callTranscript
                        - callRecordingUrl
                        - callDisposition
                      properties:
                        id:
                          type:
                            - string
                            - 'null'
                          description: >-
                            Id of the activity (the provider message id on
                            LinkedIn rows).
                        channel:
                          type:
                            - string
                            - 'null'
                          description: >-
                            Where the activity happened: `email`,
                            `linkedin_message`, `linkedin_connection`, `inmail`,
                            `linkedin_visit`, `linkedin_like`,
                            `non_campaign_call` (a call that was placed,
                            campaign or one-off), `dialer` (a campaign call step
                            still scheduled), `todo` (a manual campaign step),
                            and `crm_activity` for a note, meeting or task
                            logged in a connected CRM. A CRM's own emails and
                            calls arrive as `email` and `non_campaign_call` like
                            any other.
                        status:
                          type:
                            - string
                            - 'null'
                          description: >-
                            Delivery state, in the vocabulary of the store the
                            row came from. Campaign steps: scheduled,
                            approval_required, action_required, sent, replied,
                            skipped, stopped, overwritten, preview, failed.
                            Calls: answered, answered-subsequent, notAnswered,
                            callEnded, answeredByMachine, message-played, busy,
                            inbound-forwarding-not-accepted, failed, cancelled,
                            pick-up-race-dropped. LinkedIn: sent, replied.
                            Activity logged by a connected CRM: logged.
                        direction:
                          type:
                            - string
                            - 'null'
                          enum:
                            - inbound
                            - outbound
                            - null
                          description: >-
                            Direction when the channel records one (calls always
                            do); null otherwise.
                        campaignId:
                          type:
                            - string
                            - 'null'
                          description: >-
                            Campaign the activity belongs to; null for activity
                            outside a campaign.
                        subject:
                          type:
                            - string
                            - 'null'
                          description: Email subject; null on every other channel.
                        body:
                          type:
                            - object
                            - 'null'
                          description: >-
                            The text the activity carries: the email body, the
                            LinkedIn message text, or — on call rows — the notes
                            the rep saved against the call. Null when the
                            activity carries no text. Read `contentType` before
                            rendering it: the same key carries HTML and plain
                            text, and a long body can arrive shortened to a
                            snippet.
                          required:
                            - contentType
                            - content
                          properties:
                            contentType:
                              type: string
                              enum:
                                - html
                                - text
                              description: How to read `content`.
                            content:
                              type: string
                              description: >-
                                The body text, in the form `contentType` names;
                                a long body can be shortened to a snippet.
                        sentAt:
                          type:
                            - string
                            - 'null'
                          format: date-time
                          description: When an outbound activity went out.
                        receivedAt:
                          type:
                            - string
                            - 'null'
                          format: date-time
                          description: When an inbound activity arrived.
                        scheduledAt:
                          type:
                            - string
                            - 'null'
                          format: date-time
                          description: >-
                            For a campaign step that has not gone out yet: when
                            it will.
                        from:
                          type:
                            - object
                            - 'null'
                          description: >-
                            Email rows: the sender; null when the channel
                            records no address.
                          required:
                            - name
                            - address
                          properties:
                            name:
                              type:
                                - string
                                - 'null'
                              description: Display name when known.
                            address:
                              type: string
                              description: Email address.
                        to:
                          type: array
                          description: >-
                            Email rows: the recipients; empty on channels that
                            record no address.
                          items:
                            type: object
                            required:
                              - name
                              - address
                            properties:
                              name:
                                type:
                                  - string
                                  - 'null'
                                description: Display name when known.
                              address:
                                type: string
                                description: Email address.
                        linkedinUrl:
                          type:
                            - string
                            - 'null'
                          description: >-
                            LinkedIn rows: the profile the message or invitation
                            was sent to.
                        phoneNumber:
                          type:
                            - string
                            - 'null'
                          description: 'Call rows: the number dialled.'
                        callTranscript:
                          type:
                            - string
                            - 'null'
                          description: 'Call rows: the transcript when one was produced.'
                        callRecordingUrl:
                          type:
                            - string
                            - 'null'
                          description: >-
                            Call rows: a time-limited recording URL when a
                            recording exists.
                        callDisposition:
                          type:
                            - string
                            - 'null'
                          enum:
                            - connected-positive
                            - connected-neutral
                            - connected-negative
                            - connected-follow-up
                            - left-voicemail
                            - no-answer
                            - connected-busy
                            - bad-wrong-number
                            - not-specified
                            - null
                          description: >-
                            Call rows: the outcome the rep recorded.
                            `not-specified` is the default a call carries until
                            the rep sets one; null on every other channel.
                  nextCursor:
                    type:
                      - string
                      - 'null'
                    description: Cursor for the next page; null on the last page.
              example:
                contactId: 68a1f2c89c41d20014b3e955
                activities:
                  - id: 68a2b1c09c41d20014b41a10
                    channel: email
                    status: replied
                    direction: null
                    campaignId: 68a201559c41d20014b40111
                    subject: 'Re: Quick question about Brightpay''s Q3 hiring'
                    body:
                      contentType: html
                      content: <p>Thanks Sam, happy to chat on Thursday.</p>
                    sentAt: null
                    receivedAt: '2026-08-21T14:02:11.000Z'
                    scheduledAt: null
                    from:
                      name: Ada Nwosu
                      address: ada@brightpay.com
                    to:
                      - name: Sam Rivera
                        address: sam@acme.com
                    linkedinUrl: null
                    phoneNumber: null
                    callTranscript: null
                    callRecordingUrl: null
                    callDisposition: null
                  - id: 68a2a0114773c751a92de55d
                    channel: non_campaign_call
                    status: answered
                    direction: outbound
                    campaignId: null
                    subject: null
                    body:
                      contentType: html
                      content: >-
                        - Asked for pricing on the 10-seat plan<br>- Sending the
                        deck, following up Thursday
                    sentAt: '2026-08-20T16:47:18.434Z'
                    receivedAt: null
                    scheduledAt: null
                    from: null
                    to: []
                    linkedinUrl: null
                    phoneNumber: '+14155552671'
                    callTranscript: >-
                      Ada: Hello? — Sam: Hi Ada, Sam from Acme, is now a bad
                      time?
                    callRecordingUrl: >-
                      https://fuse-call-recordings.s3.us-east-1.amazonaws.com/68a1f2c8/68a2a0114773c751a92de55d.wav?X-Amz-Expires=3600&X-Amz-Signature=8a3f0b7c9d2e4f1a6b5c8d7e9f0a1b2c
                    callDisposition: connected-positive
                  - id: OmgR3-p-X9mOYqVQgiQ4Hw
                    channel: linkedin_message
                    status: sent
                    direction: null
                    campaignId: 68a201559c41d20014b40111
                    subject: null
                    body:
                      contentType: text
                      content: >-
                        Hi Ada, loved your post on payroll automation. Open to a
                        quick chat next week?
                    sentAt: '2026-08-19T09:15:00.000Z'
                    receivedAt: null
                    scheduledAt: null
                    from: null
                    to: []
                    linkedinUrl: linkedin.com/in/ada-nwosu
                    phoneNumber: null
                    callTranscript: null
                    callRecordingUrl: null
                    callDisposition: null
                nextCursor: '3'
        '400':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - basicAuth: []
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            param:
              type:
                - string
                - 'null'
            doc_url:
              type:
                - string
                - 'null'
            request_id:
              type:
                - string
                - 'null'
          required:
            - code
            - message
      required:
        - error
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: >-
        Your API token (`af_…`) as the Basic-auth username, with an empty
        password.

````