{"openapi":"3.1.0","info":{"title":"Debriefing Read API","version":"1.0.0","summary":"Read competitors, signals, digests, and battlecards for one workspace.","description":"A read-only JSON API for one organization. Create an API key in Settings → Integrations.\nThe same key authenticates the MCP endpoint at `POST /mcp`.\n\nEvery request is scoped to the organization that owns the key. The free week that unlocks\nthe dashboard does not unlock this API. A paid subscription is required.\n\nBlank fields are omitted from response objects. Empty summary domains are omitted from a\ncompetitor dossier.\n\nEvery error is RFC 9457 problem details, sent as `application/problem+json`, with a\nmachine-readable `code` and a `hint`. See the `Problem` schema and\nhttps://debriefing.io/developers#errors.\n\nThis file is also served as JSON at `/openapi.json`.\n","contact":{"name":"Debriefing","url":"https://debriefing.io"}},"servers":[{"url":"https://debriefing.io","description":"Production"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"tags":[{"name":"Competitors","description":"Competitors this workspace tracks."},{"name":"Signals","description":"Evidence-backed competitor moves."},{"name":"Digests","description":"Generated digests for this workspace."},{"name":"Battlecards","description":"Generated battlecards for this workspace."}],"paths":{"/api/v1/competitors":{"get":{"tags":["Competitors"],"operationId":"listCompetitors","summary":"List tracked competitors","description":"Returns every competitor this workspace actively monitors, ordered by priority then\ntracked date. Paused, removed, and pending-approval links are left out. Not paginated.\n","responses":{"200":{"description":"The watchlist for this workspace.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CompetitorSummary"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/competitors/{id}":{"get":{"tags":["Competitors"],"operationId":"getCompetitor","summary":"Get a competitor dossier","description":"Returns the company record and the current intelligence reads for one competitor this\nworkspace tracks. Signals and the battlecard stay on their own routes; this response\nnames them under `links`.\n","parameters":[{"$ref":"#/components/parameters/CompetitorId"}],"responses":{"200":{"description":"The stored dossier for this competitor.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/CompetitorDetail"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/signals":{"get":{"tags":["Signals"],"operationId":"listSignals","summary":"List open signals","description":"Returns open signals for competitors this workspace tracks, newest first. Every signal\nincludes its evidence. Default page size is 50. Maximum page size is 50.\n","parameters":[{"name":"competitor_id","in":"query","schema":{"type":"integer"},"description":"Limit to one tracked competitor."},{"name":"severity","in":"query","schema":{"type":"string","enum":["low","medium","high"]}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Include signals whose first seen time is on or after this ISO 8601 time."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Case-insensitive match on title or summary."},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"}],"responses":{"200":{"description":"A page of open signals.","content":{"application/json":{"schema":{"type":"object","required":["data","page","per_page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Signal"}},"page":{"type":"integer","minimum":1},"per_page":{"type":"integer","minimum":1,"maximum":50}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/signals/{id}":{"get":{"tags":["Signals"],"operationId":"getSignal","summary":"Get one signal","description":"Returns one signal for a competitor this workspace tracks. Unlike the list, this route\ncan return a closed signal when you know the id.\n","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"One signal with its evidence.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Signal"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/digests":{"get":{"tags":["Digests"],"operationId":"listDigests","summary":"List generated digests","description":"Returns digests with status `generated`, newest coverage period first. Default page\nsize is 50. Maximum page size is 50.\n","parameters":[{"name":"type","in":"query","schema":{"type":"string"},"description":"Limit to one debrief type, for example `daily_digest` or `weekly_tldr`."},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"}],"responses":{"200":{"description":"A page of digests.","content":{"application/json":{"schema":{"type":"object","required":["data","page","per_page"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Digest"}},"page":{"type":"integer","minimum":1},"per_page":{"type":"integer","minimum":1,"maximum":50}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/digests/{id}":{"get":{"tags":["Digests"],"operationId":"getDigest","summary":"Get one digest","description":"Looks up a generated digest by slug first, then by id.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Digest slug or numeric id."}],"responses":{"200":{"description":"One digest.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Digest"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/battlecards":{"get":{"tags":["Battlecards"],"operationId":"listBattlecards","summary":"List generated battlecards","description":"Returns generated battlecards for this workspace, ordered by competitor id. Not paginated.","responses":{"200":{"description":"The battlecards for this workspace.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Battlecard"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/battlecards/{id}":{"get":{"tags":["Battlecards"],"operationId":"getBattlecard","summary":"Get one battlecard","description":"Looks up a generated battlecard by battlecard id first, then by competitor id.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"Battlecard id or competitor id."}],"responses":{"200":{"description":"One battlecard.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Battlecard"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"dbk_","description":"Send `Authorization: Bearer dbk_…`. The plain token is shown once when the key is\ncreated. Only a SHA-256 digest is stored.\n"},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Alternative to Bearer. Send the same `dbk_…` token."}},"parameters":{"CompetitorId":{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"Competitor id from the watchlist."},"Page":{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},"PerPage":{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":50}}},"responses":{"BadRequest":{"description":"A parameter is not valid. For example, `since` is not an ISO 8601 time.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://debriefing.io/developers#errors-invalid_request","title":"Invalid request","status":400,"detail":"since must be an ISO 8601 time.","code":"invalid_request","hint":"Correct the parameter that the detail names. Then send the request again.","instance":"/api/v1/signals","request_id":"5f1c2b7e-9a41-4c1e-8d0e-2b1f3a6c7d80","error":"since must be an ISO 8601 time."}}}},"Unauthorized":{"description":"Missing, wrong, or revoked API key.","headers":{"WWW-Authenticate":{"schema":{"type":"string"},"example":"Bearer realm=\"Debriefing API\""}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://debriefing.io/developers#errors-invalid_api_key","title":"API key missing or not valid","status":401,"detail":"A valid API key is required.","code":"invalid_api_key","hint":"Send a valid key as Authorization: Bearer dbk_… or as X-API-Key. A workspace admin creates keys in Organization settings, under Integrations.","instance":"/api/v1/competitors","request_id":"5f1c2b7e-9a41-4c1e-8d0e-2b1f3a6c7d80","error":"A valid API key is required."}}}},"PaymentRequired":{"description":"The key's organization does not have a paid subscription.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://debriefing.io/developers#errors-paid_plan_required","title":"Paid plan required","status":402,"detail":"Choose a paid plan to use this feature.","code":"paid_plan_required","hint":"Choose a paid plan for this workspace on /pricing. The free week does not include the API.","instance":"/api/v1/competitors","request_id":"5f1c2b7e-9a41-4c1e-8d0e-2b1f3a6c7d80","error":"Choose a paid plan to use this feature."}}}},"NotFound":{"description":"No matching record in this workspace.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://debriefing.io/developers#errors-not_found","title":"Not found","status":404,"detail":"No such competitor.","code":"not_found","hint":"Check the path and the id. The list routes, such as /api/v1/competitors, give the ids that this key can read.","instance":"/api/v1/competitors/999","request_id":"5f1c2b7e-9a41-4c1e-8d0e-2b1f3a6c7d80","error":"No such competitor."}}}},"TooManyRequests":{"description":"This address sent more than 600 requests in one minute.","headers":{"Retry-After":{"description":"Seconds to wait before the next request.","schema":{"type":"integer"},"example":60}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://debriefing.io/developers#errors-rate_limited","title":"Too many requests","status":429,"detail":"This address sent more than 600 requests in one minute.","code":"rate_limited","hint":"Wait for the number of seconds in the Retry-After header. Then send the request again.","instance":"/api/v1/signals","request_id":"5f1c2b7e-9a41-4c1e-8d0e-2b1f3a6c7d80","error":"This address sent more than 600 requests in one minute."}}}},"InternalError":{"description":"An error occurred on the server. The body holds no internal detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://debriefing.io/developers#errors-internal_error","title":"Internal error","status":500,"detail":"An error occurred on the server.","code":"internal_error","hint":"Send the request again later. If the error continues, email team@debriefing.io with the request_id.","instance":"/api/v1/signals","request_id":"5f1c2b7e-9a41-4c1e-8d0e-2b1f3a6c7d80","error":"An error occurred on the server."}}}}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem details, sent as `application/problem+json`. Every 4xx and 5xx\nresponse of the read API has this shape. Branch on `code`, not on `detail` or `title`.\nThe `type` URL points at the row for the code on /developers.\n","required":["type","title","status","detail","code","hint"],"properties":{"type":{"type":"string","format":"uri","description":"Documentation URL for this code, `https://debriefing.io/developers#errors-<code>`."},"title":{"type":"string","description":"Short summary of the code. The same for every problem with this code."},"status":{"type":"integer","description":"The HTTP status code."},"detail":{"type":"string","description":"What went wrong with this request."},"code":{"type":"string","description":"Machine-readable error code. Stable.","enum":["invalid_request","invalid_api_key","paid_plan_required","forbidden","not_found","unprocessable_content","rate_limited","internal_error"]},"hint":{"type":"string","description":"What the client can do next."},"instance":{"type":"string","description":"The request path."},"request_id":{"type":"string","description":"The request id. Send it to support when you report an error."},"error":{"type":"string","deprecated":true,"description":"The same text as `detail`. Kept for clients that read the old `{ \"error\" }` body."}}},"CompetitorSummary":{"type":"object","required":["id","name","watch"],"properties":{"id":{"type":"integer"},"name":{"type":"string"},"website_url":{"type":"string","format":"uri"},"category":{"type":"string"},"watch":{"type":"string","enum":["core","horizon"]},"tracked_since":{"type":"string","format":"date-time"},"url":{"type":"string","format":"uri","description":"Link to the competitor page in the app."}}},"CompetitorDetail":{"type":"object","required":["id","name","watch"],"description":"Company identity, workspace relationship, and current rolled-up reads. Internal fields\nsuch as Brandfetch ids, discovery source, feature aliases, pricing snapshot ids, funding\nsource counts, comparison scores, and team notes are not included.\n","properties":{"id":{"type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"website_url":{"type":"string","format":"uri"},"category":{"type":"string"},"industry":{"type":"string"},"company_type":{"type":"string"},"business_model":{"type":"string"},"company_size":{"type":"integer"},"founding_year":{"type":"integer"},"headquarters":{"type":"object","properties":{"city":{"type":"string"},"country":{"type":"string"}}},"target_customer":{"type":"string"},"ownership":{"type":"object","properties":{"type":{"type":"string"},"parent_company_name":{"type":"string"},"public":{"type":"boolean"},"ticker":{"type":"string"}}},"urls":{"type":"object","additionalProperties":{"type":"string","format":"uri"},"description":"Present keys may include `pricing`, `docs`, `changelog`, `careers`, `linkedin`,\n`github`, `x`, `youtube`, `facebook`, `instagram`, and `tiktok`.\n"},"watch":{"type":"string","enum":["core","horizon"]},"priority":{"type":"integer"},"tracked_since":{"type":"string","format":"date-time"},"workspace":{"type":"object","properties":{"relative_risk":{"type":"string"},"relative_opportunity":{"type":"string"},"icp_overlap":{"type":"object","additionalProperties":true}}},"reads":{"$ref":"#/components/schemas/CompetitorReads"},"freshness":{"type":"object","properties":{"state_updated_at":{"type":"string","format":"date-time"},"last_signal_at":{"type":"string","format":"date-time"},"last_snapshot_at":{"type":"string","format":"date-time"}}},"links":{"type":"object","properties":{"signals":{"type":"string","description":"Relative path to list signals for this competitor.","example":"/api/v1/signals?competitor_id=42"},"battlecard_id":{"type":"integer","description":"Generated battlecard id when one exists."},"url":{"type":"string","format":"uri","description":"Link to the competitor page in the app."}}}}},"CompetitorReads":{"type":"object","description":"Domain summaries from `competitor_state`. A domain appears only when something is\nstored. Nested empty values are pruned. Shapes follow the research rollups and may gain\nkeys over time.\n","properties":{"positioning":{"type":"string"},"product":{"type":"object","additionalProperties":true},"pricing":{"type":"object","additionalProperties":true},"ai":{"type":"object","additionalProperties":true},"hiring":{"type":"object","additionalProperties":true,"description":"Includes `estimated_headcount` when known."},"funding":{"type":"object","additionalProperties":true,"description":"Includes `estimated_revenue_text` and `ownership_summary` when known."},"traffic":{"type":"object","additionalProperties":true},"market":{"type":"object","additionalProperties":true},"regulation":{"type":"object","additionalProperties":true},"tech_stack":{"type":"object","additionalProperties":true},"integrations":{"type":"object","additionalProperties":true},"release_cadence":{"type":"object","additionalProperties":true},"fortnight":{"type":"object","properties":{"written_at":{"type":"string","format":"date-time"},"sentences":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}},"Signal":{"type":"object","required":["id","title","evidence","url"],"properties":{"id":{"type":"integer"},"competitor_id":{"type":"integer"},"competitor_name":{"type":"string"},"title":{"type":"string"},"summary":{"type":"string"},"category":{"type":"string"},"type":{"type":"string"},"severity":{"type":"string","enum":["low","medium","high"]},"status":{"type":"string"},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"},"confidence":{"type":"number"},"topics":{"type":"array","items":{"type":"string"}},"evidence":{"type":"array","items":{"$ref":"#/components/schemas/EvidenceItem"}},"url":{"type":"string","format":"uri","description":"Link to the signal page in the app."}}},"EvidenceItem":{"type":"object","properties":{"text":{"type":"string"},"source_title":{"type":"string"},"source_url":{"type":"string","format":"uri"},"observed_at":{"type":"string","format":"date-time"}}},"Digest":{"type":"object","required":["id","type","status","url"],"properties":{"id":{"type":"integer"},"slug":{"type":"string"},"type":{"type":"string","description":"Debrief type, for example `daily_digest` or `weekly_tldr`."},"status":{"type":"string","example":"generated"},"title":{"type":"string"},"headline":{"type":"string"},"tldr":{"type":"string"},"what_to_watch":{"type":"string"},"coverage_period_start":{"type":"string","format":"date-time"},"coverage_period_end":{"type":"string","format":"date-time"},"generated_at":{"type":"string","format":"date-time"},"items":{"type":"array","items":{"type":"object","additionalProperties":true}},"signal_ids":{"type":"array","items":{"type":"integer"}},"markdown":{"type":"string"},"url":{"type":"string","format":"uri","description":"Link to the digest page in the app."}}},"Battlecard":{"type":"object","required":["id","competitor_id","status","url"],"properties":{"id":{"type":"integer"},"competitor_id":{"type":"integer"},"competitor_name":{"type":"string"},"status":{"type":"string","example":"generated"},"generated_at":{"type":"string","format":"date-time"},"sections":{"type":"object","additionalProperties":true},"evidence":{"type":"object","additionalProperties":true},"url":{"type":"string","format":"uri","description":"Link to the battlecard page in the app."}}}}}}