Developers

Read one workspace from your own tools. Create the key in Settings, then Integrations. The token is shown once. A paid plan is required. Use the API tab for HTTP, or the MCP tab for Claude and Cursor.

Get an API key

The read API needs a key. The MCP server takes the same key, or an OAuth sign-in from Claude and ChatGPT. A paid plan is required.

  1. Sign in to your workspace.
  2. Open Organization settings, then Integrations.
  3. Under API keys and MCP, name a key and click Create key.
  4. Copy the token from the notice. It starts with dbk_ and is shown once.
  5. Send it as Authorization: Bearer dbk_… or as X-API-Key.

Revoke a key from the same list when you need to rotate it. A missing or revoked key returns 401. A free workspace returns 402.

Authentication

Send the key as Authorization: Bearer dbk_… or as X-API-Key. Blank fields are omitted from every response.

GET /api/v1/competitors
Authorization: Bearer dbk_…

GET /api/v1/competitors

List tracked competitors

Every competitor this workspace actively monitors. Paused, removed, and pending links are left out. Not paginated.

Request

GET /api/v1/competitors
Authorization: Bearer dbk_…

Response

{
  "data": [
    {
      "id": 42,
      "name": "Acme Analytics",
      "website_url": "https://acme.example",
      "category": "Analytics",
      "watch": "core",
      "tracked_since": "2026-01-12T09:00:00Z",
      "url": "https://debriefing.io/competitors/42"
    },
    {
      "id": 57,
      "name": "Northwind AI",
      "website_url": "https://northwind.example",
      "category": "AI",
      "watch": "horizon",
      "tracked_since": "2026-03-02T14:30:00Z",
      "url": "https://debriefing.io/competitors/57"
    }
  ]
}

GET /api/v1/competitors/:id

Get a competitor dossier

Company record and current reads for one tracked competitor. Signals and the battlecard stay on their own routes.

Parameters

  • id path · required

    Competitor id from the watchlist.

Request

GET /api/v1/competitors/42
Authorization: Bearer dbk_…

Response

{
  "data": {
    "id": 42,
    "name": "Acme Analytics",
    "description": "Product analytics for B2B SaaS teams.",
    "website_url": "https://acme.example",
    "category": "Analytics",
    "industry": "Software",
    "company_type": "private",
    "business_model": "subscription",
    "company_size": 120,
    "founding_year": 2018,
    "headquarters": {
      "city": "San Francisco",
      "country": "US"
    },
    "target_customer": "B2B SaaS product teams",
    "ownership": {
      "type": "private",
      "public": false
    },
    "urls": {
      "pricing": "https://acme.example/pricing",
      "docs": "https://docs.acme.example",
      "linkedin": "https://www.linkedin.com/company/acme"
    },
    "watch": "core",
    "priority": 1,
    "tracked_since": "2026-01-12T09:00:00Z",
    "workspace": {
      "relative_risk": "medium",
      "relative_opportunity": "high",
      "icp_overlap": {
        "score": "high",
        "notes": "Same ICP in mid-market SaaS."
      }
    },
    "reads": {
      "positioning": "Product analytics for growth and product teams.",
      "pricing": {
        "plans": [
          {
            "name": "Pro",
            "price": "$99/mo"
          }
        ],
        "recent_changes": []
      },
      "funding": {
        "total_raised_text": "$45M",
        "last_round": "Series B",
        "estimated_revenue_text": "$8M–$12M ARR"
      },
      "traffic": {
        "monthly_visits": 180000,
        "trend": "up"
      },
      "fortnight": {
        "written_at": "2026-09-20T08:00:00Z",
        "sentences": [
          {
            "text": "Acme raised pricing on the Pro plan.",
            "kind": "pricing"
          }
        ]
      }
    },
    "freshness": {
      "state_updated_at": "2026-09-22T11:00:00Z",
      "last_signal_at": "2026-09-21T16:40:00Z",
      "last_snapshot_at": "2026-09-22T10:55:00Z"
    },
    "links": {
      "signals": "/api/v1/signals?competitor_id=42",
      "battlecard_id": 9,
      "url": "https://debriefing.io/competitors/42"
    }
  }
}

GET /api/v1/signals

List open signals

Open signals for tracked competitors, newest first. Each signal includes its evidence. Default page size is 50. Maximum is 50.

Parameters

  • competitor_id query

    Limit to one tracked competitor.

  • severity query

    low, medium, or high.

  • since query

    ISO 8601 time. First seen on or after this time.

  • q query

    Case-insensitive match on title or summary.

  • page query

    Page number. Default 1.

  • per_page query

    Page size. Default 50. Maximum 50.

Request

GET /api/v1/signals?severity=high&per_page=2
Authorization: Bearer dbk_…

Response

{
  "data": [
    {
      "id": 881,
      "competitor_id": 42,
      "competitor_name": "Acme Analytics",
      "title": "Acme raised Pro plan pricing",
      "summary": "The Pro plan moved from $79 to $99 per month on the public pricing page.",
      "category": "pricing",
      "type": "price_change",
      "severity": "high",
      "status": "open",
      "first_seen_at": "2026-09-21T16:40:00Z",
      "last_seen_at": "2026-09-21T16:40:00Z",
      "confidence": 0.92,
      "topics": [
        "pricing",
        "packaging"
      ],
      "evidence": [
        {
          "text": "Pro · $99 / month",
          "source_title": "Acme Pricing",
          "source_url": "https://acme.example/pricing",
          "observed_at": "2026-09-21T16:40:00Z"
        }
      ],
      "url": "https://debriefing.io/dashboard/signals/881"
    }
  ],
  "page": 1,
  "per_page": 2
}

GET /api/v1/signals/:id

Get one signal

One signal for a tracked competitor. Unlike the list, this route can return a closed signal when you know the id.

Parameters

  • id path · required

    Signal id.

Request

GET /api/v1/signals/881
Authorization: Bearer dbk_…

Response

{
  "data": {
    "id": 881,
    "competitor_id": 42,
    "competitor_name": "Acme Analytics",
    "title": "Acme raised Pro plan pricing",
    "summary": "The Pro plan moved from $79 to $99 per month on the public pricing page.",
    "category": "pricing",
    "type": "price_change",
    "severity": "high",
    "status": "open",
    "first_seen_at": "2026-09-21T16:40:00Z",
    "last_seen_at": "2026-09-21T16:40:00Z",
    "confidence": 0.92,
    "topics": [
      "pricing",
      "packaging"
    ],
    "evidence": [
      {
        "text": "Pro · $99 / month",
        "source_title": "Acme Pricing",
        "source_url": "https://acme.example/pricing",
        "observed_at": "2026-09-21T16:40:00Z"
      }
    ],
    "url": "https://debriefing.io/dashboard/signals/881"
  }
}

GET /api/v1/digests

List generated digests

Digests with status generated, newest coverage period first. Default page size is 50. Maximum is 50.

Parameters

  • type query

    Debrief type, for example daily_digest or weekly_tldr.

  • page query

    Page number. Default 1.

  • per_page query

    Page size. Default 50. Maximum 50.

Request

GET /api/v1/digests?type=daily_digest
Authorization: Bearer dbk_…

Response

{
  "data": [
    {
      "id": 310,
      "slug": "daily-2026-09-22",
      "type": "daily_digest",
      "status": "generated",
      "title": "Daily digest · 22 Sep 2026",
      "headline": "Acme raised Pro pricing. Northwind opened a EU careers page.",
      "tldr": "Two moves matter today: Acme pricing and Northwind hiring in Europe.",
      "what_to_watch": "Watch whether Acme changes packaging next.",
      "coverage_period_start": "2026-09-21T00:00:00Z",
      "coverage_period_end": "2026-09-22T00:00:00Z",
      "generated_at": "2026-09-22T07:15:00Z",
      "signal_ids": [
        881,
        902
      ],
      "url": "https://debriefing.io/dashboard/digests/daily-2026-09-22"
    }
  ],
  "page": 1,
  "per_page": 50
}

GET /api/v1/digests/:id

Get one digest

Looks up a generated digest by slug first, then by id.

Parameters

  • id path · required

    Digest slug or numeric id.

Request

GET /api/v1/digests/daily-2026-09-22
Authorization: Bearer dbk_…

Response

{
  "data": {
    "id": 310,
    "slug": "daily-2026-09-22",
    "type": "daily_digest",
    "status": "generated",
    "title": "Daily digest · 22 Sep 2026",
    "headline": "Acme raised Pro pricing. Northwind opened a EU careers page.",
    "tldr": "Two moves matter today: Acme pricing and Northwind hiring in Europe.",
    "what_to_watch": "Watch whether Acme changes packaging next.",
    "coverage_period_start": "2026-09-21T00:00:00Z",
    "coverage_period_end": "2026-09-22T00:00:00Z",
    "generated_at": "2026-09-22T07:15:00Z",
    "signal_ids": [
      881,
      902
    ],
    "url": "https://debriefing.io/dashboard/digests/daily-2026-09-22"
  }
}

GET /api/v1/battlecards

List generated battlecards

Generated battlecards for this workspace, ordered by competitor id. Not paginated.

Request

GET /api/v1/battlecards
Authorization: Bearer dbk_…

Response

{
  "data": [
    {
      "id": 9,
      "competitor_id": 42,
      "competitor_name": "Acme Analytics",
      "status": "generated",
      "generated_at": "2026-09-20T12:00:00Z",
      "sections": {
        "overview": "Acme sells product analytics to mid-market SaaS.",
        "strengths": [
          "Strong product analytics brand",
          "Clear Pro packaging"
        ],
        "weaknesses": [
          "Price rose without a feature add"
        ],
        "talk_tracks": [
          "Ask what they get for the new Pro price."
        ]
      },
      "url": "https://debriefing.io/dashboard/battlecards/9"
    }
  ]
}

GET /api/v1/battlecards/:id

Get one battlecard

Looks up a generated battlecard by battlecard id first, then by competitor id.

Parameters

  • id path · required

    Battlecard id or competitor id.

Request

GET /api/v1/battlecards/9
Authorization: Bearer dbk_…

Response

{
  "data": {
    "id": 9,
    "competitor_id": 42,
    "competitor_name": "Acme Analytics",
    "status": "generated",
    "generated_at": "2026-09-20T12:00:00Z",
    "sections": {
      "overview": "Acme sells product analytics to mid-market SaaS.",
      "strengths": [
        "Strong product analytics brand",
        "Clear Pro packaging"
      ],
      "weaknesses": [
        "Price rose without a feature add"
      ],
      "talk_tracks": [
        "Ask what they get for the new Pro price."
      ]
    },
    "url": "https://debriefing.io/dashboard/battlecards/9"
  }
}

Errors

Every error is RFC 9457 problem details, sent as application/problem+json. Branch on code. The hint tells you what to do next. The error field holds the same text as detail, for older clients.

A JSON request for a missing page anywhere on the site gets the same shape, with the code not_found. The OAuth endpoints send RFC 6749 errors. The MCP endpoint sends JSON-RPC errors.

Codes

  • invalid_request 400 · Invalid request

    Correct the parameter that the detail names. Then send the request again.

  • invalid_api_key 401 · API key missing or not valid

    Send a valid key as Authorization: Bearer dbk_… or as X-API-Key. A workspace admin creates keys in Organization settings, under Integrations.

  • paid_plan_required 402 · Paid plan required

    Choose a paid plan for this workspace on /pricing. The free week does not include the API.

  • forbidden 403 · Forbidden

    Use a key from the workspace that owns this record. The read API does not send this code now.

  • not_found 404 · Not found

    Check the path and the id. The list routes, such as /api/v1/competitors, give the ids that this key can read.

  • unprocessable_content 422 · Unprocessable content

    Correct the value that the detail names. Then send the request again. The read API does not send this code now.

  • rate_limited 429 · Too many requests

    Wait for the number of seconds in the Retry-After header. Then send the request again.

  • internal_error 500 · Internal error

    Send the request again later. If the error continues, email team@debriefing.io with the request_id.

Request

GET /api/v1/competitors/999
Authorization: Bearer dbk_…

Response

{
  "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."
}