{"openapi":"3.1.0","info":{"title":"Citare API","version":"0.1.0","description":"Full programmatic access to every Citare action. Every endpoint here\nmirrors a button or query in the dashboard at https://citare-v2.ravirdp.workers.dev/app.\n\nThe same set of operations is exposed as MCP tools at\n`https://mcp.citare.ai` for AI agents (Claude Desktop, ChatGPT\nDesktop, Cursor, etc.).\n\n**Authentication:** all routes (except this spec itself) require a\nbearer token in the `Authorization` header. Issue keys at\n`/app/account/api-keys`. Each key carries a granular set of scopes\n(see `components.securitySchemes`).\n\n**Rate limits:** per-user, tier-based, fixed-window 60s:\n* Free 60/min\n* Pulse 1000/min\n* Pro 5000/min\n* Agency 10,000/min\n* Enterprise unlimited\n\n**Long-running operations** (audit, brand-radar dispatch, batch\nanalysis) return `202 Accepted` with a `jobId`; poll\n`GET /api/v1/jobs/{jobId}` for completion.","contact":{"name":"Citare Support","email":"hi@citare.ai","url":"https://citare.ai/support"}},"servers":[{"url":"https://citare-v2.ravirdp.workers.dev","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"cit_api_*","description":"Issue keys at `/app/account/api-keys`. Each key carries a list\nof granular scopes from the catalog below. The same key works\nfor the REST API and the MCP server.\n\n**Catalog:**\n* `read:projects` — List projects + read project details\n* `read:audits` — Read audit history + scores\n* `read:keywords` — Read tracked keywords + GSC rankings\n* `read:backlinks` — Read cached backlink profile\n* `read:bot-analytics` — Read AI crawler hits + property list\n* `read:alerts` — Read alert rules + fired events\n* `read:reports` — Read report templates + runs + PDF download URLs\n* `read:competitive-analysis` — Read competitor sets + cached analysis runs\n* `read:batch-analysis` — Read cached batch runs\n* `read:serp-overview` — Read cached SERP snapshots\n* `read:brand-radar` — Read knowledge graph + dispatch runs + aggregates\n* `read:integrations` — Read connection status for GSC / GA4 / BWT\n* `read:team` — List team members + roles\n* `read:billing` — Read subscription + plan + invoices\n* `read:tools` — Read cached tool runs\n* `read:webhooks` — List webhook endpoints + delivery history\n* `read:ai-search` — Read AI search traffic from GA4\n* `read:audit-log` — Read your own API audit log\n* `write:projects` — Create / update / delete projects\n* `write:audits` — Run new audits on demand\n* `write:keywords` — Add / remove tracked keywords\n* `write:backlinks` — Request fresh backlink pull (counts toward DFS quota)\n* `write:bot-analytics` — Create / rotate / delete properties + API keys\n* `write:alerts` — Create / update / delete alert rules\n* `write:reports` — Create / update / delete templates + trigger run-now\n* `write:competitive-analysis` — Save competitor sets + run new analyses\n* `write:batch-analysis` — Run new batch analyses\n* `write:serp-overview` — Run new SERP overviews\n* `write:brand-radar` — Trigger dispatch runs + manage KG\n* `write:integrations` — Disconnect integrations (connecting requires browser OAuth)\n* `write:team` — Invite / remove members + change roles\n* `write:billing` — Change plan / cancel subscription\n* `write:tools` — Run any of the 18 free tools (consumes external API quota)\n* `write:webhooks` — Create / update / delete webhook endpoints\n* `admin:api-keys` — Manage other team members' API keys"}}},"paths":{"/api/v1/ping":{"get":{"operationId":"ping","summary":"Smoke endpoint — confirms auth chain works","description":"Returns the authenticated user's id + plan + the scope the key carried\nfor this call. Useful for verifying API key setup end-to-end.","tags":["meta"],"responses":{"200":{"description":"Authenticated.","content":{"application/json":{"schema":{"type":"object"},"example":{"ok":true,"user_id":"00000000-0000-0000-0000-000000000000","plan":"free","scope_used":"read:projects"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:projects"]}],"x-citare-scope":"read:projects"}},"/api/v1/account/me":{"get":{"operationId":"getMe","summary":"Authenticated user + plan + project memberships","description":"Identity for the bearer token: user id, email, name, resolved plan\n(highest across all the user's projects), the calling key's metadata,\nand the list of projects the user is a member of with role.\n\nUse this on first API call to discover available project ids.","tags":["account"],"responses":{"200":{"description":"Account snapshot.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"user":{"id":"uuid","email":"me@example.com","name":null},"plan":"free","key":{"id":"uuid","label":"Looker","tail":"ab12","scopes":["read:projects"]},"projects":[{"id":"uuid","slug":"acme","name":"Acme","domain":"acme.com","tier":"pulse","role":"agency_admin"}]}}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:projects"]}],"x-citare-scope":"read:projects"}},"/api/v1/projects":{"get":{"operationId":"listProjects","summary":"List projects you have access to","description":"Every project the authed user is a member of, with role. Mirrors the dashboard's project switcher.","tags":["projects"],"responses":{"200":{"description":"Membership list.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":[{"id":"uuid","slug":"acme","name":"Acme","domain":"acme.com","tier":"pulse","role":"agency_admin","createdAt":"2026-05-11T00:00:00Z"}]}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:projects"]}],"x-citare-scope":"read:projects"},"post":{"operationId":"createProject","summary":"Create a project","description":"Creates a project and adds the caller as `agency_admin`. Slug auto-derived from name when omitted. Domain must be bare.","tags":["projects"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{"name":"Acme","slug":"acme","domain":"acme.com"}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"409":{"description":"Slug already taken."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:projects"]}],"x-citare-scope":"write:projects"}},"/api/v1/projects/{projectId}":{"get":{"operationId":"getProject","summary":"Project details by id or slug","description":"Single project with the caller's role. Returns 404 (not 403) when the user isn't a member — deliberately doesn't leak existence.","tags":["projects"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"200":{"description":"Project.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"id":"uuid","slug":"acme","name":"Acme","domain":"acme.com","tier":"pulse","role":"agency_admin"}}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:projects"]}],"x-citare-scope":"read:projects"},"patch":{"operationId":"updateProject","summary":"Update project metadata","description":"Admin only. Partial update of name + domain.","tags":["projects"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:projects"]}],"x-citare-scope":"write:projects"},"delete":{"operationId":"deleteProject","summary":"Delete a project + all its data","description":"Admin only. Cascades to audits, alerts, reports, integrations, etc. Irreversible.","tags":["projects"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:projects"]}],"x-citare-scope":"write:projects"}},"/api/v1/projects/{projectId}/audits":{"get":{"operationId":"listAudits","summary":"Audit history + latest result","description":"Latest completed audit (or null) + history. Failed runs filtered out\nby default; pass `?include_failed=true` to see them too.\n\n**Why filter:** the audit runner writes a row on every run, including\nfailures (status='failed' + score=0). Defaulting to completed-only\nmatches the dashboard's MetricsRow / Alerts / Report Builder reads.","tags":["audits"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"include_failed","in":"query","schema":{"type":"boolean","default":false},"description":"Include rows with `status='failed'`."},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"minimum":1,"maximum":100},"description":"History items to return (max 100)."}],"responses":{"200":{"description":"Audits.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"latest":{"id":"uuid","score":75,"status":"completed","capturedAt":"2026-05-17T02:00:00Z"},"history":[{"id":"uuid","score":75,"status":"completed","capturedAt":"2026-05-17T02:00:00Z"}]}}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:audits"]}],"x-citare-scope":"read:audits"}},"/api/v1/projects/{projectId}/keywords":{"get":{"operationId":"listKeywords","summary":"Tracked keywords for the project","description":"Keywords the user has subscribed to daily rank snapshots for. `lastPosition` + `lastUrl` are denormalized for the list view; full rank history lives in `seo_daily_metrics` and will be exposed via `?include_history=true` in v1.5.","tags":["keywords"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"200":{"description":"Tracked keywords.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:keywords"]}],"x-citare-scope":"read:keywords"},"post":{"operationId":"addKeyword","summary":"Add a tracked keyword","description":"Idempotent. Subscribes to daily SERP-rank snapshots. Defaults: locationCode=2356 (India), languageCode=en.","tags":["keywords"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{"keyword":"ai search","locationCode":2356,"languageCode":"en"}}}},"responses":{"201":{"description":"Tracking.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:keywords"]}],"x-citare-scope":"write:keywords"},"delete":{"operationId":"removeKeyword","summary":"Untrack a keyword","description":"Idempotent. Pass keyword + locationCode + languageCode via query string or JSON body.","tags":["keywords"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"keyword","in":"query","schema":{"type":"string"},"required":true},{"name":"locationCode","in":"query","schema":{"type":"integer","default":2356}},{"name":"languageCode","in":"query","schema":{"type":"string","default":"en"}}],"responses":{"204":{"description":"Removed."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:keywords"]}],"x-citare-scope":"write:keywords"}},"/api/v1/projects/{projectId}/backlinks":{"get":{"operationId":"getBacklinks","summary":"Cached backlinks summary","description":"DFS backlink summary for the project's domain. Cached for 24h in KV;\nto force a fresh pull (consumes DFS quota), POST `/refresh` with the\n`write:backlinks` scope — shipping Day 6+.\n\nReturns `null` when neither the cache nor DFS has been populated for\nthis domain yet.","tags":["backlinks"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"200":{"description":"Summary.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:backlinks"]}],"x-citare-scope":"read:backlinks"}},"/api/v1/projects/{projectId}/bot-analytics":{"get":{"operationId":"getBotAnalytics","summary":"Bot Analytics dashboard payload","description":"Headline counts + daily sparkline + by-bot table + by-path table + recent hits + property list in one round trip. Property rows omit raw key material (use `write:bot-analytics` to rotate or create).","tags":["bot-analytics"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"period","in":"query","schema":{"type":"string","enum":["7d","30d","90d"],"default":"30d"},"description":"Window for all aggregates."}],"responses":{"200":{"description":"Bot Analytics snapshot.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:bot-analytics"]}],"x-citare-scope":"read:bot-analytics"}},"/api/v1/projects/{projectId}/alerts":{"get":{"operationId":"getAlerts","summary":"Alert rules + recent fired events","description":"Rules the project has set up + recent fired events. Events are immutable (one row per fire); rules are mutable (create/update/delete with `write:alerts`, Day 6+).","tags":["alerts"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"event_limit","in":"query","schema":{"type":"integer","default":30,"minimum":1,"maximum":100},"description":"Recent events to return."}],"responses":{"200":{"description":"Alerts.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:alerts"]}],"x-citare-scope":"read:alerts"},"post":{"operationId":"createAlertRule","summary":"Create an alert rule","description":"Email-only delivery. Rules fire daily at 04:30 UTC via the detect-alerts cron. Recipients capped at 3.","tags":["alerts"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{"kind":"position_drop","recipients":["alerts@example.com"],"thresholdSpots":5,"minPreviousPosition":20}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:alerts"]}],"x-citare-scope":"write:alerts"}},"/api/v1/projects/{projectId}/reports":{"get":{"operationId":"getReports","summary":"Report templates + recent runs","description":"Templates the project has configured + runs (history). Each run with\na rendered PDF includes a `pdfUrl` pointing at our auth-gated proxy\n(`/api/reports/{runId}/pdf`) that re-checks project membership before\nstreaming the R2 object.\n\nThe PDF proxy works for both browser sessions and bearer-tokened API\ncallers — pass `Authorization: Bearer cit_api_...` on the proxy URL\nto fetch from a script.","tags":["reports"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"run_limit","in":"query","schema":{"type":"integer","default":30,"minimum":1,"maximum":100}}],"responses":{"200":{"description":"Reports.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:reports"]}],"x-citare-scope":"read:reports"}},"/api/v1/projects/{projectId}/competitive-analysis":{"get":{"operationId":"getCompetitiveAnalysis","summary":"Saved competitor sets for the project","description":"Lists the project's saved competitor sets (up to 5 domains per set). To run a fresh analysis (consumes DFS quota), POST with `write:competitive-analysis` — Day 6+.","tags":["competitive-analysis"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"200":{"description":"Competitor sets.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:competitive-analysis"]}],"x-citare-scope":"read:competitive-analysis"}},"/api/v1/projects/{projectId}/ai-search":{"get":{"operationId":"getAiSearchTraffic","summary":"AI-tool referral traffic (GA4-derived)","description":"30-day summary of human clicks from ChatGPT / Perplexity / Gemini / Claude / Copilot etc. through to the project's domain. `connected: false` when GA4 isn't connected for this project (no other fields populated).","tags":["ai-search"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"200":{"description":"AI search summary.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:ai-search"]}],"x-citare-scope":"read:ai-search"}},"/api/v1/projects/{projectId}/integrations":{"get":{"operationId":"getIntegrations","summary":"Connection status for inbound data integrations","description":"GSC / BWT / GA4 / DataForSEO / etc. — null when not connected. Originating a connection requires the browser-based OAuth flow; disconnect is a `write:integrations` POST endpoint shipping Day 6+.","tags":["integrations"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"200":{"description":"Integrations.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:integrations"]}],"x-citare-scope":"read:integrations"}},"/api/v1/projects/{projectId}/brand-radar":{"get":{"operationId":"getBrandRadar","summary":"Recent Brand Radar dispatch runs + dispatches","description":"Recent dispatch runs (Brand Radar's primary unit of work) with their per-run dispatched queries. KG read + aggregate analytics ship in v1.5; for v1 this is the 'show me recent activity' surface.","tags":["brand-radar"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10,"minimum":1,"maximum":50}}],"responses":{"200":{"description":"Brand Radar.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:brand-radar"]}],"x-citare-scope":"read:brand-radar"}},"/api/v1/projects/{projectId}/webhooks":{"get":{"operationId":"listWebhooks","summary":"List webhook endpoints","description":"Returns endpoints + their subscriptions + last-delivery status. Secret material (raw + encrypted) is never returned; rotation requires write:webhooks + POST /rotate-secret (v1.5).","tags":["webhooks"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"200":{"description":"Endpoints.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:webhooks"]}],"x-citare-scope":"read:webhooks"},"post":{"operationId":"createWebhook","summary":"Register a webhook endpoint","description":"Generates a signing secret server-side and returns it ONCE. Use it to\nverify HMAC-SHA256(`${t}.${body}`) against the `v1=` portion of the\n`X-Citare-Signature` header on incoming requests.","tags":["webhooks"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{"label":"Slack #alerts","url":"https://hooks.slack.com/services/T0/B0/abc","eventsSubscribed":["alert.fired","report.generated"]}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:webhooks"]}],"x-citare-scope":"write:webhooks"}},"/api/v1/projects/{projectId}/webhooks/{endpointId}/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"Recent delivery attempts for an endpoint","description":"Each row carries the event, response code, response body snippet, and the error message on failure. Useful for debugging 'why didn't my Slack channel get the alert'.","tags":["webhooks"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"Deliveries.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:webhooks"]}],"x-citare-scope":"read:webhooks"}},"/api/v1/projects/{projectId}/webhooks/{endpointId}":{"patch":{"operationId":"updateWebhook","summary":"Update a webhook endpoint","description":"Partial update. Pass `enabled: false` to pause without losing config or history.","tags":["webhooks"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:webhooks"]}],"x-citare-scope":"write:webhooks"},"delete":{"operationId":"deleteWebhook","summary":"Delete a webhook endpoint","description":"Endpoint + its delivery history removed. Cannot be undone.","tags":["webhooks"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"endpointId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:webhooks"]}],"x-citare-scope":"write:webhooks"}},"/api/v1/projects/{projectId}/audits/run":{"post":{"operationId":"runAudit","summary":"Kick off a site audit","description":"Long-running. Returns 202 with `auditId`; poll `/audits` to track status. `maxPages` 10-500 (default 50). `url` defaults to the project's domain root.","tags":["audits"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"},"example":{"url":"https://acme.com","maxPages":50}}}},"responses":{"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:audits"]}],"x-citare-scope":"write:audits"}},"/api/v1/projects/{projectId}/alerts/{ruleId}":{"patch":{"operationId":"updateAlertRule","summary":"Update an alert rule","description":"Partial update. Pass `enabled: false` to pause without losing config.","tags":["alerts"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"ruleId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:alerts"]}],"x-citare-scope":"write:alerts"},"delete":{"operationId":"deleteAlertRule","summary":"Delete an alert rule","description":"Fired-event history stays. Rule is gone.","tags":["alerts"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"ruleId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:alerts"]}],"x-citare-scope":"write:alerts"}},"/api/v1/projects/{projectId}/reports/templates":{"post":{"operationId":"createReportTemplate","summary":"Create a report template","description":"Widget keys must come from the registry. Recipients capped at 3. Schedule: daily / weekly (scheduleDay 0-6) / monthly (1-31).","tags":["reports"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:reports"]}],"x-citare-scope":"write:reports"}},"/api/v1/projects/{projectId}/reports/templates/{templateId}":{"patch":{"operationId":"updateReportTemplate","summary":"Update a report template","description":"Partial update of any template field.","tags":["reports"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"templateId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:reports"]}],"x-citare-scope":"write:reports"},"delete":{"operationId":"deleteReportTemplate","summary":"Delete a report template","description":"Past runs stay; template deleted.","tags":["reports"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"templateId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:reports"]}],"x-citare-scope":"write:reports"}},"/api/v1/projects/{projectId}/reports/templates/{templateId}/run":{"post":{"operationId":"runReportNow","summary":"Run a report immediately","description":"Composes HTML → PDF → R2 → email. Synchronous; can take 5-15s. Idempotent on `(template, ran_on)` — re-firing same day reuses the existing run.","tags":["reports"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"templateId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Run result.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:reports"]}],"x-citare-scope":"write:reports"}},"/api/v1/projects/{projectId}/bot-analytics/properties":{"post":{"operationId":"createBotProperty","summary":"Register a property for AI bot tracking","description":"Returns the raw ingest API key ONCE. Use this key with the V1-compatible `POST /api/crawler-logs/ingest` endpoint to send hits.","tags":["bot-analytics"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{"hostname":"acme.com","label":"production"}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"409":{"description":"Hostname already registered for this project."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:bot-analytics"]}],"x-citare-scope":"write:bot-analytics"}},"/api/v1/projects/{projectId}/bot-analytics/properties/{propertyId}":{"patch":{"operationId":"updateBotProperty","summary":"Toggle / rename a property","description":"Pass `enabled` and/or `label`. Hits arriving for a disabled property are rejected at the ingest endpoint.","tags":["bot-analytics"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:bot-analytics"]}],"x-citare-scope":"write:bot-analytics"},"delete":{"operationId":"deleteBotProperty","summary":"Delete a property","description":"Hit history for this property cascades; project-level aggregates remain.","tags":["bot-analytics"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:bot-analytics"]}],"x-citare-scope":"write:bot-analytics"}},"/api/v1/projects/{projectId}/bot-analytics/properties/{propertyId}/rotate-key":{"post":{"operationId":"rotateBotPropertyKey","summary":"Rotate a property's API key","description":"Old key stops working the instant the new one is generated. Returns the new raw key ONCE.","tags":["bot-analytics"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Rotated.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:bot-analytics"]}],"x-citare-scope":"write:bot-analytics"}},"/api/v1/projects/{projectId}/backlinks/refresh":{"post":{"operationId":"refreshBacklinks","summary":"Force a fresh DataForSEO backlinks pull","description":"Consumes DFS quota — counts against the daily $10 cap. Synchronous; returns the fresh summary.","tags":["backlinks"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"responses":{"200":{"description":"Fresh summary.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:backlinks"]}],"x-citare-scope":"write:backlinks"}},"/api/v1/projects/{projectId}/competitive-analysis/run":{"post":{"operationId":"runCompetitiveAnalysis","summary":"Run a competitive keyword-gap analysis","description":"Up to 5 competitor domains. 24h KV cache; pass `force: true` to bypass. Synchronous, typically 5-15s.","tags":["competitive-analysis"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{"competitorDomains":["competitor1.com","competitor2.com"],"force":false}}}},"responses":{"200":{"description":"Result.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:competitive-analysis"]}],"x-citare-scope":"write:competitive-analysis"}},"/api/v1/projects/{projectId}/batch-analysis/run":{"post":{"operationId":"runBatchAnalysis","summary":"Run a multi-domain batch analysis","description":"Up to 10 domains side-by-side. OPR + cached DFS lookups. Synchronous.","tags":["batch-analysis"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{"domains":["a.com","b.com","c.com"]}}}},"responses":{"200":{"description":"Result.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:batch-analysis"]}],"x-citare-scope":"write:batch-analysis"}},"/api/v1/projects/{projectId}/serp-overview/run":{"post":{"operationId":"runSerpOverview","summary":"Run a SERP overview for a keyword","description":"24h KV cache; pass `force: true` to bypass.","tags":["serp-overview"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{"keyword":"ai search intelligence","country":"in"}}}},"responses":{"200":{"description":"Result.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:serp-overview"]}],"x-citare-scope":"write:serp-overview"}},"/api/v1/projects/{projectId}/integrations/{kind}":{"delete":{"operationId":"disconnectIntegration","summary":"Disconnect an integration","description":"Removes the credential row for the integration. Initiating a connection requires the browser-based OAuth flow at the dashboard.","tags":["integrations"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project UUID or slug. Slugs are accepted for ergonomics; the API normalizes to the canonical UUID internally.","schema":{"type":"string"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string","enum":["gsc","bwt","ga4","dataforseo","openpagerank","scrapedo","serpapi"]}}],"responses":{"204":{"description":"Disconnected."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["write:integrations"]}],"x-citare-scope":"write:integrations"}},"/api/v1/account/audit-log":{"get":{"operationId":"getAuditLog","summary":"Your own API call history","description":"Every API call made with one of your keys lands here — successes\nAND failures. Cursor-paginated via `?before=<createdAt-iso>`.\n\nUseful for debugging an integration that's hitting 401/403/429 or\nconfirming an AI agent didn't do something unexpected.","tags":["account"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200}},{"name":"before","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO-8601 timestamp; return rows created strictly before."}],"responses":{"200":{"description":"Audit log page.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":[{"id":"uuid","method":"GET","path":"/api/v1/ping","scopeUsed":"read:projects","statusCode":"200","durationMs":"120","createdAt":"2026-05-18T07:00:00Z"}],"meta":{"cursor":"2026-05-18T06:59:00.000Z"}}}}},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."}},"security":[{"bearerAuth":["read:audit-log"]}],"x-citare-scope":"read:audit-log"}},"/api/v1/tools/ai-bot-ua-detector":{"post":{"operationId":"runAiBotUaDetector","summary":"Detect AI bot vs. real browser from a User-Agent string","description":"Pattern-matches the canonical AI-crawler list against newline-\nseparated User-Agent strings. Pure CPU, no outbound fetch, no\ncache.\n\nPOST `{ uas: \"<UA-1>\\n<UA-2>\\n…\" }` → per-UA detection result.\nPOST `{}` → returns the canonical bot reference table.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"uas":"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.0; +https://openai.com/gptbot)"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/ai-robots-checker":{"post":{"operationId":"runAiRobotsChecker","summary":"Check robots.txt allow/block for every AI crawler","description":"Fetches `robots.txt` from the URL's origin and runs deterministic\nrule evaluation per bot from the canonical list (GPTBot, ClaudeBot,\nPerplexityBot, OAI-SearchBot, Google-Extended, etc.). KV-cached 24h\nper origin.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"url":"https://example.com"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/sitemap-checker":{"post":{"operationId":"runSitemapChecker","summary":"Validate sitemap.xml structure + lastmod coverage","description":"Auto-detects the sitemap from robots.txt, parses XML, follows\nindex nesting, reports lastmod coverage + AI-readiness flags.\nKV-cached 24h per origin.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"url":"https://example.com"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/json-ld-inspector":{"post":{"operationId":"runJsonLdInspector","summary":"Inspect every JSON-LD block on a page","description":"Fetches the URL's HTML, extracts every JSON-LD block, and\nvalidates each against schema.org expected fields. KV-cached 24h\nper URL.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"url":"https://example.com"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/json-ld-generator":{"post":{"operationId":"runJsonLdGenerator","summary":"Generate paste-ready JSON-LD for a schema type","description":"Pure-CPU validator + serializer. Pass `{ form: <SchemaFormData> }`\nwhere SchemaFormData matches one of Organization / LocalBusiness /\nArticle / FAQPage. Returns the `<script>` tag string + validation\nissues. No cache.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"form":{"type":"Organization","name":"Example Corp","url":"https://example.com"}}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/llms-txt-generator":{"post":{"operationId":"runLlmsTxtGenerator","summary":"Generate a starter llms.txt from a description tree","description":"Pure-CPU validator + serializer following the llmstxt.org spec.\nPass `{ data: <LlmsTxtData> }` with title + summary + sections.\nReturns the rendered text + validation issues.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"title":"Example","summary":"An example site."}}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/robots-txt-generator":{"post":{"operationId":"runRobotsTxtGenerator","summary":"Generate a starter robots.txt with AI-friendly defaults","description":"Pure-CPU renderer. Pass `{ config: <RobotsTxtConfig> }` declaring\nwhich AI crawlers to allow + an optional sitemap URL + crawl\ndelay. Returns the rendered text.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"config":{"allowAi":true,"sitemapUrl":"https://example.com/sitemap.xml"}}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/brand-disambiguation":{"post":{"operationId":"runBrandDisambiguation","summary":"Wikidata + Wikipedia entity check for a brand name","description":"Searches Wikidata + Wikipedia for entities matching the brand\nname. Surfaces namesake collisions and recommends `sameAs` URLs\nfor AI grounding. KV-cached 24h per (brand, url).","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"brand":"Example Corp","url":"https://example.com"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/citation-scorer":{"post":{"operationId":"runCitationScorer","summary":"0-100 score for how AI-citable a page is","description":"Composite of 6 readiness checks (page HTML + robots.txt +\nsitemap + llms.txt + JSON-LD + optional brand disambiguation).\nUp to 6 outbound fetches; all parallel where independent.\nKV-cached 24h per (url, brand).","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"url":"https://example.com","brand":"Example Corp"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/free-backlink-checker":{"post":{"operationId":"runFreeBacklinkChecker","summary":"Top 20 backlinks by rank desc for any domain","description":"DataForSEO-backed. Returns 20 strongest backlinks (one per\nreferring domain) with anchor text, source page, rank, and\ndofollow/nofollow. KV-cached 24h per bare domain.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"url":"example.com"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/broken-link-checker":{"post":{"operationId":"runBrokenLinkChecker","summary":"Find 4xx pages that still receive inbound links","description":"DataForSEO-backed. Lists broken pages on the domain that have\nexternal backlinks pointing at them — reclaim with a 301 or page\nrestore. KV-cached 24h per host.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"url":"example.com"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/website-authority-checker":{"post":{"operationId":"runWebsiteAuthorityChecker","summary":"0-100 authority score (DR-equivalent) for any domain","description":"OpenPageRank-backed (free, unlimited). Returns authority score,\nPageRank, global rank, and a letter grade. KV-cached 24h per\nbare host.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"url":"example.com"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/keyword-generator":{"post":{"operationId":"runKeywordGenerator","summary":"50+ keywords + monthly volume from a seed term","description":"DataForSEO-backed. Returns 50 related keywords with monthly\nvolume, KD 0-100, CPC. KV-cached 24h per (seed, country).","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"seed":"ai search optimization","country":"us"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/keyword-difficulty-checker":{"post":{"operationId":"runKeywordDifficultyChecker","summary":"Score a single keyword's difficulty 0-100","description":"DataForSEO native KD. Returns score 0-100, volume, CPC,\ncompetition, search intent, 12-month volume history. KV-cached\n24h per (keyword, country).","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"keyword":"ai search intelligence","country":"us"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/keyword-rank-checker":{"post":{"operationId":"runKeywordRankChecker","summary":"Check a domain's live position for a keyword","description":"scrape.do primary + SerpAPI fallback. Returns the domain's top-10\nposition (or null) + the full top-10 for context. Subdomain\nmatching included. KV-cached 24h per (domain, keyword, country).","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"domain":"example.com","keyword":"ai search intelligence","country":"us"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/serp-checker":{"post":{"operationId":"runSerpChecker","summary":"Live top-10 Google organic results for a keyword","description":"scrape.do primary + SerpAPI fallback. Returns the top 10 with\npositions, titles, URLs. KV-cached 24h per (keyword, country).","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"keyword":"ai search intelligence","country":"us"}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}},"/api/v1/tools/serp-overview":{"post":{"operationId":"runSerpOverviewTool","summary":"Top 10 + per-URL authority + highlight your/competitor domains","description":"Live top 10 enriched with OpenPageRank authority on every\nranking domain. Optional `primaryDomain` + `highlightCompetitors`\nto flag rows in the result table. KV-cached 24h per (keyword,\ncountry) in the orchestrator; highlight is applied post-cache.","tags":["tools"],"requestBody":{"required":true,"description":"Tool-specific JSON body — see `example` for shape.","content":{"application/json":{"schema":{"type":"object"},"example":{"keyword":"ai search intelligence","country":"us","primaryDomain":"example.com","highlightCompetitors":["competitor.com"]}}}},"responses":{"200":{"description":"Tool result envelope `{ data: { result, cached } }`.","content":{"application/json":{"schema":{"type":"object"},"example":{"data":{"result":{},"cached":false}}}}},"400":{"description":"Invalid input (missing or malformed field)."},"401":{"description":"Missing or invalid bearer token."},"403":{"description":"Valid token but missing the required scope."},"404":{"description":"Project not found or you are not a member."},"429":{"description":"Rate limit exceeded; check `Retry-After`."},"502":{"description":"Upstream provider (DFS / SerpAPI / OPR) failed."},"503":{"description":"Upstream provider over quota or suspended."}},"security":[{"bearerAuth":["write:tools"]}],"x-citare-scope":"write:tools"}}}}