Research runs
Statuses, retries, refunds, depth, and monitoring — the run lifecycle in full
Base URL + auth as everywhere: Authorization: Bearer ds_live_....
Lifecycle
queued → running → completed | failed | cancelled (with cancelling between a
cancel request and its terminal state). The enum is closed — build exhaustive
matches safely.
- completed — results persisted with citations;
run.completedwebhook fires. - failed —
error.code/error.messageon the resource; the run charge is automatically refunded;run.failedwebhook fires. Don't blindly re-create — read the message first. - cancelled — partial results may exist; the charge stands (work was done).
Cost & latency
A run bills prepaid credits when it starts (typically $10 standard / $20 max
depth — see pricing, or /billing for your own account) and takes
15-60 minutes.
One run researches one topic area and fills your Blueprint with what it finds. How many rows that yields depends on the area, so don't budget from an entity count — price the specific run:
curl -s -X POST $BASE_URL/v1/research/runs/estimate \
-H "Authorization: Bearer $DEEPSIEVE_API_KEY" -H "Content-Type: application/json" \
-d '{"query": "solid-state battery startups in Japan", "depth": "standard"}'Your first real run is free (one per account, before you subscribe) and isn't consumed if it fails.
Failed runs are refunded automatically; cancelled runs are charged (work was
done). Spending is capped by the prepaid balance and any per-key budget — an
agent can hit 402, never an invoice.
Top up a report instead of re-running it
If you already have a report and want to extend it, pass additive_to rather
than starting a fresh run. Entities that report already holds with in-TTL
evidence are dropped before the run is batched, so you pay for the gap, not
the list — re-sending 20 held seeds plus 6 new ones costs about the 6.
There is no cap on how many seeds you send: price scales with the list, so a
longer one simply costs more and you approve it first.
curl -s -X POST $BASE_URL/v1/research/runs \
-H "Authorization: Bearer $DEEPSIEVE_API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"seeds": ["newco.example", "otherco.example"],
"additive_to": "<existing_run_id>"}'This is the right shape for a recurring loop — a quarterly refresh, a watchlist
you keep topping up. Without it, re-sending the full list starts a new run that
re-researches, and re-charges for, everything you already had. 404 means that
id isn't a run in your workspace.
Price it first. additive_to works on /runs/estimate too, and it narrows
the list exactly the way the charge does — so the quote is the gap, not the list
you sent:
curl -s -X POST $BASE_URL/v1/research/runs/estimate \
-H "Authorization: Bearer $DEEPSIEVE_API_KEY" -H "Content-Type: application/json" \
-d '{"seeds": ["newco.example", "otherco.example"],
"additive_to": "<existing_run_id>"}'The response carries skipped_already_held when anything was dropped — that is
why the number is lower than the list you sent, and worth logging so a surprise
looks like an explanation rather than a bug.
Reuse what we already have
If the workspace already holds current data on some of your seeds, you can keep it instead of paying to research those entities again:
curl -s -X POST $BASE_URL/v1/research/runs \
-H "Authorization: Bearer $DEEPSIEVE_API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"seeds": ["acme.example", "newco.example"], "reuse_existing": true}'Entities we already cover with in-TTL evidence are carried into the new
report as they stand, with their sources, and cost no run credit. Anything stale
is researched again regardless — reuse never passes off out-of-date data as
current. The skipped entities come back as reused_existing so a cheaper run
than your seed list implies is explained rather than mysterious.
This is the lineage-free sibling of additive_to: use reuse_existing when you
just want whatever we have, and additive_to when you specifically mean "extend
that report".
Depth
"depth": "standard" (default) or "max" — max lifts research budgets and
uses the deeper agent preview; it costs more per run.
Monitoring
"monitored": true (default) keeps the run's target re-verified after the
initial research, on a paid plan: every report is covered for its first 30 days,
then while monitoring stays on. That is the "living dataset". Your plan keeps a set number
of units fresh at no charge; each unit beyond that allowance bills per day
(see pricing for your plan's rate, or /billing for your account).
The unit is a DOSSIER, not a report — one Deep Research call's returned data.
A 20-entity request is researched as 4 dossiers, so it is 4 run credits AND 4
monitoring units, even though it reads as one report. Budget for the second
number as well as the first: it is the recurring one. When a monitored value is
re-verified and changes, a dataset.updated webhook fires with the
record/column/evidence ids. Toggle per target later in the app.
See everything you're paying to monitor
An agent that creates reports on a schedule is the caller most likely to
accumulate overlapping monitoring: re-researching a watchlist into a fresh
report, rather than topping up the old one, is the natural loop — and it
silently doubles the recurring cost. GET /v1/research/monitoring is how you
audit that in one call.
curl -s $BASE_URL/v1/research/monitoring \
-H "Authorization: Bearer $DEEPSIEVE_API_KEY"{
"object": "monitoring_overview",
"monitored_units": 12,
"billing_units": 8,
"duplicated_units": 4,
"reports": [
{"run_id": "…", "label": "EU vendors", "units": 4, "entities": 20,
"in_free_window": false, "free_until": "2026-07-30", "billing": true,
"fully_covered_by": ["<other_run_id>"]},
{"run_id": "…", "label": "Watchlist", "units": 4, "entities": 18,
"in_free_window": true, "free_until": "2026-09-04", "billing": false,
"fully_covered_by": []}
],
"warnings": [{"level": "INFO", "code": "monitoring_fully_duplicated", "…": "…"}]
}Three things worth wiring into a scheduled job:
in_free_windowandbillingare separate flags, not one status. The first means the report is inside its free 30 days and costs nothing yet (free_untilis the date that ends); the second means it is past that and spendingunitsdaily. The word "monitored" hides that difference, and it is the difference that shows up on an invoice next month.fully_covered_bylists reports whose in-TTL entity set is a superset of this one's — everything here is already kept fresh there, so these units buy nothing. Only reported for reports actuallybilling.billing_unitsvsmonitored_unitsis what you are charged for versus what you are watching.duplicated_unitsis the gap you could reclaim.
Advisory only: warnings carries INFO entries and nothing is turned off on
your behalf. Deciding which report keeps the coverage is a judgement call about
which one your pipeline reads from, and we won't guess it.
Attribution & budgets
Runs created with an API key record that key (api_key_id) for audit and
budget purposes. Keys can carry budget_runs/budget_cents ceilings —
exceeding one returns 402 budget_exceeded.
Questions about a finished run
Ask the research agent directly — see Chat with the research agent. Your questions appear in the customer's own chat history for that report, attributed to your API key.