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

# Get Sequence Metrics

> Report outreach performance over a date window.

Report outreach performance over a date window.

Counters cover the window, not the lifetime of a template, and are counts
rather than rates: leads found, sent, opened, clicked, replied, positive
replies, hot leads, bounced and unsubscribed, plus how the replies were
categorised. Bounced and unsubscribed counts come from replies categorised
as a bounce or an unsubscribe request. Templates are returned busiest first.
Omit `sequence_template_id` to cover the whole portfolio.

Requires the `sequences:read` scope on the API key.


## OpenAPI

````yaml GET /v1/sequence-templates/metrics
openapi: 3.1.0
info:
  title: Topo Public API
  description: >-
    Public REST API for Topo. All requests require a bearer API key issued from
    Settings → Developers. See the **Guides** in the left sidebar for
    authentication and rate-limit details.
  version: 1.0.0
servers:
  - url: https://api.topo.io
    description: Production
security:
  - BearerApiKey: []
tags:
  - name: Authentication
    description: >-
      Every request to the Topo Public API is authenticated with a bearer API
      key.


      ```http

      Authorization: Bearer topo_live_4f8a9c2b...

      ```


      Requests without a valid bearer token receive `401 Unauthorized`. After
      repeated failures with the same token, further attempts are
      short-circuited with `429 Too Many Requests` (`data.window_seconds: 60`)
      so a stale or malformed key cannot be retried in a tight loop.


      ### Issuing keys


      API keys are issued from the dashboard under **Settings → Developers → API
      keys**. Each key is bound to a single organization — the workspace it was
      created in — and cannot be used to read or write data from any other
      organization.


      The raw key is shown **once** at creation and never displayed again. If
      the raw key is lost, revoke it and issue a new one.


      ### Scopes


      Keys carry a granular scope list of `resource:action` pairs. A request to
      an endpoint whose required scope is not on the key returns `403
      Forbidden`.


      v1 ships with the following scopes:


      - `account_exclusions:read`, `account_exclusions:write`

      - `account_lists:read`, `account_lists:write`

      - `accounts:read`, `accounts:write`

      - `activities:read`

      - `contact_exclusions:read`, `contact_exclusions:write`

      - `contact_lists:read`, `contact_lists:write`

      - `contacts:read`, `contacts:write`

      - `crm:write`

      - `events:read`, `events:write`

      - `messages:read`

      - `sequences:read`, `sequences:write`

      - `signals:read`, `signals:write`

      - `tasks:read`, `tasks:write`

      - `users:read`

      - `webhooks:read`, `webhooks:write`


      Each endpoint's required scope is listed in its description.


      ### Inspecting the current key


      `GET /v1/me` returns the principal behind the bearer token: the key id,
      its name, the organization id and name, the id of the user who issued the
      key (`null` when it was not issued by a person), the scope list, the key
      prefix, the last-used timestamp, and the creation date. Use it to confirm
      a key is wired up correctly before debugging endpoint-level errors.
  - name: Rate limits
    description: >-
      Requests are rate-limited per organization across three concurrent
      windows. The budget is shared by every API key issued for the
      organization.


      | Window | Default limit |

      |---|---|

      | Per second | 10 requests |

      | Per minute | 60 requests |

      | Per day | 10,000 requests |


      A request is accepted only if it fits inside **all three** windows.
      Exceeding any one of them returns `429`.


      ### Response headers


      Every response carries the state of all three windows. Each window is
      suffixed with its name — `second`, `minute`, or `day`:


      ```http

      X-RateLimit-Limit-second: 5

      X-RateLimit-Remaining-second: 2

      X-RateLimit-Reset-second: 1729435920

      X-RateLimit-Limit-minute: 60

      X-RateLimit-Remaining-minute: 13

      X-RateLimit-Reset-minute: 1729435932

      X-RateLimit-Limit-day: 1000

      X-RateLimit-Remaining-day: 842

      X-RateLimit-Reset-day: 1729519200

      ```


      | Header | Meaning |

      |---|---|

      | `X-RateLimit-Limit-{window}` | Capacity of that window |

      | `X-RateLimit-Remaining-{window}` | Requests left in that window before
      the next `429` |

      | `X-RateLimit-Reset-{window}` | Unix timestamp (seconds) at which that
      window is fully refilled |


      Each window is a token bucket that refills continuously, so
      `X-RateLimit-Remaining-{window}` recovers gradually under steady traffic —
      it does not snap back at a fixed boundary.


      ### When the limit is exceeded


      Requests over the budget return `429` with the standard error envelope and
      a `Retry-After` header. `data.window_seconds` identifies the tier that
      tripped (`1`, `60`, or `86400`):


      ```http

      Retry-After: 3

      ```


      ```json

      {
        "status_code": 429,
        "type": "RateLimitIssue",
        "message": "Rate limit exceeded",
        "data": {
          "limit": 60,
          "reset_at": 1729435932,
          "window_seconds": 60
        },
        "request_id": "req_01HX7K..."
      }

      ```


      `Retry-After` is the number of seconds until the next request is allowed
      and is the recommended signal for backoff. `X-RateLimit-Reset` marks when
      the window is fully refilled, which is later than `Retry-After` whenever
      the bucket has more than one slot.
  - name: Task lifecycle
    description: >-
      A task represents one action a rep is expected to take — reply to a
      message, review a new lead, make a call, or complete a standalone to-do.
      This guide covers the states a task moves through, and how the wording
      used in the Topo app maps onto the values returned by this API.


      ### Statuses


      | `status` | Meaning |

      |---|---|

      | `PENDING` | Waiting for the rep. This is where a task starts. |

      | `IN_PROGRESS` | A call task the rep has started but not yet logged. |

      | `COMPLETED` | The rep acted on the task — a reply was sent, a lead
      approved or refused, a call logged. |

      | `SKIPPED` | The rep dismissed the task without acting on it. Shown as
      **Archived** in the app. |


      `PENDING` and `IN_PROGRESS` are the actionable states. `COMPLETED` and
      `SKIPPED` are terminal, but both can be reversed with `POST
      /v1/tasks/{task_id}/reopen`.


      ### App wording vs. API wording


      The Topo app calls the dismiss action **Archive**. On this API the same
      operation is called *skip*. They are the same thing — only the label
      differs:


      | In the Topo app | On this API |

      |---|---|

      | The **Archive** button | `POST /v1/tasks/{task_id}/skip` |

      | The **Archived** badge | `status: "SKIPPED"` |

      | "Archived 2 hours ago" | `skipped_at` |

      | — | webhook event `task.skipped` |


      These names are part of the frozen `/v1` contract and will not change
      within this major version. If you are mapping API data back to what a user
      sees in the app, treat `SKIPPED` and `skipped_at` as "archived".


      ### Ending a task


      | Action | Endpoint | Result |

      |---|---|---|

      | Act on it | `POST /v1/tasks/{task_id}/execute` | `COMPLETED` +
      `completed_at`, and the task's own side effects (message sent, lead
      enrolled or refused, call logged) |

      | Mark done without acting | `POST /v1/tasks/{task_id}/complete` |
      `COMPLETED` + `completed_at` |

      | Dismiss it (archive) | `POST /v1/tasks/{task_id}/skip` | `SKIPPED` +
      `skipped_at` |


      `execute` is the only one of the three that changes anything beyond the
      task itself. `complete` and `skip` record an outcome and nothing more.


      Both terminal states emit a webhook if you are subscribed:
      `task.completed` and `task.skipped` respectively.


      ### Reopening


      `POST /v1/tasks/{task_id}/reopen` returns a `COMPLETED` or `SKIPPED` task
      to `PENDING`. It clears `completed_at` and `skipped_at`, and sets
      `reopened_at`. A task that is already actionable cannot be reopened.


      `reopen_reason` distinguishes an automatic reopen from a manual one.
      `REMINDER_RULE` means Topo brought the task back on its own because a sent
      message went unanswered; `null` means a person reopened it.


      ### Snoozing


      Deferring a task ("Snooze") does **not** change its status. The task stays
      `PENDING` and drops out of the active queue until the chosen time passes,
      then reappears on its own.


      Use `POST /v1/tasks/{task_id}/snooze` with `{ "snoozed_until": "<ISO-8601
      timestamp>" }` to defer a task. The `snoozed_until` timestamp is also
      returned on task objects in `GET /v1/tasks` and `GET /v1/tasks/{task_id}`.
  - name: me
    description: >-
      Identity of the API key in use: the workspace it belongs to and its
      scopes.
  - name: search
    description: >-
      Find records by name across kinds and load any match back. A search result
      carries a typed id (`<type>:<uuid>`) that `GET /v1/fetch` resolves into
      the full record, so a name is enough to reach a lead, an account, a
      sequence template or a task without knowing which endpoint owns it.
  - name: users
    description: List users in the authenticated organization.
  - name: contacts
    description: Manage contact lists, list entries, and contact-level exclusions.
  - name: accounts
    description: Manage account lists, list entries, and account-level exclusions.
  - name: sequences
    description: Manage outbound sequences and inspect their execution state.
  - name: sequence-templates
    description: Manage reusable sequence templates that seed new sequences.
  - name: activities
    description: >-
      Read the immutable event log produced by outbound sequences (sent, opened,
      replied, meeting booked, etc.).
  - name: events
    description: >-
      Ingest first-party events (product usage, website activity, form
      submissions) and read them back to verify ingestion and resolution. Every
      well-formed event is accepted (HTTP 202) and stored. Subject correlation
      to contacts and accounts is asynchronous and best-effort. Replays with the
      same `external_event_id` or identical event content are deduplicated.
  - name: signals
    description: >-
      Create and run buying signals: a signal watches one catalog preset
      (hiring, funding, technology adoption, news, LinkedIn activity, or your
      own first-party events), checks it daily, and imports the qualified people
      or companies into a destination list it creates. Read the imports feed to
      see what each signal brought in.
  - name: webhooks
    description: Manage webhook subscriptions to receive outbound event notifications.
  - name: tasks
    description: List and inspect tasks in the workspace.
  - name: messages
    description: Read email and LinkedIn messages exchanged in outreach sequences.
paths:
  /v1/sequence-templates/metrics:
    get:
      tags:
        - sequence-templates
      summary: Get Sequence Metrics
      description: >-
        Report outreach performance over a date window.


        Counters cover the window, not the lifetime of a template, and are
        counts

        rather than rates: leads found, sent, opened, clicked, replied, positive

        replies and hot leads, plus how the replies were categorised. Templates
        are

        returned busiest first. Omit `sequence_template_id` to cover the whole

        portfolio.


        Requires the `sequences:read` scope on the API key.
      operationId: get_sequence_metrics_v1_sequence_templates_metrics_get
      parameters:
        - name: sequence_template_id
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: uuid
              - type: 'null'
            description: >-
              Report on one template. Omit to cover every template in the
              workspace.
            title: Sequence Template Id
          description: >-
            Report on one template. Omit to cover every template in the
            workspace.
        - name: days
          in: query
          required: false
          schema:
            type: integer
            maximum: 365
            minimum: 1
            description: >-
              Lookback window in days, used when start_date and end_date are
              omitted.
            default: 30
            title: Days
          description: >-
            Lookback window in days, used when start_date and end_date are
            omitted.
        - name: start_date
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: date
              - type: 'null'
            description: Inclusive start of the reporting window.
            title: Start Date
          description: Inclusive start of the reporting window.
        - name: end_date
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: date
              - type: 'null'
            description: Inclusive end of the window. Defaults to today.
            title: End Date
          description: Inclusive end of the window. Defaults to today.
        - name: channel
          in: query
          required: false
          schema:
            anyOf:
              - $ref: '#/components/schemas/SequenceMetricChannel'
              - type: 'null'
            description: Restrict counters to one channel. Defaults to all channels.
            title: Channel
          description: Restrict counters to one channel. Defaults to all channels.
        - name: include_inactive
          in: query
          required: false
          schema:
            type: boolean
            description: Include templates that are no longer active.
            default: false
            title: Include Inactive
          description: Include templates that are no longer active.
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SequenceMetricsPublicOutput'
components:
  schemas:
    SequenceMetricChannel:
      type: string
      enum:
        - EMAIL
        - LINKEDIN
        - ALL
        - MANUAL
      title: SequenceMetricChannel
    SequenceMetricsPublicOutput:
      properties:
        start_date:
          type: string
          format: date
          title: Start Date
          description: Inclusive first day of the reporting window.
        end_date:
          type: string
          format: date
          title: End Date
          description: Inclusive last day of the reporting window.
        channel:
          $ref: '#/components/schemas/SequenceMetricChannel'
          description: Channel the counters cover.
        sequences:
          items:
            $ref: '#/components/schemas/SequenceTemplateMetricsPublicOutput'
          type: array
          title: Sequences
          description: Per-template counters, busiest first.
        reply_categories:
          items:
            $ref: '#/components/schemas/ReplyCategoryMetricsPublicOutput'
          type: array
          title: Reply Categories
          description: Reply breakdown across the templates reported on.
      type: object
      required:
        - start_date
        - end_date
        - channel
        - sequences
        - reply_categories
      title: SequenceMetricsPublicOutput
    SequenceTemplateMetricsPublicOutput:
      properties:
        sequence_template_id:
          type: string
          format: uuid
          title: Sequence Template Id
          description: Template these counters belong to.
        name:
          anyOf:
            - type: string
            - type: 'null'
          title: Name
          description: Name of the template.
        status:
          $ref: '#/components/schemas/SequenceTemplateStatus'
          description: Lifecycle state.
        metrics:
          $ref: '#/components/schemas/SequenceMetricsCountersPublicOutput'
          description: Counters for the reporting window.
      type: object
      required:
        - sequence_template_id
        - name
        - status
        - metrics
      title: SequenceTemplateMetricsPublicOutput
    ReplyCategoryMetricsPublicOutput:
      properties:
        reply_category:
          $ref: '#/components/schemas/MessageReplyCategory'
          description: Category the replies were classified into.
        unique_replies:
          type: integer
          title: Unique Replies
          description: Leads whose reply fell in this category.
        total_replies:
          type: integer
          title: Total Replies
          description: Replies in this category.
      type: object
      required:
        - reply_category
        - unique_replies
        - total_replies
      title: ReplyCategoryMetricsPublicOutput
    SequenceTemplateStatus:
      type: string
      enum:
        - PENDING_SETUP
        - ACTIVE
        - INACTIVE
        - FINISHING
        - ARCHIVED
      title: SequenceTemplateStatus
    SequenceMetricsCountersPublicOutput:
      properties:
        unique_found:
          type: integer
          title: Unique Found
          description: Leads found in the window.
        unique_sent:
          type: integer
          title: Unique Sent
          description: Leads sent at least one message.
        total_sent:
          type: integer
          title: Total Sent
          description: Messages sent.
        unique_opens:
          type: integer
          title: Unique Opens
          description: Leads who opened at least once.
        total_opens:
          type: integer
          title: Total Opens
          description: Opens recorded.
        unique_clicks:
          type: integer
          title: Unique Clicks
          description: Leads who clicked at least once.
        total_clicks:
          type: integer
          title: Total Clicks
          description: Clicks recorded.
        unique_replies:
          type: integer
          title: Unique Replies
          description: Leads who replied at least once.
        total_replies:
          type: integer
          title: Total Replies
          description: Replies received.
        unique_positive_replies:
          type: integer
          title: Unique Positive Replies
          description: Leads who replied positively at least once.
        total_positive_replies:
          type: integer
          title: Total Positive Replies
          description: Positive replies received.
        unique_hot_leads:
          type: integer
          title: Unique Hot Leads
          description: Leads that turned hot.
        total_hot_leads:
          type: integer
          title: Total Hot Leads
          description: Hot-lead events recorded.
        unique_bounced:
          type: integer
          title: Unique Bounced
          description: Leads whose reply was categorized as a bounce.
        total_bounced:
          type: integer
          title: Total Bounced
          description: Replies categorized as a bounce.
        unique_unsubscribed:
          type: integer
          title: Unique Unsubscribed
          description: Leads whose reply was categorized as an unsubscribe request.
        total_unsubscribed:
          type: integer
          title: Total Unsubscribed
          description: Replies categorized as an unsubscribe request.
      type: object
      required:
        - unique_found
        - unique_sent
        - total_sent
        - unique_opens
        - total_opens
        - unique_clicks
        - total_clicks
        - unique_replies
        - total_replies
        - unique_positive_replies
        - total_positive_replies
        - unique_hot_leads
        - total_hot_leads
        - unique_bounced
        - total_bounced
        - unique_unsubscribed
        - total_unsubscribed
      title: SequenceMetricsCountersPublicOutput
    MessageReplyCategory:
      type: string
      enum:
        - MEETING
        - INTERESTED
        - BAD_TIMING
        - REFERRAL
        - WRONG_PERSON
        - LEFT_COMPANY
        - OUT_OF_OFFICE
        - SPAM_FILTER
        - UNKNOWN
        - NOT_INTERESTED
        - UNSUBSCRIBED
        - BOUNCED
      title: MessageReplyCategory
  securitySchemes:
    BearerApiKey:
      type: http
      scheme: bearer
      bearerFormat: topo_live_<64hex>
      description: Bearer API key issued from Settings → Developers.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.