# Refresh a breakdown's videos

> For the complete documentation index, see [llms.txt](https://www.shortsintel.com/llms.txt). Every docs page is also available as markdown: add .md to its URL. To connect, read [agents.md](https://www.shortsintel.com/agents.md).

POST `/v1/breakdowns/{id}/refresh`

Sweeps fresh metrics for a Breakdown's videos, as `POST /v1/research/{id}/refresh` does: same price, rules and response. An intent-mode Research id is the same 404 as an unknown id.

[Open in Playground](https://www.shortsintel.com/console/playground?op=refreshBreakdown&id=id_example) (no API Key needed)

## Price

3 credits per video that comes back.

Supports `estimate=true`: the reply is the price in Credits and whether it would be `cached`, with no Run created and nothing charged.

A cached result costs the same as a fresh one; `cached` says which you got.

## Parameters

| Name | In | Type | Required | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `id` | path | `string` | Required | — | Breakdown id — the id of its Run. |
| `Idempotency-Key` | header | `string` | Optional | — | 1-255 printable ASCII characters. Replaying this key with the same payload returns the original Run (202 while it is still running); a different payload, or a different operation, is a 409 `idempotency_conflict`. |
| `wait` | query | `integer` min 0; max 120 | Optional | `30` | Seconds to hold the response open before handing back a running Run to poll. Default 30, max 120. A POST may send it in the body instead; different values in both places are a 400. |
| `max_credits` | query | `integer` min 0 | Optional | — | Most Credits the call may cost. A higher quote is a 402 `max_credits_exceeded`, no Run. Where `x-price.max_credits` is null, the Run stops at it and settles `partial`. |
| `estimate` | query | `boolean` | Optional | — | `true` returns `{ estimate_credits, cached }` from what is already stored, creating no Run. Nothing is charged. Only `true` or `false`, else a 400. A POST may send it in the body instead; different values in both places are a 400. |

## Responses

### 200 OK

The sweep finished inside the wait budget: `{ run, result }`. The example is a `partial` run — two of the fifty videos have been deleted since the research ran, so forty-eight were swept and charged for. With `estimate=true`, `{ estimate_credits, cached, videos, per_video_credits, max_estimate_credits, note }` instead: `videos` is how many will be swept, `max_estimate_credits` equals `estimate_credits` because a video that fails is not charged, and `note` says so — and, when some of the research's videos are on a platform that cannot be refreshed yet, how many are left out.

any of 2 shapes

- Option 1 object The envelope every charged operation answers with: `{ run }` while the Run is running (plus `poll_url` on the 202), joined by `result` once it completes or `error` once it fails.
  - `run` object required Every charged operation creates a Run. The envelope is identical whether the result came back inline or was polled.
    - `id` string required
    - `kind` string required What was run, e.g. `video_lookup`.
    - `status` string required one of `running`, `completed`, `partial`, `failed` `partial` keeps the completed items and charges for them, up to what the Balance covers; `failed` charges nothing.
    - `created_at` string required RFC 3339.
    - `completed_at` string required nullable Null while the Run is still running.
    - `charge_credits` integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    - `list_price_credits` integer required The full price of the work asked for, in Credits. Equal to `charge_credits` unless the Run charged for only part of it.
    - `cached` boolean required True when a stored result answered without a fresh fetch.
    - `progress` object What a running Research has done so far, refreshed as it works: its `stage` and the counts known by then, such as `analysed` of `shortlisted`. A count is absent until its stage produced it. Absent once the Run settles, and on every other kind.
      - `stage` string required one of `keywords`, `searching`, `reading_creators`, `filtering`, `analysing`, `writing_digest`
      - `keywords` integer value at least 0
      - `creators` integer value at least 0
      - `creators_read` integer value at least 0
      - `searches` integer value at least 0
      - `found` integer value at least 0
      - `judged` integer value at least 0
      - `kept` integer value at least 0
      - `dropped_off_topic` integer value at least 0
      - `dropped_unsure` integer value at least 0
      - `shortlisted` integer value at least 0
      - `analysed` integer value at least 0
      - `updated_at` string required
  - `result` object required What a refresh swept. Frozen reads are unchanged by it; `as_of=latest` serves the new snapshots.
    - `research_id` string required The research whose videos were swept.
    - `requested` integer required
    - `refreshed` integer required Videos we fetched fresh numbers for, and the only ones charged for.
    - `failed` integer required
    - `per_video_credits` integer required
    - `note` string required
- Option 2 object Returned instead of a Run when `estimate=true`. Nothing is charged. Operations with more to say about a quote add members; the two above are always present.
  - `estimate_credits` integer required What the call would be charged, in Credits.
  - `cached` boolean required Whether a stored result can already answer. It does not change the price.

200 · The sweep finished inside the wait budget: `{ run, result }`. The example is a `partial` run — two of the fifty videos have been deleted since the research ran, so forty-eight were swept and charged for. With `estimate=true`, `{ estimate_credits, cached, videos, per_video_credits, max_estimate_credits, note }` instead: `videos` is how many will be swept, `max_estimate_credits` equals `estimate_credits` because a video that fails is not charged, and `note` says so — and, when some of the research's videos are on a platform that cannot be refreshed yet, how many are left out.

```json
{
  "run": {
    "id": "run_8f2c1ad04b",
    "kind": "research_refresh",
    "status": "partial",
    "created_at": "2026-09-08T09:14:02.418Z",
    "completed_at": "2026-09-08T09:14:04.930Z",
    "charge_credits": 144,
    "list_price_credits": 150,
    "cached": false
  },
  "result": {
    "research_id": "run_c07a41bb92",
    "requested": 50,
    "refreshed": 48,
    "failed": 2,
    "per_video_credits": 3,
    "note": "Frozen reads are unchanged. `as_of=latest` now serves these snapshots."
  }
}
```

200 · With `estimate=true`: the price, no Run, no charge.

```json
{
  "estimate_credits": 150,
  "cached": false,
  "videos": 50,
  "per_video_credits": 3,
  "max_estimate_credits": 150,
  "note": "A video we cannot fetch is not charged, so the final charge is at or below this quote."
}
```

### 202 Accepted

Still running: `{ run }`. Poll `GET /v1/runs/{id}`.

object

Still running. Poll `poll_url` (`GET /v1/runs/{id}`), waiting the 202's `Retry-After` seconds between polls.

- `run` object required Every charged operation creates a Run. The envelope is identical whether the result came back inline or was polled. Its fields are on [Poll or re-read a run](https://www.shortsintel.com/docs/reference/runs/get-run#response-200).
- `poll_url` string required format `uri` Absolute URL of `GET /v1/runs/{id}` for this Run, the body's copy of the 202's `Location` header for callers that never see headers (MCP). Present only while the Run is `running`.

202 · Example

```json
{
  "run": {
    "id": "run_8f2c1ad04b",
    "kind": "research_refresh",
    "status": "running",
    "created_at": "2026-09-08T09:14:02.418Z",
    "completed_at": null,
    "charge_credits": 0,
    "list_price_credits": 0,
    "cached": false
  },
  "poll_url": "https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"
}
```

### 400 Bad Request

`invalid_request` (a malformed id, `wait`, `estimate` or Idempotency-Key) or `unsupported_platform`, refused before any Run opens. Nothing is charged.

Codes: `invalid_request`, `unsupported_platform`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 401 Unauthorized

Codes: `missing_authorization`, `invalid_key`, `key_revoked`, `key_expired`, `invalid_token`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 402 Payment Required

`insufficient_balance` — the Balance cannot cover the quoted price (the worst case for Research and enriched search). No Run is created and nothing is charged. A multi-item Run whose Balance runs short later charges its completed items up to the Balance and ends `partial`.

Code: `insufficient_balance`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 404 Not Found

Code: `not_found`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 409 Conflict

`run_not_ready` — the research is still running, or failed with nothing to serve. If it is still running, poll `GET /v1/runs/{id}` and refresh once it settles; a failed research never becomes readable. Also `idempotency_conflict` — the same Idempotency-Key sent for a different research.

Codes: `run_not_ready`, `idempotency_conflict`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 429 Too Many Requests

`rate_limit_exceeded` or `concurrency_limit_exceeded`, with `Retry-After`.

Codes: `rate_limit_exceeded`, `concurrency_limit_exceeded`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 502 Bad Gateway

A Run that opened and then failed is answered as `application/problem+json` with its problem's status — `vendor_error` here, `not_found` as 404 — and the Run envelope alongside, so the Run id is kept. A failed Run is never charged.

Code: `vendor_error`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

### 503 Service Unavailable

`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.

Code: `source_unavailable`. The problem body and every code are on [Errors](https://www.shortsintel.com/docs/reference/errors).

## Request samples

curl:

```bash
curl -X POST "https://www.shortsintel.com/v1/breakdowns/id_example/refresh?wait=30" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
```

TypeScript:

```typescript
const response = await fetch(
  "https://www.shortsintel.com/v1/breakdowns/id_example/refresh?wait=30",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer sk_live_YOUR_KEY",
    },
  },
);

if (!response.ok) {
  throw new Error(`ShortsIntel ${response.status}`);
}

const data = await response.json();
```

Python:

```python
import requests

response = requests.post(
    "https://www.shortsintel.com/v1/breakdowns/id_example/refresh?wait=30",
    headers={
        "Authorization": "Bearer sk_live_YOUR_KEY",
    },
)
response.raise_for_status()

data = response.json()
```

## Related guides

This call creates a Run. With `wait` it holds the response open until the Run finishes or the wait runs out, then answers with the finished result or `202` and the running Run. Poll [`GET /v1/runs/{id}`](https://www.shortsintel.com/docs/reference/runs/get-run) until it settles; re-reading a Run is free.

- [Runs](https://www.shortsintel.com/docs/concepts/runs): How a call becomes a Run, waiting inline, polling and free re-reads.
- [Pricing and estimates](https://www.shortsintel.com/docs/concepts/pricing-and-estimates): Credits, estimates and why a cached result costs the same as a fresh one.

[Previous Read a breakdown's digest](https://www.shortsintel.com/docs/reference/breakdowns/get-breakdown-digest)
