{"openapi":"3.1.0","info":{"title":"Rivalize API","version":"1.0.0","description":"Competitive intelligence as an API. Track competitors, generate intelligence\nreports and company dossiers, read the cross-customer universe dataset, and\nreceive change webhooks.\n\n## Authentication\n\nREST API (`/api/v1/*`) requests authenticate with a Bearer API key:\n\n```\nAuthorization: Bearer rk_live_<random>\n```\n\nCreate a key via `POST /api/v1/keys`. Keys are never accepted in query strings.\n\n## Errors\n\nEvery `/api/v1/*` error returns a typed envelope with a stable `code`, a human\n`message`, the HTTP `status`, an optional field-level `details` array, and the\n`request_id` for that request:\n\n```json\n{ \"error\": { \"code\": \"NOT_FOUND\", \"message\": \"Competitor not found\", \"status\": 404, \"request_id\": \"...\" } }\n```\n\nThe same id is returned on **every** response (success and error) in the\n`x-request-id` header. Paste it into a support request and we can find the\nexact call."},"components":{"securitySchemes":{"session":{"type":"apiKey","in":"cookie","name":"better-auth.session_token","description":"BetterAuth session cookie — set automatically after sign-in via /api/auth/*"},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"rk_live_*","description":"API key — create via POST /api/v1/keys. Format: rk_live_<random>. All plans including free (rate-limited reads + add_competitor); webhooks and report triggers require a paid plan."}},"schemas":{}},"paths":{"/api/v1/keys":{"post":{"summary":"Create API key","tags":["API Keys"],"description":"Generate a new API key. The full key is returned ONCE in the response. Store it securely — it cannot be retrieved again.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["label"],"properties":{"label":{"type":"string","minLength":1,"maxLength":100,"description":"Human-readable label for the key"}}}}}},"security":[{"session":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"key":{"type":"string","description":"Full API key — shown only once"},"prefix":{"type":"string"},"createdAt":{"type":"string"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}},"get":{"summary":"List API keys","tags":["API Keys"],"description":"List all API keys for the authenticated user. Only prefixes are shown — full keys are never retrievable.","security":[{"session":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"prefix":{"type":"string"},"lastUsedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"revokedAt":{"type":"string","nullable":true}}}}}}}}}}}},"/api/v1/keys/{id}":{"delete":{"summary":"Revoke API key","tags":["API Keys"],"description":"Revoke an API key. The key will immediately stop working.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"session":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"revoked":{"type":"boolean"}}}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/me":{"get":{"summary":"Account info","tags":["API v1"],"description":"Returns account details, plan tier, credit usage, and rate limit status.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/projects":{"post":{"summary":"Create project","tags":["API v1"],"description":"Create a project. Provide a URL (we scrape to build a profile), or name + context (you describe your product). Optionally include competitor URLs to kick off analysis immediately.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Your product URL"},"name":{"type":"string","description":"Your product name"},"context":{"type":"string","description":"Product description, ICP, differentiators — used as the lens for analysis"},"competitors":{"type":"array","items":{"type":"string"},"maxItems":50,"description":"Competitor URLs to analyze. The number accepted is capped by your plan; exceeding it returns 409 COMPETITOR_LIMIT_REACHED."}}}}}},"security":[{"apiKey":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}},"get":{"summary":"List projects","tags":["API v1"],"description":"List all projects owned by the authenticated user.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/v1/projects/{id}":{"get":{"summary":"Get project","tags":["API v1"],"description":"Get a project by ID with intelligence summary and competitor list. By default only active competitors are returned; pass ?include_inactive=true to also include removed (soft-deleted) competitors.","parameters":[{"schema":{"type":"boolean"},"in":"query","name":"include_inactive","required":false,"description":"Include removed (soft-deleted) competitors in the list. Default false."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/projects/{id}/competitors":{"post":{"summary":"Add competitors","tags":["API v1"],"description":"Add competitor URLs to an existing project. Analysis kicks off immediately. A URL that cannot be counted as a rival (the company itself, its former or new name, its parent, a business it acquired, one no longer trading, a customer or partner on its own site) is not added and is listed in `data.not_counted` with the reason; when none can be added the reply is 400 NOT_A_RIVAL and nothing is started.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["urls"],"properties":{"urls":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":50,"description":"Competitor URLs to add and analyze. The number accepted is capped by your plan; exceeding it returns 409 COMPETITOR_LIMIT_REACHED."}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/projects/{id}/competitors/{competitorId}":{"delete":{"summary":"Remove competitor","tags":["API v1"],"description":"Deactivate a competitor in a project (soft-delete). The competitor is excluded from analysis and the default competitor list, and frees a slot against your plan limit. History is preserved. The next synthesis re-evaluates the remaining set.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"competitorId","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/projects/{id}/context":{"post":{"summary":"Upload context documents","tags":["API v1"],"description":"Upload 1-5 documents (text, markdown, or base64-encoded PDF) to enrich the project company profile. Documents are processed and discarded — only extracted fields persist.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["documents"],"properties":{"documents":{"type":"array","minItems":1,"maxItems":5,"items":{"type":"object","required":["content","type"],"properties":{"content":{"type":"string","minLength":30},"type":{"type":"string","enum":["text","markdown","pdf","docx"]},"label":{"type":"string","enum":["pitch-deck","prd","feature-list","pricing-rationale","company-description","investor-memo","other"]}}}}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/projects/{id}/freshness":{"get":{"summary":"Data freshness","tags":["API v1"],"description":"How current a project's data is: its latest readable report, and for every tracked competitor the date it was last actually observed and which kind of observation that was. Kinds: `report_run` (A report you can read analysed this competitor (its crawl of the site did not fail). Date: when the report was generated.); `site_crawl` (A stored crawl of the competitor's site. Date: when the crawl was captured.); `monitoring_page_capture` (A monitoring check fetched one of its pages (homepage, pricing, careers ...). Date: when the page was captured.); `search_check` (A monitoring search asked whether anything changed. It does not read the site, so it never sets last_observed_at.). A competitor no report run or monitoring capture has observed is `never_observed` with null dates. `competitors.updated_at` is never used as an observation date. Read-only; nothing is fetched.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/projects/{id}/evidence":{"get":{"summary":"Evidence for one subject","tags":["API v1"],"description":"The sources behind the facts for one subject of the project's latest readable report that analysed it: the home product when `competitor_id` is absent, else that competitor. Each source has its URL, what it supports (the fact, claim or section, as the served report states it, with withheld claims withheld) and `observed_at`, the date of the report run that read it; a press mention also has its own `published_at`. Read from the same served projection as the Brief and GET /v1/reports/:id/intelligence. A `competitor_id` that is not a competitor in this project is a 404 COMPETITOR_NOT_FOUND, the same whether it belongs to another account or does not exist. Read-only.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"query","name":"competitor_id","required":false,"description":"A competitor in this project; omit for the home product."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/competitors":{"get":{"summary":"List competitors","tags":["API v1"],"description":"List tracked competitors across all projects for the authenticated user, alphabetically, paged with `limit` (1-100, default 100) and `offset`. `pagination.total` is the full count, so a caller pages until offset + data.length reaches it. By default only active competitors are returned; pass include_inactive=true to also include removed (soft-deleted) competitors. A `project_id` that is not one of your projects is a 404 PROJECT_NOT_FOUND.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"query","name":"project_id","required":false,"description":"Filter by project ID"},{"schema":{"type":"boolean"},"in":"query","name":"include_inactive","required":false,"description":"Include removed (soft-deleted) competitors. Default false."},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":100},"in":"query","name":"limit","required":false,"description":"Page size, 1-100 (default 100)."},{"schema":{"type":"integer","minimum":0,"default":0},"in":"query","name":"offset","required":false,"description":"Rows to skip (default 0)."}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/competitors/{id}":{"get":{"summary":"Get competitor","tags":["API v1"],"description":"Get full competitor profile including intelligence data.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/competitors/{id}/intelligence":{"get":{"summary":"Competitor intelligence","tags":["API v1"],"description":"Competitor intelligence. `latest_snapshot` when a monitoring snapshot exists; otherwise `report` carries the competitor as its latest readable report analysed it (SWOT, strengths, weaknesses, key findings, tech stack, pricing tiers, social, reviews), with `source: \"report\"`, `source_report_id` and `source_report_date`. A field the report did not measure is null. Claims the report withholds as unverified are withheld here too. `source: \"none\"` when neither exists.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/competitors/{id}/changes":{"get":{"summary":"Competitor changes","tags":["API v1"],"description":"Recent changes for a competitor, filterable by type, priority, and date.","parameters":[{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severity filter"},{"schema":{"type":"string"},"in":"query","name":"type","required":false,"description":"Comma-separated change type filter"},{"schema":{"type":"string","enum":["critical","high","medium","low"]},"in":"query","name":"min_severity","required":false,"description":"Minimum significance level. Only returns changes at this level or above (critical,high,medium,low)"},{"schema":{"type":"string","enum":["date","significance"]},"in":"query","name":"sort","required":false,"description":"Sort order: \"date\" (default) or \"significance\" (by score desc then date)"},{"schema":{"type":"string"},"in":"query","name":"since","required":false,"description":"ISO date or relative (e.g. \"7d\", \"30d\")"},{"schema":{"type":"string"},"in":"query","name":"limit","required":false,"description":"Max results (default 50, max 100)"},{"schema":{"type":"string"},"in":"query","name":"offset","required":false,"description":"Pagination offset"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The collection is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The collection is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["data"]}}}},"400":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/competitors/{id}/momentum":{"get":{"summary":"Momentum score","tags":["API v1"],"description":"Momentum score (0-100) with signal breakdown: changelog, careers, social platforms, app store, pages scraped, customer proof.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/competitors/{id}/pricing":{"get":{"summary":"Pricing timeline","tags":["API v1"],"description":"Historical pricing data from snapshots. Shows pricing changes over time.","parameters":[{"schema":{"type":"string"},"in":"query","name":"limit","required":false,"description":"Number of snapshots (default 10)"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/competitors/{id}/seo":{"get":{"summary":"SEO metrics","tags":["API v1"],"description":"Domain authority, organic traffic, backlinks, referring domains, traffic value, and top ranking keywords for a competitor.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/competitors/{id}/battlecard":{"get":{"summary":"Competitor battlecard","tags":["API v1"],"description":"Cited per-competitor sales battlecard: Why We Win, Their Weaknesses, Objection Handlers, Discovery Questions. Every claim carries citations resolving to collected sources; claims that could not be cited were withheld. `source` is \"generated\" (the dashboard Battlecard tab) or \"report\" (the battlecard section of the competitor's latest report, with `report_id` and `report_date`, used when none was generated). `status` is read off the card's four sections: \"ready\" when every section carries a cited claim, \"partial\" when some do not, \"withheld\" when none does (`withheld_reason` says why); `sections_empty` names the sections with no claim, and `sections_locked` the ones among them that are locked until the user's company profile is complete (a generated card's Why We Win) rather than withheld. `status: \"not_generated\"` when no card can be served: none was generated, and the latest report either has no card for this competitor or has one in an older format that fails the citation contract (withheld from serving, never repaired). Pro plan required. Pass ?format=md for agent-ready Markdown.","parameters":[{"schema":{"type":"string","enum":["json","md"]},"in":"query","name":"format","required":false,"description":"md returns text/markdown for direct agent consumption"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. `status` is \"ready\" (every section carries a cited claim), \"partial\" (`sections_empty` names the empty ones), \"withheld\" (no section carries a claim; `withheld_reason` says why) or \"not_generated\" (no card can be served).","content":{"application/json":{"schema":{"description":"Success. `status` is \"ready\" (every section carries a cited claim), \"partial\" (`sections_empty` names the empty ones), \"withheld\" (no section carries a claim; `withheld_reason` says why) or \"not_generated\" (no card can be served).","type":"object","properties":{"data":{"type":"object","additionalProperties":true,"properties":{"status":{"type":"string","enum":["ready","partial","withheld","not_generated"]},"source":{"type":"string","enum":["generated","report"]},"sections_empty":{"type":"array","items":{"type":"string","enum":["whyWeWin","theirWeaknesses","objectionHandlers","discoveryQuestions"]},"description":"Sections with no cited claim, in card order. Absent for not_generated."},"sections_locked":{"type":"array","items":{"type":"string","enum":["whyWeWin","theirWeaknesses","objectionHandlers","discoveryQuestions"]},"description":"Of sections_empty, those locked until the company profile is complete (not withheld)."},"withheld_reason":{"type":"string","description":"Why every claim was withheld. Present only when status is \"withheld\"."},"markdown":{"type":"string"},"message":{"type":"string"}},"required":["status"]}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/universe/companies":{"get":{"summary":"List universe companies","tags":["API v1"],"description":"List live companies from the Rivalize universe with search plus category/layer filters. The universe is the cross-customer competitive-intelligence dataset.","parameters":[{"schema":{"type":"string"},"in":"query","name":"q","required":false,"description":"Search name, domain, or description (literal match; % and _ are not wildcards)"},{"schema":{"type":"string"},"in":"query","name":"category","required":false,"description":"Filter by category slug or display name, exact and case-insensitive (e.g. \"ai-infra\" or \"AI infrastructure\"); comma-separate for any-of"},{"schema":{"type":"string","enum":["identity","pricing","features","ads","social","reviews","funding_hiring","rankings"]},"in":"query","name":"layer","required":false,"description":"Require this intelligence layer to hold real data (e.g. ads: at least one stored creative). An unknown value is a 400 listing the valid layers."},{"schema":{"type":"string"},"in":"query","name":"limit","required":false,"description":"Page size (1-100, default 50)"},{"schema":{"type":"string"},"in":"query","name":"offset","required":false,"description":"Pagination offset (default 0)"}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","additionalProperties":true},"filters":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/universe/companies/{domain}":{"get":{"summary":"Get universe company","tags":["API v1"],"description":"Get the full universe company detail row for a domain, including all populated intelligence layers (identity, pricing, features, ads, social, reviews, funding/hiring, rankings).","parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"domain","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/universe/categories":{"get":{"summary":"List universe categories","tags":["API v1"],"description":"List the controlled category taxonomy with active-company and momentum-scored counts per category.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/v1/universe/categories/{category}/leaderboard":{"get":{"summary":"Category momentum leaderboard","tags":["API v1"],"description":"Ranked momentum scores for published companies in one category. Companies below the minimum-signal threshold are excluded (counted in excludedBelowThreshold), never ranked with fabricated zeros. Methodology: /methodology.","parameters":[{"schema":{"type":"string"},"in":"query","name":"limit","required":false,"description":"Rows to return (1-100, default 25)"},{"schema":{"type":"string","minLength":1},"in":"path","name":"category","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/reports":{"post":{"summary":"Trigger report","tags":["API v1"],"description":"Trigger a new competitive intelligence report. Returns 202 Accepted with a report ID for polling.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product_url","competitor_urls"],"properties":{"product_url":{"type":"string","format":"uri","description":"Your product URL"},"competitor_urls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":0,"maxItems":50,"description":"Competitor URLs to analyze, up to your plan's per-report competitor limit. Duplicates of the same company and your own product URL are dropped before anything is charged, and listed in `data.dropped`. PRD-26: pass `[]` to run self-report mode (product URL only, no comparison)."},"depth":{"type":"string","enum":["full","quick"],"description":"Report depth (default: full). `full` is full research, charged 15 credits per 5 competitors started. `quick` is the quick check, charged 1 credit per competitor (minimum 1): it reads public pages only and leaves search traffic, follower counts and the written note on each company blank. A quick check does not use up the monthly report cap."},"report_tier":{"type":"string","enum":["standard","pro"],"description":"Deprecated and ignored: every report triggered here runs at the depth in `depth`."}}}}}},"security":[{"apiKey":[]}],"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"job_id":{"type":"string"},"status_url":{"type":"string"},"message":{"type":"string"},"competitor_urls":{"type":"array","items":{"type":"string"},"description":"The competitor URLs the report will analyze, one per company."},"dropped":{"type":"array","description":"Entries removed before anything was charged: `duplicate` (same company as an earlier entry), `own_product` (your product URL), or `not_a_rival` (the company itself, a former or new name, its parent, a business it acquired, one no longer trading, or a customer or partner listed on its own site; `code` and `detail` say which and why).","items":{"type":"object","properties":{"url":{"type":"string"},"reason":{"type":"string","enum":["duplicate","own_product","not_a_rival"]},"code":{"type":"string"},"detail":{"type":"string"}}}}}}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}},"get":{"summary":"List reports","tags":["API v1"],"description":"List the reports this API key can read, newest first. Use a returned `id` with GET /v1/reports/:id/intelligence. `status` is `completed` for a finished competitive analysis, `no_competitors` for a finished report that analysed no competitor (a profile of the product alone, which names no threat), and `unavailable` for a report that cannot be read. `competitors_analyzed` is how many competitors the report analysed (null when not recorded).","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"query","name":"project_id","required":false,"description":"Only this project"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false},{"schema":{"type":"integer","minimum":0,"default":0},"in":"query","name":"offset","required":false}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. Reports in the `data` envelope, with `pagination`.","content":{"application/json":{"schema":{"description":"Success. Reports in the `data` envelope, with `pagination`.","type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/reports/{id}/intelligence":{"get":{"summary":"Report intelligence (Markdown)","tags":["API v1"],"description":"The report as an agent-ready Markdown document. Accepts the report id or its job id. Claims the fabrication scan flagged are replaced with \"[removed — unverified]\", as in the HTML report. `data.sections` lists the named sections this report has. With `section`, `data.markdown` is that one section (with the report's title and date) and `data.section` names it; without it, `data.markdown` is the whole document. Section names: tldr, biggest-threat, blind-spots, competitors, battlecards, actions, pricing, momentum, app-store, strengths, weaknesses, key-findings, creators, ads, tech-stack. A name that is not one of this report's sections is a 400 UNKNOWN_SECTION (or SECTION_NOT_IN_REPORT for a section this report does not have) whose message and `valid_sections` list the sections it does have.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":100},"in":"query","name":"section","required":false,"description":"One named section of the report: tldr, biggest-threat, blind-spots, competitors, battlecards, actions, pricing, momentum, app-store, strengths, weaknesses, key-findings, creators, ads, tech-stack. Case, spaces and underscores are ignored."},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"400":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/reports/{id}":{"get":{"summary":"Report status","tags":["API v1"],"description":"Get report status and data. Returns the report data when generation is complete. Poll this until `data.status` is `completed`, `no_competitors` or `no_rivals` (the run stopped before any research because none of its competitors could be counted as a rival; `message` names each one and why, and no credits were used); a report still in the human spot-check queue (PRD-305) reports as `processing`. Both are finished and carry `report_data`: `no_competitors` is a report that analysed no competitor (a profile of the product alone, which names no threat), and `competitors_analyzed` is how many competitors the report analysed.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/reports/{id}/download":{"get":{"summary":"Download report","tags":["API v1"],"description":"Download the full report as a self-contained HTML document (Content-Type: text/html).","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The report as a self-contained HTML document.","content":{"text/html":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/reports/{id}/pdf":{"get":{"summary":"Download report PDF","tags":["API v1"],"description":"Download the full report as a branded PDF document. The PDF preserves the dark theme, amber accents, and all formatting from the HTML report.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The report as a branded PDF document.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/projects/{id}/timeline":{"get":{"summary":"Get strategic timeline","tags":["API v1"],"description":"Structured five-lane competitor activity with moves and evidence URLs. Set format=markdown for agent-ready text.","parameters":[{"schema":{"type":"integer","enum":[30,90,180],"default":90},"in":"query","name":"days","required":false},{"schema":{"type":"string","format":"uuid"},"in":"query","name":"competitorId","required":false},{"schema":{"type":"string"},"in":"query","name":"lanes","required":false,"description":"Comma-separated lane ids to return (default: all). Lanes: pricing, product, people, funding, content-social."},{"schema":{"type":"string","enum":["json","markdown"],"default":"json"},"in":"query","name":"format","required":false},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The strategic timeline in the `data` envelope, or agent-ready Markdown with format=markdown.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}},"text/markdown":{"schema":{"type":"string"}}}},"400":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}},"402":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/dossier":{"post":{"summary":"Generate company dossier","tags":["API v1"],"description":"Generate a complete intelligence dossier on a single company. Returns 202 Accepted with a dossier ID for polling.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["company_url"],"properties":{"company_url":{"type":"string","format":"uri","description":"The company's primary website URL"},"company_name":{"type":"string","description":"Optional company name hint. Improves enrichment accuracy for reviews, Product Hunt, GitHub matching."},"depth":{"type":"string","enum":["standard","deep"],"description":"standard: web scrape + all enrichments (~90s, 3 credits). deep: adds Perplexity deep research (~3min, 10 credits)."},"format":{"type":"string","enum":["json","html"],"description":"json: structured profile + synthesis. html: self-contained styled dossier document."}}}}}},"security":[{"apiKey":[]}],"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"dossier_id":{"type":"string"},"status_url":{"type":"string"},"estimated_seconds":{"type":"number"},"message":{"type":"string"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/dossier/{jobId}":{"get":{"summary":"Dossier status","tags":["API v1"],"description":"Get dossier status and data. Returns the dossier profile data when generation is complete. Poll until `data.status` is `completed` or `failed`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"jobId","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/dossier/{jobId}/download":{"get":{"summary":"Download dossier HTML","tags":["API v1"],"description":"Download the dossier as a self-contained HTML document (Content-Type: text/html).","parameters":[{"schema":{"type":"string"},"in":"path","name":"jobId","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The dossier as a self-contained HTML document.","content":{"text/html":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/dossier/{jobId}/pdf":{"get":{"summary":"Download dossier PDF","tags":["API v1"],"description":"Download the company dossier as a branded PDF document. Preserves the classified-doc aesthetic, dark theme, and all formatting.","parameters":[{"schema":{"type":"string"},"in":"path","name":"jobId","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The dossier as a branded PDF document.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/projects/{id}/landscape":{"get":{"summary":"Get competitive landscape","tags":["API v1"],"description":"Current or stored weekly activity × importance positions. Set format=markdown for agent-ready text.","parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"in":"query","name":"week","required":false,"description":"Any day (YYYY-MM-DD) of the week wanted; it is read as that ISO week (Monday). The current week returns the current positions. A past week must be in `availableWeeks` (404 LANDSCAPE_WEEK_NOT_FOUND lists them). An impossible date is a 400."},{"schema":{"type":"string","enum":["json","markdown"],"default":"json"},"in":"query","name":"format","required":false},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The competitive landscape in the `data` envelope, or agent-ready Markdown with format=markdown.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}},"text/markdown":{"schema":{"type":"string"}}}},"400":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}},"402":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/webhooks":{"post":{"summary":"Register webhook","tags":["API v1 — Webhooks"],"description":"Register a webhook URL. Returns the signing secret ONCE — store it securely.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri","maxLength":2000},"events":{"type":"array","items":{"type":"string","enum":["change.detected","report.completed","momentum.shift","digest.weekly"]},"minItems":1},"min_priority":{"type":"string","enum":["high","medium","low"],"description":"Default: low"},"project_id":{"type":"string","format":"uuid","description":"Scope to a specific project"}}}}}},"security":[{"apiKey":[]}],"responses":{"201":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"400":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}},"409":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}},"get":{"summary":"List webhooks","tags":["API v1 — Webhooks"],"description":"List all registered webhooks. Signing secrets are NOT included.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The collection is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The collection is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["data"]}}}}}}},"/api/v1/webhooks/{id}":{"delete":{"summary":"Remove webhook","tags":["API v1 — Webhooks"],"description":"Permanently remove a webhook registration.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/webhooks/{id}/deliveries":{"get":{"summary":"Delivery log","tags":["API v1 — Webhooks"],"description":"View recent delivery attempts for a webhook.","parameters":[{"schema":{"type":"string"},"in":"query","name":"limit","required":false,"description":"Max results (default 20)"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The collection is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The collection is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}},"/api/v1/webhooks/{id}/test":{"post":{"summary":"Test webhook","tags":["API v1 — Webhooks"],"description":"Send a signed test payload to the webhook URL to verify it works. Always 200 — inspect `data.success` and `data.status_code` for the delivery outcome.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. The resource is returned in the `data` envelope.","content":{"application/json":{"schema":{"description":"Success. The resource is returned in the `data` envelope.","type":"object","properties":{"data":{"type":"object","additionalProperties":true}},"required":["data"]}}}},"404":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","content":{"application/json":{"schema":{"description":"Error. Carries a stable `code`, a human `message`, the HTTP `status`, and the `request_id` (also on the x-request-id response header).","type":"object","properties":{"error":{"type":"object","additionalProperties":true,"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"status":{"type":"integer","description":"HTTP status code."},"request_id":{"type":"string","description":"Correlation id for this request — also returned in the x-request-id response header. Include it in any support request."}}}}}}}}}}}},"servers":[{"url":"https://api.rivalize.ai","description":"This server"},{"url":"http://localhost:5800","description":"Local development"},{"url":"https://rivalize.ai","description":"Production"}],"tags":[{"name":"API Keys","description":"Create, list, and revoke API keys for REST API authentication"},{"name":"API v1","description":"REST API v1 — programmable competitive intelligence. Requires API key."},{"name":"API v1 — Webhooks","description":"Webhook registration, management, testing, and delivery logs via API key"}]}