> ## 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.

# List Signal Presets

> List the presets a signal can be created from.

Each preset names the detection filters `POST /v1/signals` accepts and
which of them are mandatory. Presets not yet available for creation are
omitted.

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



## OpenAPI

````yaml /openapi.json get /v1/signals/presets
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/signals/presets:
    get:
      tags:
        - signals
      summary: List Signal Presets
      description: |-
        List the presets a signal can be created from.

        Each preset names the detection filters `POST /v1/signals` accepts and
        which of them are mandatory. Presets not yet available for creation are
        omitted.

        Requires the `signals:read` scope on the API key.
      operationId: list_signal_presets_v1_signals_presets_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                items:
                  $ref: '#/components/schemas/SignalPresetPublicOutput'
                type: array
                title: Response List Signal Presets V1 Signals Presets Get
components:
  schemas:
    SignalPresetPublicOutput:
      properties:
        signal_type:
          $ref: '#/components/schemas/SignalType'
          description: Pass this as `signal_type` to create a signal from the preset.
        title:
          type: string
          title: Title
          description: Display name of the preset.
        description:
          type: string
          title: Description
          description: What the preset detects.
        category_label:
          type: string
          title: Category Label
          description: Catalog category the preset belongs to.
        scope:
          $ref: '#/components/schemas/SignalScope'
          description: >-
            What the preset's provider detects: COMPANY facts or PEOPLE. A
            COMPANY preset can still import the people behind its detected
            companies through `import_target`.
        scope_selectable_at_creation:
          type: boolean
          title: Scope Selectable At Creation
          description: >-
            Whether `import_target` may pick either entity, instead of being
            fixed by the scope.
        filter_keys:
          items:
            $ref: '#/components/schemas/FilterFieldKey'
          type: array
          title: Filter Keys
          description: Every detection filter the preset accepts.
        required_filter_keys:
          items:
            $ref: '#/components/schemas/FilterFieldKey'
          type: array
          title: Required Filter Keys
          description: The detection filters the preset refuses to go without.
        requires_event_subject:
          type: boolean
          title: Requires Event Subject
          description: >-
            Whether creation must declare `event_subject`, which only a
            custom-event preset does.
        preview_supported:
          type: boolean
          title: Preview Supported
          description: >-
            Whether `POST /v1/signals/preview` can sample the preset before a
            signal is created.
        backfill_windows_days:
          anyOf:
            - items:
                type: integer
              type: array
            - type: 'null'
          title: Backfill Windows Days
          description: >-
            Null when the preset cannot import past matches at creation.
            Otherwise the windows `backfill.window_days` must pick from — empty
            when it takes no window.
      type: object
      required:
        - signal_type
        - title
        - description
        - category_label
        - scope
        - scope_selectable_at_creation
        - filter_keys
        - required_filter_keys
        - requires_event_subject
        - preview_supported
        - backfill_windows_days
      title: SignalPresetPublicOutput
    SignalType:
      type: string
      enum:
        - LINKEDIN_OWN_POST_ENGAGEMENT
        - LINKEDIN_COMPETITOR_POST_ENGAGEMENT
        - LINKEDIN_PERSON_POST_ENGAGEMENT
        - LINKEDIN_KEYWORD_MENTION
        - LINKEDIN_OWN_COMPANY_FOLLOWERS
        - LINKEDIN_COMPETITOR_FOLLOWERS
        - LINKEDIN_COMPANY_PAGE_FOLLOWERS
        - HIRING_SIGNALS
        - JOB_DESCRIPTION_KEYWORD
        - FUNDING_EVENTS
        - TECH_ADOPTION
        - NEWS_EVENTS
        - NEW_JOB
        - CUSTOM_EVENT
        - LINKEDIN_PARTNER_FOLLOWERS
        - LINKEDIN_CUSTOMER_FOLLOWERS
        - LINKEDIN_PARTNER_POST_ENGAGEMENT
        - LINKEDIN_CUSTOMER_POST_ENGAGEMENT
        - LINKEDIN_COMPANY_PAGE_POST_ENGAGEMENT
        - LINKEDIN_OWN_PROFILE_POST_ENGAGEMENT
        - LINKEDIN_OWN_EMPLOYEES_POST_ENGAGEMENT
        - LINKEDIN_COMPETITOR_EMPLOYEES_POST_ENGAGEMENT
        - LINKEDIN_PARTNER_EMPLOYEES_POST_ENGAGEMENT
        - LINKEDIN_CUSTOMER_EMPLOYEES_POST_ENGAGEMENT
        - LINKEDIN_OWN_BRAND_MENTION
        - LINKEDIN_COMPETITOR_MENTION
        - LINKEDIN_PARTNER_MENTION
        - LINKEDIN_CUSTOMER_MENTION
        - LINKEDIN_EVENT_MENTION
        - COMPETITOR_TECH_ADOPTION
        - INTEGRATION_TECH_ADOPTION
        - LINKEDIN_EVENT_PAGE_FOLLOWERS
        - CHAMPION_CHANGED_JOB
        - CRM_LIST_ENTRY
      title: SignalType
    SignalScope:
      type: string
      enum:
        - PEOPLE
        - COMPANY
      title: SignalScope
    FilterFieldKey:
      type: string
      enum:
        - job_titles
        - locations
        - employee_count_ranges
        - keywords
        - employer_names
        - exact_employer_names
        - exclude_job_titles
        - all_titles
        - names
        - exclude_names
        - skills
        - exclude_skills
        - languages
        - schools
        - degrees
        - field_of_study
        - exclude_locations
        - geographies
        - exclude_keywords
        - exclude_employer_names
        - employer_domains
        - exclude_employer_domains
        - past_employer_names
        - company_types
        - hq_countries
        - hq_states
        - largest_headcount_countries
        - markets
        - acquisition_status
        - linkedin_connections_min
        - linkedin_connections_max
        - linkedin_followers_min
        - linkedin_followers_max
        - company_revenue_min
        - company_revenue_max
        - year_founded_min
        - year_founded_max
        - open_to_work
        - is_freelance
        - is_public_company
        - employee_start_date_after
        - role_started_max_months_ago
        - role_started_min_months_ago
        - competitor_domains
        - query
        - company_technology_slug_or
        - company_technology_slug_and
        - company_technology_slug_not
        - tech_min_confidence
        - funding_stage_or
        - industry_or
        - industry_not
        - company_country_code_or
        - company_country_code_not
        - company_name_or
        - company_name_not
        - company_name_partial_match_or
        - company_domain_or
        - company_domain_not
        - company_description_pattern_or
        - min_employee_count
        - max_employee_count
        - company_size
        - min_funding_usd
        - max_funding_usd
        - last_funding_round_after
        - last_funding_round_before
        - funding_raised_max_age_days
        - only_yc_companies
        - company_type
        - job_title_or
        - job_title_not
        - job_description_contains_or
        - job_location_pattern_or
        - posted_at_max_age_days
        - tech_first_detected_after
        - tech_first_detected_before
        - tech_last_detected_before
        - tech_last_detected_after
        - tech_first_detected_max_age_days
        - min_matching_jobs
        - seniority
        - job_functions
        - departments
        - exclude_seniority
        - exclude_job_functions
        - exclude_hq_countries
        - past_job_titles
        - posted_on_linkedin
        - years_of_experience
        - follows_your_company
        - exact_job_titles
        - exclude_exact_job_titles
        - years_of_experience_min
        - years_of_experience_max
        - has_profile_picture
        - naics_codes
        - monthly_visitors_min
        - monthly_visitors_max
        - past_employer_titles
        - company_keywords
        - exclude_company_keywords
        - headcount_range_sales
        - headcount_range_engineering
        - headcount_range_marketing
        - headcount_range_operations
        - headcount_range_finance
        - headcount_range_human_resources
        - headcount_range_support
        - headcount_range_information_technology
        - headcount_range_business_development
        - headcount_growth_6m_min
        - headcount_growth_6m_max
        - headcount_growth_12m_min
        - headcount_growth_12m_max
        - followers_growth_6m_min
        - followers_growth_6m_max
        - followers_growth_12m_min
        - followers_growth_12m_max
        - web_traffic_growth_6m_min
        - web_traffic_growth_6m_max
        - web_traffic_growth_12m_min
        - web_traffic_growth_12m_max
        - job_openings_growth_6m_min
        - job_openings_growth_6m_max
        - job_openings_growth_12m_min
        - job_openings_growth_12m_max
        - contact_list_ids
        - account_list_ids
        - first_party_event_name
        - news_query_or
        - news_category_or
        - news_published_max_age_days
        - linkedin_company_url_or
        - linkedin_person_url_or
        - linkedin_post_max_age_days
        - linkedin_watched_engagement
        - linkedin_keyword_or
        - linkedin_followed_company_url_or
      title: FilterFieldKey
  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.