---
title: "Update the configuration of a tracker"
method: PATCH
path: "/trackers/{id}"
tags: ["Trackers"]
---

# Update the configuration of a tracker

`PATCH /trackers/{id}`

## Request

- Base URL: `https://api.epovest.com/v1`
- URL: `https://api.epovest.com/v1/trackers/{id}`
- Auth: HTTP bearer

Takes the same fields as the creation, all optional: only the fields you send change, and a
sent list replaces the previous one entirely. Keywords, analysts and the title apply in
place. Changing the prompts, engines, frequency or resolution of a version that HAS measured
creates a new version: the score series continues across versions, and the response carries
the new tracker with its new id, next to `version_created`. A version that has not measured
yet is amended in place and keeps its id, so `version_created` is `false`.

A paused tracker takes all of it, the collection settings included. The call writes the
configuration and nothing else: no survey runs, no credit is reserved, the tracker stays
paused with its `pause_reason`, and what you set takes effect at the next
`POST /trackers/{id}/start`. A version created this way is born paused as well. Manager or
above.

## Request body

- TrackerUpdate: Every field of the creation, all optional; a sent list replaces the previous one entirely.
  - `title` string, required: Display name.
  - `prompts` string[], required: The questions asked to the engines at every survey, phrased as a customer would ask them.
  - `engines` Engine[], required
  - `frequency` 'monthly' | 'weekly' | 'daily' | 'on_demand', required: The pace of the surveys. `on_demand` puts the tracker on no schedule: starting it runs one survey, and every survey after that comes from `POST /trackers/{id}/survey`.
  - `resolution` 'hd' | 'full_hd' | '4k' | '8k', required: Repetitions of every question per engine and survey: `hd`=1, `full_hd`=3, `4k`=6, `8k`=9.
  - `keywords` union[]: Names to detect in the answers, as `"Name"` or `{"keyword": "Name", "favorite": true}`.
    - union
      - string
      - Keyword
        - `keyword` string, required
        - `favorite` boolean, required
  - `analysts` AnalystType[]
  - `custom_prompt` string: The instruction of the `custom_prompt` analyst; it comes with it.
  - `discovery` boolean: Suggests new keywords spotted in the answers. It works from keywords, so send `keywords[]` alongside, and check `discovery` in the answer.
  - `notify_on_survey` boolean
  - `next_survey_at` string: When the first survey runs, ISO 8601 with a date AND a time (`2026-08-01T09:00`), strictly in the future, read as UTC without an offset. Omitted, the first survey runs at start. Sent on a PAUSED tracker it is kept and read back like anywhere else, and it is what makes the next start wait instead of surveying right away. It goes with a frequency that has a pace: sent alongside `on_demand` it answers `422`, and `POST /trackers/{id}/survey` is the move it was reaching for.
  - `project_id` string: The UUID of a project of the account, or `default` for none. Omitted, the tracker files under Default.

## Response `200`

The tracker as it now stands, and whether a version was created.

- object
  - `tracker` Tracker, required
    - `id` string, uuid, required
    - `title` string, required
    - `project` ProjectRef, nullable, required: The project a tracker is filed under, null for the virtual `Default` project.
      - `id` string, uuid
      - `name` string
    - `chain` string, required: The name of the chain the versions of this tracker share.
    - `version` integer, required
    - `status` 'draft' | 'active' | 'paused' | 'retired' | 'abandoned', required
    - `engines` Engine[], required
    - `frequency` 'monthly' | 'weekly' | 'daily' | 'on_demand', required: The pace of the surveys. `on_demand` puts the tracker on no schedule: starting it runs one survey, and every survey after that comes from `POST /trackers/{id}/survey`.
    - `resolution` 'hd' | 'full_hd' | '4k' | '8k', required: Repetitions of every question per engine and survey: `hd`=1, `full_hd`=3, `4k`=6, `8k`=9.
    - `repetitions` integer, required: Repetitions of every question per engine and survey, as the resolution sets them.
    - `prompts` string[], required: The questions asked to the engines at every survey.
    - `keywords` Keyword[], required
      - `keyword` string, required
      - `favorite` boolean, required
    - `analysts` AnalystType[], required
    - `custom_prompt` string, nullable, required
    - `discovery` boolean, required: Suggests new keywords spotted in the answers. It works from the keywords of the tracker, so read it back here rather than assuming it took.
    - `notify_on_survey` boolean, required: Emails the account owner and managers each time a survey closes with fresh data. On by default.
    - `cost_per_survey_minor` integer, required: Recalculated from the configuration on every read, in minor units of `currency`.
    - `monthly_estimate_minor` integer, required: What a month at this configuration consumes. `0` on an `on_demand` tracker, which is the true figure: nothing runs on a pace, and `cost_per_survey_minor` is what one reading costs.
    - `currency` string, required: The wallet currency of the account.
    - `created_at` string, date-time, required
    - `activated_at` string, date-time, nullable, required
    - `next_survey_at` string, date-time, nullable, required: When the next survey runs. A past instant means within the hour; null when there is no date to give, which is a tracker whose measurement is stopped and which carries no chosen date, one whose first survey runs at start, a retired version, or an `on_demand` tracker, whose next survey is a call rather than a date. A PAUSED tracker with a date set for later carries it: that is when the measurement comes back once it is started.
    - `pause_reason` 'manual' | 'credit_exhausted' | 'null', nullable, required: `manual`: the measurement was stopped on purpose, and it waits for `POST /trackers/{id}/start`. `credit_exhausted`: the balance no longer covered a survey when it was due, and a top-up resumes the tracker on its own. Null on any status other than paused.
    - `archived` boolean, required: The FOLDER, next to the measurement rather than inside it: a filed tracker keeps its status, and `GET /trackers` lists the ones still followed first.
    - `archived_at` string, date-time, nullable, required
  - `version_created` boolean, required: True when the edit recorded a new tracker version, which carries a new id.

## Other responses

- `401`: `unauthenticated`: missing, unknown or revoked key.
- `403`: `insufficient_scope`: the credential may not do this, either because the key lacks the scope, or, on a one-click connection, because the person lacks the role the action needs (manager, or owner to start, pause and top up). On that path, read it as "this person may not do this" and tell them which role the action needs.
- `404`: `not_found`: unknown for this account.
- `409`: `not_editable`: a retired version is revision history and takes nothing.
- `422`: `validation_failed`: invalid tracker configuration; `violations[]` lists field and message.
- `429`: `rate_limited`: 120 requests per minute per credential, sliding window. Retry after `Retry-After` seconds.

---

[API](https://skmtc.dev/epovest/apis/epovest-api.md) · [All operations](https://skmtc.dev/epovest/apis/epovest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/epovest/apis/epovest-api/revisions/7a78ee27ecbb?raw)
