Skip to content

AI assistance API

MethodPathAuthPurpose
POST/watches/draftTokenTurn a plain-English description into a draft watch. Nothing is saved.
POST/watches/draft/check-domainsTokenBest-effort liveness check for suggested domains.
POST/watches/draft/previewTokenDry-run a search source and return the top candidate titles and URLs.
POST/watches/:id/explainTokenExplain an existing watch in plain English. Read-only.
POST/watches/:id/reviseTokenPropose a field-level change set from one instruction. Nothing is saved.

All of them are rate-limited to 10 requests per minute per owner, and all return 503 when the instance has no model key configured.

Terminal window
curl -s -X POST https://<your-host>/watches/draft \
-H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"description":"Tell me when version 2.0 of the framework is released as stable"}'
{
"draft": {
"name": "Framework 2.0 stable release",
"condition": "Alert when version 2.0 is released as stable…",
"sources": [
{ "type": "search", "value": "framework 2.0 stable release", "recencyDays": 30, "rationale": "" }
],
"schedule": "0 */6 * * *",
"threshold": 0.6,
"notes": "Assumed you want stable releases only."
}
}

Refine a previous draft in one round by sending it back with an instruction:

{
"description": "",
"refine": { "previousDraft": { "...": "..." }, "instruction": "only official sources" }
}

rationale and notes are display-only and are never stored on a watch.

Terminal window
curl -s -X POST https://<your-host>/watches/framework-releases/revise \
-H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"instruction":"check twice a day instead, and stop sending unconfirmed alerts"}'

Returns a field-level change set — only what should change:

{
"revision": {
"schedule": "0 */12 * * *",
"weakThreshold": null,
"reasons": [ { "field": "schedule", "why": "twice a day" } ]
}
}
Convention Meaning
Field absent Leave it exactly as it is
Field present Proposed new value
Field null Remove this optional field

Send the panel’s current (possibly unsaved) form state as base so the diff is computed against what the user is actually looking at. A base whose id does not match the path is ignored, and ownership is always enforced on the path id.

Apply what you approve with a normal PUT /watches/:id.

Terminal window
curl -s -X POST https://<your-host>/watches/framework-releases/explain \
-H "authorization: Bearer $TOKEN"
{ "explanation": "Every six hours this checks the official blog feed and a web search for…" }

Read-only, and useful for confirming that a watch says what you think it says.

Terminal window
curl -s -X POST https://<your-host>/watches/draft/preview \
-H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"value":"framework 2.0 stable release","hints":{"recencyDays":30}}'

Runs the search once and returns up to five candidate titles and URLs. Nothing is stored and no evaluation happens — it is the fastest way to see whether a query finds the right pages before committing to it. Returns 503 when no search key is configured.

Terminal window
curl -s -X POST https://<your-host>/watches/draft/check-domains \
-H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"domains":["example.gov","not-a-real-domain.test"]}'
{ "liveness": { "example.gov": true, "not-a-real-domain.test": false } }

A best-effort reachability check so a hallucinated domain can be flagged rather than silently pinned. It never throws: an unverifiable domain is simply reported as false.