API Documentation
The complete Monitory workflow — query, create a monitor, get alerted — available through the web app or programmatically via the API. Pro required for API access
The Monitory workflow
Every monitor in Monitory follows the same four steps, whether you set it up in the dashboard or build it entirely through the API:
- 1Query — run an ad-hoc query (
POST /api/query) to see the structured data you'd be monitoring, or skip straight to step 2 if you already know what you want. - 2Create a monitor —
POST /api/monitorswith a schema (generic /seo_rank/ai_visibility), a check frequency, an alert condition, and where to deliver alerts. - 3Monitory checks it automatically — a background worker re-runs the monitor on schedule (every 5 min for generic, 30 min for
seo_rank, 60 min forai_visibility) and evaluates your alert condition. - 4You get alerted — Slack, email, or webhook, only when the condition actually fires.
GET /api/monitors/:idanytime to pull the full run/alert history.
1. Get an API key
API access is a Pro feature. Generate a key below (you must be signed in) — the plaintext key is shown exactly once, so copy it immediately.
2. Authenticate
Send your key as a Bearer token on every request. Keys are Pro-only and rate-limited to 60 requests per minute per key.
curl https://monitory.app/api/monitors \
-H "Authorization: Bearer mnty_xxxxxxxxxxxxxxxxxxxxxxxx"3. Endpoints
/api/queryRun an ad-hoc query and get structured JSON back. Public — no API key required. Good for previewing what a monitor would return before creating it.
curl -X POST https://monitory.app/api/query \
-H "Content-Type: application/json" \
-d '{"query": "Bitcoin price right now", "schema": "crypto"}'/api/monitorsList every monitor on your account.
curl https://monitory.app/api/monitors \
-H "Authorization: Bearer mnty_..."/api/monitorsCreate a monitor. schema determines which fields condition needs:
Generic monitor (e.g. price tracking)
curl -X POST https://monitory.app/api/monitors \
-H "Authorization: Bearer mnty_..." \
-H "Content-Type: application/json" \
-d '{
"query": "Bitcoin price right now",
"schema": "crypto",
"frequency": "hourly",
"delivery": "webhook",
"webhookUrl": "https://your-endpoint.com/hook",
"condition": {
"type": "threshold",
"field": "prices[].amount",
"operator": "<",
"threshold": 50000
}
}'SEO rank monitor
curl -X POST https://monitory.app/api/monitors \
-H "Authorization: Bearer mnty_..." \
-H "Content-Type: application/json" \
-d '{
"query": "Rank tracker: \"best crm software\"",
"schema": "seo_rank",
"frequency": "daily",
"delivery": "slack",
"webhookUrl": "https://hooks.slack.com/services/...",
"condition": {
"type": "rank_drop",
"keyword": "best crm software",
"targetUrl": "https://example.com/crm",
"locationCode": "2840",
"dropThreshold": 3
}
}'condition.type can also be position_moved, position_up, position_down, or serp_changed — only rank_drop triggers the AI why-analysis.
AI visibility monitor
curl -X POST https://monitory.app/api/monitors \
-H "Authorization: Bearer mnty_..." \
-H "Content-Type: application/json" \
-d '{
"query": "AI Visibility: \"Acme\" for \"best CRM for small teams\"",
"schema": "ai_visibility",
"frequency": "weekly",
"delivery": "slack",
"webhookUrl": "https://hooks.slack.com/services/...",
"condition": {
"type": "mention_changed",
"prompt": "What is the best CRM for a small team?",
"entity": "Acme",
"engines": ["chatgpt", "gemini", "claude", "perplexity"]
}
}'/api/monitors/:idGet a monitor plus its run history, fired alerts, and — for seo_rank monitors — its full position-over-time snapshot history.
curl https://monitory.app/api/monitors/<id> \
-H "Authorization: Bearer mnty_..."/api/monitors/:idUpdate a monitor, or pause/resume it.
curl -X PATCH https://monitory.app/api/monitors/<id> \
-H "Authorization: Bearer mnty_..." \
-H "Content-Type: application/json" \
-d '{"action": "toggle_pause"}'/api/monitors/:idDelete a monitor and its history permanently.
curl -X DELETE https://monitory.app/api/monitors/<id> \
-H "Authorization: Bearer mnty_..."4. Slack & webhook alerts
Every monitor schema (generic, seo_rank, ai_visibility) can deliver to Slack or to your own webhook endpoint — set delivery and webhookUrlthe same way in the dashboard's "Deliver to" step or via the API.
Set up Slack (Incoming Webhook)
- 1Go to api.slack.com/apps → Create New App → From scratch— name it (e.g. "Monitory") and pick the workspace to post into.
- 2In the app settings, open Incoming Webhooks in the left sidebar and switch it On.
- 3Click Add New Webhook to Workspace, choose the channel Monitory should post alerts to, and authorize it.
- 4Copy the generated URL — it looks like
https://hooks.slack.com/services/…— and paste it as the webhook URL when you pick Slackdelivery for a monitor. That's the entire setup; no bot install or extra scopes needed.
Set up a generic webhook
Pick Webhook delivery instead of Slack and point it at any HTTPS endpoint you control (a Zapier/Make catch hook, your own backend, etc). Monitory POSTs plain JSON — no Slack-specific formatting — every time the monitor's alert condition fires:
{
"source": "monitory-alert",
"alertId": "9f2c...",
"monitorName": "Rank tracker: \"best crm software\" — https://example.com/crm",
"alertType": "rank_drop",
"value": {
"keyword": "best crm software",
"targetUrl": "https://example.com/crm",
"previousPosition": 4,
"currentPosition": 11,
"analysis": { "issueType": "competitor_surge", "confidenceScore": 0.82, "recommendedAction": "..." }
},
"timestamp": "2026-08-16T09:00:00.000Z"
}The exact shape of value depends on the schema and alert condition — generic monitors send the diffed field(s), ai_visibility sends which engines mentioned the entity. Your endpoint should return a 2xx within 10 seconds; Monitory does not currently retry failed deliveries.
5. Errors & rate limits
| Status | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 402 | Free-tier monitor limit reached — upgrade to Pro |
| 403 | API access requires a Pro subscription |
| 404 | Monitor not found (or not yours) |
| 429 | Rate limit exceeded — 60 requests/minute per key |