---
title: "Add one covered product to the bound account's watchlist."
method: POST
path: "/api/v1/watch"
tags: ["watch"]
---

# Add one covered product to the bound account's watchlist.

`POST /api/v1/watch`

## Request

- Base URL: `https://formulasignal.com`
- URL: `https://formulasignal.com/api/v1/watch`
- Auth: HTTP bearer

Add one covered product to the bound account's watchlist.

**When to use.** Use when a person asks to start watching a product. Resolve the product first if you were given a name rather than an id.

**What it cannot provide.** It cannot add a product outside the covered set, exceed the account's watch limit, or act on an account this key is not bound to. It refuses a covered product FormulaSignal cannot monitor yet and says why in the refusal. It does not start a subscription and refuses when the account is not entitled.

Requires the `watch:manage` scope.
Each distinct product named in a successful answer spends one unit of the key's daily product budget. Asking twice about the same one costs once.

## Headers

- `X-FormulaSignal-Origin` 'api' | 'mcp'

## Request body

- object
  - `product_id` string, required

## Response `200`

A FormulaSignal answer. `status` says what kind of answer it is, and every value except `supported` is still a real answer about the Record rather than a fact about the product.

- Envelope
  - `request_id` string, required
  - `capability` string, required
  - `status` 'supported' | 'partial' | 'stale' | 'under_review' | 'ambiguous' | 'unsupported' | 'refused', required: What kind of answer this is. Every value except `supported` is still a real answer about the Record rather than a fact about the product.
  - `product` ProductIdentity
    - `product_id` string, required
    - `brand` string, required
    - `name` string, required
    - `variant` string, nullable, required: The observed flavor. Flavor is a version dimension, not a footnote.
  - `products` ProductIdentity[]
    - `product_id` string, required
    - `brand` string, required
    - `name` string, required
    - `variant` string, nullable, required: The observed flavor. Flavor is a version dimension, not a footnote.
  - `candidates` ProductIdentity[]: Present when `status` is `ambiguous`. Pick one; never assume the first.
    - `product_id` string, required
    - `brand` string, required
    - `name` string, required
    - `variant` string, nullable, required: The observed flavor. Flavor is a version dimension, not a footnote.
  - `summary` string, required: One sentence saying what kind of answer this is.
  - `history` HistoryState[]
    - `observed_at` string, date, nullable
    - `role` 'CURRENT' | 'CHANGE_BEFORE' | 'CHANGE_AFTER' | 'RICHEST_PRIOR_PANEL'
    - `classes` string[]
    - `declared_components` integer, nullable
    - `declared_with_amounts` integer, nullable
    - `flavor` string, nullable
    - `source` SourceReference
      - `source_id` string, required: Derived and opaque. Stable for a given URL and observation date.
      - `title` string, required
      - `url` string, uri, nullable, required
      - `observed_at` string, date, nullable, required: When FormulaSignal read the source. Not a manufacture date.
      - `source_type` 'first_party_current' | 'first_party_archived' | 'regulatory_filing' | 'retailer_listing' | 'secondary_coverage' | 'distributor_listing' | 'authoritative_reference' | 'peer_reviewed_reference' | 'interested_party_reference' | 'secondary_reference' | 'other', required
      - `evidence_class` string, nullable: Only P1, P2 and R1 support a CONFIRMED product-state label.
  - `signals` object[]
  - `comparison` object
  - `coverage` object
  - `ledger` object
  - `watch` object
  - `next_cursor` string, nullable
  - `verified_facts` VerifiedFact[], required: What a captured source literally declares. A declared fact.
    - `field` string, required
    - `value` FactValue
      - `declared_name` string: Exactly as printed or published by the brand.
      - `normalized_ingredient` string
      - `amount` number, nullable: Null means the source named the ingredient without disclosing an amount. It never means zero.
      - `unit` string, nullable
    - `before` FactValue
      - `declared_name` string: Exactly as printed or published by the brand.
      - `normalized_ingredient` string
      - `amount` number, nullable: Null means the source named the ingredient without disclosing an amount. It never means zero.
      - `unit` string, nullable
    - `after` FactValue
      - `declared_name` string: Exactly as printed or published by the brand.
      - `normalized_ingredient` string
      - `amount` number, nullable: Null means the source named the ingredient without disclosing an amount. It never means zero.
      - `unit` string, nullable
    - `confirmed` boolean
  - `commercial_facts` CommercialFact[], required: Dated commercial observations, each with its price basis. An observation.
    - `field` string, required: `list_price` only where `price_basis` is LIST. Otherwise `observed_price`.
    - `value` union, required
      - number
      - string
    - `unit` string, nullable, required
    - `price_basis` string, nullable: LIST, UNKNOWN, UNRECORDED, or the two recorded bases on a change row. Never inferred from the number.
    - `observed_at` string, date, nullable, required
    - `seller` string, nullable
  - `calculations` Calculation[], required: Deterministic arithmetic FormulaSignal performed, with the operands to redo it. Never a manufacturer figure.
    - `field` string, required
    - `value` number, nullable, required
    - `unit` string, nullable, required
    - `method` string, required: The arithmetic in words, so a reader can redo it.
    - `operands` object[], required
      - `label` string
      - `value` union
        - number
        - string
  - `research_context` ResearchContext[], required
    - `normalized_ingredient` string, required
    - `ingredient_form` string, nullable
    - `declared_amount_mg` number, nullable
    - `selected_low_mg` number, nullable
    - `selected_high_mg` number, nullable: Null on both bounds means FormulaSignal found no studied range. That is a finding, not a gap.
    - `dose_basis` string, nullable
    - `evidence_type` 'A1' | 'A2' | 'A3' | 'A4', nullable: A1 government or institutional, A2 peer-reviewed, A3 trademark holder, A4 other secondary.
    - `citation` string, nullable
    - `citation_url` string, uri, nullable
    - `comparison` 'INSIDE' | 'BELOW' | 'ABOVE' | 'NO_RANGE' | 'NOT_DECLARED' | 'NO_PRODUCT_CONTEXT', required
    - `comparison_statement` string, required
    - `limitations` string[], required
  - `regulatory_records` RegulatoryRecord[], required
    - `normalized_ingredient` string, required
    - `record_class` 'REGULATORY_RECORD' | 'LABEL_WARNING' | 'SAFETY_ADVISORY' | 'INTERACTION' | 'FDA_ACTION', required: REGULATORY_RECORD means a filing exists and says nothing about safety on its own. It appears in `regulatory_records`; the other four appear in `documented_cautions`. The two never share a heading.
    - `statement` string, required
    - `evidence_type` 'A1' | 'A2' | 'A3' | 'A4', required
    - `citation` string, required
    - `citation_url` string, uri, required
    - `accessed_at` string, date, required
  - `documented_cautions` RegulatoryRecord[], required
    - `normalized_ingredient` string, required
    - `record_class` 'REGULATORY_RECORD' | 'LABEL_WARNING' | 'SAFETY_ADVISORY' | 'INTERACTION' | 'FDA_ACTION', required: REGULATORY_RECORD means a filing exists and says nothing about safety on its own. It appears in `regulatory_records`; the other four appear in `documented_cautions`. The two never share a heading.
    - `statement` string, required
    - `evidence_type` 'A1' | 'A2' | 'A3' | 'A4', required
    - `citation` string, required
    - `citation_url` string, uri, required
    - `accessed_at` string, date, required
  - `limitations` string[], required: Always present, including when empty. Read it.
  - `source_references` SourceReference[], required
    - `source_id` string, required: Derived and opaque. Stable for a given URL and observation date.
    - `title` string, required
    - `url` string, uri, nullable, required
    - `observed_at` string, date, nullable, required: When FormulaSignal read the source. Not a manufacture date.
    - `source_type` 'first_party_current' | 'first_party_archived' | 'regulatory_filing' | 'retailer_listing' | 'secondary_coverage' | 'distributor_listing' | 'authoritative_reference' | 'peer_reviewed_reference' | 'interested_party_reference' | 'secondary_reference' | 'other', required
    - `evidence_class` string, nullable: Only P1, P2 and R1 support a CONFIRMED product-state label.
  - `confidence` Confidence, required
    - `level` 'high' | 'moderate' | 'low' | 'none', required: Evidence quality. Never how certain the writing sounds, and never "certain".
    - `explanation` string, required
  - `record_version` string, required: The Record data-state id. Two answers sharing it came from one committed state.
  - `record_as_of` string, date, required
  - `record_timestamp` string, date-time, required: The newest dated observation the Record holds. Deliberately not "now".
  - `methodology_version` string, required
  - `disclaimer` string, required

## Other responses

- `400`: A refusal, in the same envelope shape.
- `401`: A refusal, in the same envelope shape.
- `403`: A refusal, in the same envelope shape.
- `404`: A refusal, in the same envelope shape.
- `405`: A refusal, in the same envelope shape.
- `413`: A refusal, in the same envelope shape.
- `429`: A refusal, in the same envelope shape.
- `500`: A refusal, in the same envelope shape.

---

[API](https://skmtc.dev/formulasignal/apis/formulasignal-intelligence-api.md) · [All operations](https://skmtc.dev/formulasignal/apis/formulasignal-intelligence-api/llms.txt) · [OpenAPI document](https://skmtc.dev/formulasignal/apis/formulasignal-intelligence-api/revisions/61a8d9ac8b67?raw)
