> For the complete documentation index, see [llms.txt](https://docs.heron-intelligence.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.heron-intelligence.com/api-reference/api-reference/evasion.md).

# Evasion

Did management answer the question? The Evasion dataset scores every question asked in a public company's earnings call as answered or evaded, and gives you the reasoning behind each verdict.

Three resources: the analysis of a call, the evasive exchanges inside it, and the topic vocabulary they are written in.

{% hint style="warning" %}
**An evasion verdict is a language model's judgement, not an observation.** Every analysis and every exchange in this dataset is model output: a model read the question and the answer and formed a view. It is not a measurement, and it is not a statement of fact about a named executive. Attribute it accordingly wherever you surface it. See [Provenance](#provenance).
{% endhint %}

{% hint style="info" %}
**A call without a verdict is absent, not zero.** Not every call carries one. A call that does not never appears in `GET /evasion/analyses` — it is not returned with nulls or zeros standing in for a result. An empty page means "no analysed calls", never "management answered everything".
{% endhint %}

## Resources

| Endpoint                                               | Returns                                                 |
| ------------------------------------------------------ | ------------------------------------------------------- |
| `GET /api/v1/evasion/analyses`                         | Analysed calls. Newest version of each call by default. |
| `GET /api/v1/evasion/analyses/{analysis_id}`           | One analysis version.                                   |
| `GET /api/v1/evasion/analyses/{analysis_id}/exchanges` | The **evasive** question-answer pairs of one analysis.  |
| `GET /api/v1/evasion/topics`                           | The controlled vocabulary — a fixed, predefined list.   |

All four require the Evasion entitlement on your API key. Without it they answer `403`. See [Authentication](/api-reference/api-reference/authentication.md).

## The two numbers that matter, and how to read them

**`evasive_ratio` is a ratio in `0..1`, not a percentage.** `0.2667` means roughly one question in four. It is never multiplied by 100 anywhere in this API.

**`question_answer_count` is the denominator, and it is not the length of the exchanges list.** The exchanges resource returns *only* the evasive pairs, so dividing by its length gives `1.0` every time:

```
evasive_ratio = evasive_question_answer_count / question_answer_count
              = 4 / 15
              = 0.2667
```

A ratio is close to meaningless on its own — `0.5` over four questions and `0.5` over ninety are not the same finding. Carry `question_answer_count` with it.

## Analyses

### Filters

All filters are optional and compose. Unless noted, an unmatched value returns an empty page rather than an error.

| Parameter                                 | Type      | Notes                                                                                                                                                                                                                                                                                                                                                                          |
| ----------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `company_id`                              | UUID      | Resolve it first with [`GET /companies`](/api-reference/api-reference/companies-search.md).                                                                                                                                                                                                                                                                                    |
| `company_ids`                             | string    | Several company ids, comma-separated.                                                                                                                                                                                                                                                                                                                                          |
| `company_ticker`                          | string    | The analysed company's ticker, **case-insensitive**. A ticker can belong to more than one company: if it matches more than one, the answer is `409` with the candidates — see [A ticker is not an identity](#a-ticker-is-not-an-identity). No match is an empty page.                                                                                                          |
| `call_date_min` / `call_date_max`         | date-time | Inclusive bounds on the call date.                                                                                                                                                                                                                                                                                                                                             |
| `fiscal_year`                             | integer   | The fiscal year the call reports on.                                                                                                                                                                                                                                                                                                                                           |
| `fiscal_period`                           | string    | The fiscal period the call reports on, as served in `call.fiscal_period`: an exact match, usually `"1"`–`"4"`; some calls carry `"5"` or a month. Not the calendar quarter — see below. Replaces `fiscal_quarter`, removed in v0.3: a request that still sends `fiscal_quarter` gets **`422`** (with a string `detail` naming `fiscal_period`) rather than an unfiltered page. |
| `evasive_ratio_min` / `evasive_ratio_max` | number    | Inclusive bounds, in `0..1`.                                                                                                                                                                                                                                                                                                                                                   |
| `outlier`                                 | boolean   | Filter on the `outlier` flag — see its definition below.                                                                                                                                                                                                                                                                                                                       |
| `topic_id`                                | string    | Topic ids from [`GET /evasion/topics`](#topics), comma-separated. Matches an analysis that addressed **any** of them.                                                                                                                                                                                                                                                          |
| `include`                                 | string    | `previous_versions` to include earlier analysis versions as well as the newest.                                                                                                                                                                                                                                                                                                |
| `expand`                                  | string    | `exchanges` to embed each analysis's evasive exchanges.                                                                                                                                                                                                                                                                                                                        |
| `updated_since`                           | date-time | Only analyses that moved at or after this time. See [Keeping in sync](#keeping-in-sync).                                                                                                                                                                                                                                                                                       |
| `ordering`                                | string    | Field name, `-` prefix for descending. One of `call_date`, `call_title`, `evasive_ratio`, `question_answer_count`, `updated_at`, `version`. An unrecognised name is ignored rather than rejected.                                                                                                                                                                              |
| `page` / `per_page`                       | integer   | `page` starts at 1; `per_page` defaults to 20, max 100.                                                                                                                                                                                                                                                                                                                        |

### Response fields

Results arrive in the standard paginated envelope (`data`, `pagination`) described in [Data Models](/documentation/data-models.md#pagination-envelope).

| Field                                    | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `analysis_id`                            | UUID of this analysis **version**. Stable.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `company`                                | `company_id`, `company_name`, `stock_ticker`. `company_id` is the identity, resolvable via [`GET /companies/{company_id}`](/api-reference/api-reference/companies-search.md); `stock_ticker` is nullable and is **not unique** across companies.                                                                                                                                                                                                                                                                                                                            |
| `question_answer_count`                  | Number of question-and-answer groups the model found in the call's Q\&A section. **The denominator for all ratios.** Not the same numbering as `exchanges[].sequence`.                                                                                                                                                                                                                                                                                                                                                                                                      |
| `evasive_question_answer_count`          | Number of those groups judged evasive. Equals the number of rows the exchanges endpoint returns.                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `evasive_ratio`                          | `evasive_question_answer_count / question_answer_count`, rounded to 4 decimals. A ratio in `0..1`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `outlier`                                | With x = ln(1 + `evasive_ratio`) per call in date order: flagged when x exceeds the peak of a kernel density estimate over the previous 4 calls by more than 0.8 times the standard deviation of x over the previous 12 calls (minimum 4). Uses earlier calls only. First four calls never evaluated. Computed by Paragon. The KDE bandwidth and the population of calls it runs over are not published, so a recomputation from this API's data matches most flags but not all; treat it as a statistical flag against the company's own history, not a verdict. Nullable. |
| `outlier_predictive`                     | Set on an outlier whose company's earlier outliers, with 180-day windows closed before this call, had 180-day stock-minus-sector-ETF returns significantly negative at p ≤ 0.05, averaging at or below −4.9% over the trailing 5 years, with at least 3 such outliers. Requires price data; not reproducible from this API alone. Benchmark: US GICS sector ETF, price return, entry at the close after the call. Nullable.                                                                                                                                                 |
| `historical_average_evasive_ratio`       | Σ evasive groups / Σ groups over the company's **earnings calls** (`call.call_kind = earnings_call`) dated on or before this call, the latest verdict-bearing version of each, this call included when it is an earnings call. Cumulative, no window, weighted by call size, rounded to 4 decimals. A fixed-income, investor-event or other call carries the company's earnings-call average as of its date but never contributes to it. **Null, not zero**, when there is no earnings call on or before it.                                                                |
| `historical_average_evasive_ratio_delta` | `evasive_ratio` minus the field above, computed before rounding, then rounded to 4 decimals. Zero on a company's first earnings call. Null whenever either side is missing.                                                                                                                                                                                                                                                                                                                                                                                                 |
| `topics[]`                               | **Topics overlap. Counts do not sum to the call.** Per topic: `topic_id`, `topic`, `question_count`, `evasive_count`, `evasive_ratio`. `topic` comes from the fixed vocabulary at [`GET /evasion/topics`](#topics).                                                                                                                                                                                                                                                                                                                                                         |
| `topics[].question_count`                | Groups whose addressed topics include this topic. A group can carry several topics, so these do not sum to the call.                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `topics[].evasive_count`                 | Those groups where the topic was evaded. Equals the number of exchanges tagged with the topic and `evasive: true`.                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `call`                                   | `call_date`, `call_type`, `call_title`, `fiscal_year`, `fiscal_period`, `calendar_quarter`, `call_kind`. **All but `call_kind` are nullable.**                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `call.calendar_quarter`                  | `year(call_date) * 100 + quarter(call_date)` — calendar, not fiscal.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `call.call_kind`                         | What kind of session the call was: `earnings_call`, `fixed_income`, `investor_event` or `other`. FactSet types fixed-income and investor sessions as earnings events, so `call_type` alone cannot tell them apart. Only `earnings_call` contributes to the historical average. See [Call kinds](#call-kinds).                                                                                                                                                                                                                                                               |
| `version`                                | 1-based, per call.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `parent_analysis_id`                     | The older version of this call that this one replaced, or null for version 1. The parent comes first: the newest version is the one no analysis points at. Always resolvable.                                                                                                                                                                                                                                                                                                                                                                                               |
| `is_latest`                              | Whether this is the newest version of the call.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `updated_at`                             | When the analysis last moved at the source. **This is the sync cursor.**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `exchanges`                              | Present only with `expand=exchanges`. `null` means not expanded; `[]` means expanded and the call had nothing evasive.                                                                                                                                                                                                                                                                                                                                                                                                                                                      |

A call has no id of its own on this API. Key it on `company.company_id` + `call.call_date` + `call.call_title`, which is also how you will recognise it.

### A ticker is not an identity

Tickers are reused across exchanges: 1,925 of them belong to more than one live company. `CSL` is Carlisle Companies on the NYSE **and** CSL Limited on the ASX; `JD` is JD.com on Nasdaq **and** JD Sports Fashion in London, and both of those have analysed calls.

So `company_ticker` never guesses. It matches case-insensitively, and:

* **one** company → that company's analyses;
* **none** → an empty page;
* **more than one** → `409 Conflict`, listing every candidate, most-analysed first. Pick one — by `exchange` or `company_name`, or ask your user — and call again with its `company_id`.

```json
{
  "detail": {
    "error": "ambiguous_ticker",
    "message": "Ticker 'CSL' matches 2 companies. Pass company_id to choose one.",
    "candidates": [
      {
        "company_id": "7c31a0e2-4f8b-4a7d-9c21-3e5f6a8b0d19",
        "company_name": "Carlisle Companies Incorporated",
        "stock_ticker": "CSL",
        "exchange": "NYSE",
        "analysed_calls": 65
      },
      {
        "company_id": "5e2b9c47-1d8a-4f36-b7e0-c94a2d1f8b63",
        "company_name": "CSL Limited",
        "stock_ticker": "CSL",
        "exchange": "ASX",
        "analysed_calls": 0
      }
    ]
  }
}
```

`analysed_calls` is the number of distinct calls with a served analysis — what `?company_id=` would list for that company by default. Passing `company_id` (or `company_ids`) alongside the ticker already chooses, and no `409` is raised. If you store companies, store `company_id`; a ticker is something to display.

### Call kinds

FactSet types every session of an earnings event as an earnings call, so they all arrive with `call_type: "earnings_release"`. Some of them are not the earnings call: a bank holds a **fixed-income** call for bondholders the same afternoon ("Q4 2014 Earnings Call - Fixed Income", "… - Bondholders Call", "… - Treasurer Q\&A"), and some companies fold an **investor day** into the event ("… - Capital Market Day"). The title is the only thing that tells them apart, and `call.call_kind` is that distinction made for you:

| `call_kind`      | What it is                                                                                                                                             |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `earnings_call`  | The earnings call. A second session of it for another audience or locale ("- Second Call", "- Q\&A", "- Retail Investors") is still the earnings call. |
| `fixed_income`   | A session for bondholders, creditors or debt investors, or a treasury / credit update.                                                                 |
| `investor_event` | An investor, analyst, capital-markets, strategy or R\&D day, or an investor meeting or conference.                                                     |
| `other`          | Anything that is not an earnings release and matches neither of the above.                                                                             |

**Only `earnings_call` feeds `historical_average_evasive_ratio`.** A fixed-income call answered by the treasurer is a different conversation with a different audience; counting it into the company's average counted one results day twice. Every analysis of a non-earnings session is still served — with its own verdict, and carrying the company's earnings-call average as of its date — so keep only `call_kind: "earnings_call"` on your side if you want earnings calls alone (there is no `call_kind` query filter).

### Versions — a call can be analysed more than once

**The default list returns the newest version of each call.** A call can be re-analysed, and two versions of the same call can carry different verdicts, so a list that showed every version would hand you two contradictory numbers for one call.

Pass `include=previous_versions` when you want the history. `version`, `parent_analysis_id` and `is_latest` describe where each row sits in its call's chain, and `parent_analysis_id` always resolves through `GET /evasion/analyses/{analysis_id}`.

{% hint style="info" %}
**Two quarters, and they disagree for most calls.** `fiscal_period` is the fiscal period the call *reports on*; `calendar_quarter` (`YYYYQQ`, e.g. `202603`) is the calendar quarter it *happened in*. A company reports its fiscal Q2 weeks into the following calendar quarter, so for the large majority of calls the two are different. Both are served, both are named, and neither is derived from the other. Use `fiscal_period` when you mean a company's quarter.

**`fiscal_period` is a string.** It carries the source's value, which is usually `"1"`–`"4"` but on a minority of calls is `"5"` or a month abbreviation. Filter on it with `fiscal_period`, which matches that string exactly, `"5"` and months included. There is no `fiscal_quarter` field in the response, and no `fiscal_quarter` filter either: sending it is a `422`.
{% endhint %}

### Example

```bash
curl "https://api.heron-intelligence.com/api/v1/evasion/analyses?company_ticker=AMZN&per_page=1" \
  -H "x-api-key: <YOUR_API_KEY>"
```

```json
{
  "data": [
    {
      "analysis_id": "4a1c2f70-9c3d-5b2e-8f01-2d6b7a9e4c11",
      "company": {
        "company_id": "7c31a0e2-4f8b-4a7d-9c21-3e5f6a8b0d19",
        "company_name": "Amazon.com, Inc.",
        "stock_ticker": "AMZN"
      },
      "question_answer_count": 15,
      "evasive_question_answer_count": 4,
      "evasive_ratio": 0.2667,
      "outlier": false,
      "outlier_predictive": false,
      "historical_average_evasive_ratio": 0.1883,
      "historical_average_evasive_ratio_delta": 0.0784,
      "topics": [
        {
          "topic_id": "8a20b1c4-5d6e-4f70-8192-a3b4c5d6e7f8",
          "topic": "Capital Allocation & Financial Strategy",
          "question_count": 6,
          "evasive_count": 2,
          "evasive_ratio": 0.3333
        }
      ],
      "call": {
        "call_date": "2026-08-04T12:30:00Z",
        "call_type": "earnings_release",
        "call_title": "Q2 2026 Earnings Call",
        "fiscal_year": 2026,
        "fiscal_period": "2",
        "calendar_quarter": 202603,
        "call_kind": "earnings_call"
      },
      "version": 2,
      "parent_analysis_id": "1b7d5e93-2a84-5c16-b0f7-9d4e2c8a5301",
      "is_latest": true,
      "updated_at": "2026-09-09T04:02:55Z",
      "exchanges": null
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 1,
    "total_items": 34,
    "total_pages": 34,
    "has_next": true,
    "has_previous": false,
    "next_page": 2,
    "previous_page": null
  }
}
```

{% openapi src="/files/rhZvju8DuyV351qD9FwY" path="/api/v1/evasion/analyses" method="get" %}
[dataproduct-openapi.json](https://3524418219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FRWm75ANZdNMw24schJSn%2Fuploads%2Fgit-blob-29443b5f66daf843ba15b1d60e5cc3c105771cea%2Fdataproduct-openapi.json?alt=media)
{% endopenapi %}

{% openapi src="/files/rhZvju8DuyV351qD9FwY" path="/api/v1/evasion/analyses/{analysis\_id}" method="get" %}
[dataproduct-openapi.json](https://3524418219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FRWm75ANZdNMw24schJSn%2Fuploads%2Fgit-blob-29443b5f66daf843ba15b1d60e5cc3c105771cea%2Fdataproduct-openapi.json?alt=media)
{% endopenapi %}

## Exchanges

`GET /api/v1/evasion/analyses/{analysis_id}/exchanges` returns **the evasive question-answer pairs of one analysis, and only those.** The question you are asking is "what did they evade"; the denominator lives on the parent analysis.

Each exchange carries **its own question and answer and nothing around them** — no preceding pair, no following pair, no transcript. The pair is served as the evidence for the verdict so that you can judge the verdict yourself.

| Field         | Notes                                                                                                                                   |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `exchange_id` | UUID.                                                                                                                                   |
| `analysis_id` | The parent analysis version.                                                                                                            |
| `sequence`    | Position of the pair in the API's own pairing of the call. Can exceed `question_answer_count`. Null when the pair could not be located. |
| `question`    | The question as asked. Nullable.                                                                                                        |
| `answer`      | The answer as given. Nullable.                                                                                                          |
| `evasive`     | Always `true` on this resource.                                                                                                         |
| `rationale`   | The model's written reasoning. A model's opinion, not a finding.                                                                        |
| `topics[]`    | `topic_id`, `topic`, `detail`, `description`, `evasive`.                                                                                |
| `updated_at`  | When the exchange last moved at the source.                                                                                             |

**`topic` and `detail` are different things.** `topic` is a term from the [controlled vocabulary](#topics) — a fixed list you can fetch and cache, not something generated per call — so use it to group or compare. `detail` is the model's own finer phrasing of the same idea ("AFFO accretion") and will not match across calls.

**Both can be `null`, and not together.** `topic` is `null` when the model's phrasing matched no vocabulary term; `detail` still carries what it said, so the topic is never silently dropped. `topic_id` is `null` whenever `topic` is, and also when a term is not in the catalogue.

{% hint style="warning" %}
**`sequence` is not an index into `question_answer_count`, and the two must not be compared.** They are different countings of the same call: `question_answer_count` counts the groups the model found, `sequence` is this API's own pairing, and it splits a call into more units than the model groups it into. A call counted as 25 questions routinely has evasive exchanges at sequence 30 or beyond — that is the two systems disagreeing about where one exchange ends and the next begins, not a missing question. Use `sequence` to order exchanges and to see where in a call one falls; use `question_answer_count` as the denominator, and never one against the other.
{% endhint %}

{% hint style="info" %}
**`question` and `answer` can be null, and that is a real answer.** On a minority of exchanges the pair cannot be located — the analysed group had no question in it, or the call has no readable body. The verdict and its `rationale` are still real; we cannot show the words they are about, and saying so is better than showing a different pair. `sequence` is null on the same terms.
{% endhint %}

```json
{
  "data": [
    {
      "exchange_id": "c0a1f83b-7e25-4d69-9a04-b81c3f27de50",
      "analysis_id": "4a1c2f70-9c3d-5b2e-8f01-2d6b7a9e4c11",
      "sequence": 7,
      "question": "Can you size the year-one AFFO accretion from the 100-basis-point spread?",
      "answer": "We're very comfortable with the returns profile on that portfolio…",
      "evasive": true,
      "rationale": "The executive discusses investment strategy and IRR without answering the specific question about year-one AFFO accretion.",
      "topics": [
        {
          "topic_id": "8a20b1c4-5d6e-4f70-8192-a3b4c5d6e7f8",
          "topic": "Capital Allocation & Financial Strategy",
          "detail": "AFFO accretion",
          "description": "Requested the expected year-one AFFO accretion attributable to the 100-basis-point spread…",
          "evasive": true
        }
      ],
      "updated_at": "2026-09-09T04:02:55Z"
    }
  ],
  "pagination": { "current_page": 1, "per_page": 20, "total_items": 4, "total_pages": 1, "has_next": false, "has_previous": false, "next_page": null, "previous_page": null }
}
```

{% openapi src="/files/rhZvju8DuyV351qD9FwY" path="/api/v1/evasion/analyses/{analysis\_id}/exchanges" method="get" %}
[dataproduct-openapi.json](https://3524418219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FRWm75ANZdNMw24schJSn%2Fuploads%2Fgit-blob-29443b5f66daf843ba15b1d60e5cc3c105771cea%2Fdataproduct-openapi.json?alt=media)
{% endopenapi %}

## Topics

`GET /api/v1/evasion/topics` returns the controlled vocabulary the dataset's topics are drawn from: a set of terms per industry, plus a default set that applies where no industry-specific one does.

**It is a predefined list, not free text and not generated per call.** The terms and their `topic_id`s are fixed, so you can fetch this resource once, cache it, and join against it. It changes rarely; when it does, an existing term keeps its `topic_id`.

A call is scored against its own industry's set, so a `topic` on an analysis or an exchange is normally a term from this list. **Resolve it by its `topic_id` rather than by matching its text**, so that a renamed term stays the same term.

On this resource `topic_id` and `topic` are always present. Elsewhere they are not, and the two differ:

* inside an **analysis**, `topics[].topic` is always a term, but its `topic_id` is `null` if that term is not in the catalogue;
* inside an **exchange**, `topics[].topic` itself can be `null`, because a small share of what the model produces matches no catalogued term. It is served as it is, in `detail`, rather than dropped.

| Field         | Notes                                                             |
| ------------- | ----------------------------------------------------------------- |
| `topic_id`    | UUID. Use it in the `topic_id` filter on analyses.                |
| `industry`    | The industry whose set this term belongs to.                      |
| `ordinal`     | Render order within the industry's set.                           |
| `topic`       | The term itself.                                                  |
| `explanation` | The sentence the model was given describing what the topic means. |

| Parameter           | Type    | Notes                                                                                       |
| ------------------- | ------- | ------------------------------------------------------------------------------------------- |
| `industry`          | string  | One industry's set. Pass an empty string for the default set.                               |
| `ordering`          | string  | `industry`, `ordinal`, `topic`, with `-` for descending. Defaults to `(industry, ordinal)`. |
| `page` / `per_page` | integer | Standard pagination.                                                                        |

{% hint style="warning" %}
**`industry: ""` is the default topic set — a value, not a blank.** It is the catalogue that applies where no industry-specific one does. Do not coerce it to null, filter it out, or treat it as missing data. `?industry=` returns that set.
{% endhint %}

{% openapi src="/files/rhZvju8DuyV351qD9FwY" path="/api/v1/evasion/topics" method="get" %}
[dataproduct-openapi.json](https://3524418219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FRWm75ANZdNMw24schJSn%2Fuploads%2Fgit-blob-29443b5f66daf843ba15b1d60e5cc3c105771cea%2Fdataproduct-openapi.json?alt=media)
{% endopenapi %}

## Keeping in sync

Two mechanisms, and you want both.

**Webhooks** push you `evasion.analysis.published` and `evasion.analysis.revised` as they happen. See [Webhooks](/api-reference/api-reference/webhooks.md#evasion-events).

**`updated_since` + pagination** is how you catch up. A webhook alone is not a feed: if your endpoint was down, nothing replays it. Every list resource accepts `updated_since`, so:

1. Keep the largest `updated_at` you have seen.
2. Call `GET /evasion/analyses?updated_since=<that value>&ordering=updated_at`.
3. Page through, and advance your cursor.

`updated_at` is the timestamp at which the analysis last moved at the source, and it is the value the webhooks and this filter agree on.

**Expect revisions.** A revision changes a number you have already stored — that is what `evasion.analysis.revised` and `parent_analysis_id` are for. Key your own store on `analysis_id` and follow `parent_analysis_id` to retire what it replaced.

## Provenance

Heron Intelligence names the origin of everything it serves. See [Data Providers](/documentation/data-providers.md).

**An evasion verdict is not one of those origins.** It is not a transcript and not something a researcher observed: it is a language model's judgement *about* an earnings call, scored inside [Paragon](/documentation/data-providers.md#paragon). **Every analysis and every exchange — the verdict, the ratios built on it, every rationale — is model output.** That holds for every row, so it is stated here once rather than carried as a field on each object.

When you surface a verdict:

* **Attribute it as an inference.** "The analysis judged this answer evasive" — not "the CFO dodged the question". The second states a model's opinion as a fact about a named person.
* **Carry the denominator.** "4 of the 15 questions on the Q2 call were judged evasive", not "27% evasive".
* **Do not report an absent verdict as a zero.** A call with no analysis is a call we have not scored.
