> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devtune.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# DevTune REST API Reference

> Integrate DevTune visibility metrics, citations, adoption data, and webhooks into CI/CD pipelines, BI tools, and dashboards with the public REST API.

DevTune provides a public REST API for integrating your AI search visibility data into CI/CD pipelines, BI tools, custom dashboards, and automated workflows. Most endpoints are read-focused analytics endpoints. API keys also power webhook management and non-interactive MCP clients, while MCP clients that support OAuth can use browser sign-in and project selection instead.

| Pillar | API path prefix | MCP tools |
| - | - | - |
| Visibility | `/api/v2/projects/{projectId}/visibility/` | `devtune_get_visibility_summary`, `devtune_get_visibility_response` |
| AI Traffic | `/api/v2/projects/{projectId}/traffic/` | `devtune_get_traffic_summary`, `devtune_get_traffic_platforms`, `devtune_get_ai_referrals`, `devtune_get_recent_answer_fetches` |
| Actions | `/api/v2/projects/{projectId}/actions/` | `devtune_get_actions` |
| Results | `/api/v2/projects/{projectId}/outcomes/` | `devtune_get_outcomes_ledger`, `devtune_get_content_changes`, `devtune_get_page_tracking` |

The Results API keeps the `/outcomes/` path and the `devtune_get_outcomes_ledger` tool name for compatibility.

## What You Can Do

With the DevTune API you can:

* Pull visibility metrics (share of voice, presence rate, brand mentions) into your reporting tools
* Monitor competitive positioning trends programmatically
* Feed citation data into your own analytics pipelines
* Track adoption metrics (npm downloads, GitHub stars) alongside search visibility
* Pull your actions: what DevTune suggests, what your team accepted, what is live and what was archived
* Trigger brief generation for an action DevTune suggested
* List, search, read, upload, and version project Library items
* Read and directly edit the Knowledge Profile, and review proposed profile changes
* Build custom alerting on top of DevTune data
* Connect AI coding agents (Codex, Claude, Cursor) via the MCP server for in-IDE access

## Requirements

* A **Plus plan or higher** with API access enabled
* An API key scoped to a specific project

## Available Endpoints

| Endpoint | Description |
| - | - |
| `GET /projects/{projectId}/prompt-set-analysis` | Read prompt-set analysis |
| `POST /projects/{projectId}/prompt-set-analysis` | Start or retry prompt-set analysis |
| `POST /projects/{projectId}/prompt-set-analysis/proposals` | Review a prompt-set proposal |
| `GET /projects/{projectId}/pages/metrics` | List unified page metrics |
| `GET /projects/{projectId}/pages/guard-rails` | List page guard-rail findings |
| `GET /projects/{projectId}/attributes` | List positioning statements |
| `GET /projects/{projectId}/attributes/match` | Get positioning match |
| `GET /projects/{projectId}/attributes/{attributeId}/answers` | List positioning match answers |
| `GET /projects/{projectId}/accuracy` | Get Accuracy |
| `GET /projects/{projectId}/accuracy/claims` | List Accuracy claims |
| `GET /projects/{projectId}/accuracy/claims/{groupId}` | Get Accuracy claim |
| `GET /projects/{projectId}/accuracy/contradictions` | List Accuracy contradictions |
| `GET /projects/{projectId}/accuracy/contradictions/{sentenceKey}` | Get Accuracy contradiction |
| `GET /projects/{projectId}/accuracy/decisions` | List Accuracy decisions |
| `GET /projects/{projectId}/audit/summary` | Get Audit summary |
| `GET /projects/{projectId}/audit/extraction` | Get stored extraction for a section finding |
| `POST /projects/{projectId}/audit/retrieval-intent` | Acknowledge or reconsider a retrieval restriction |
| `GET /projects/{projectId}/audit/findings` | List Audit findings |
| `GET /projects/{projectId}/audit/eligibility` | Get Google eligibility evidence |
| `GET /projects/{projectId}/outcomes/changes` | List detected content changes |
| `GET /projects/{projectId}/outcomes/page-tracking` | Read published-page tracking status |
| `POST /projects/{projectId}/outcomes/changes/attach` | Attach a published URL to a completed action |
| `POST /projects/{projectId}/outcomes/changes/claim` | Claim a content change |
| `POST /projects/{projectId}/outcomes/changes/unclaim` | Unclaim a content change |
| `GET /projects/{projectId}/outcomes/ledger` | List measured results |
| `GET /projects/{projectId}/traffic/recent-answer-fetches` | List recent answer fetches |
| `GET /projects/{projectId}/traffic/referrals` | List AI referrals |
| `GET /projects/{projectId}/traffic/404-demand` | Get 404 Demand |
| `GET /projects/{projectId}/traffic/direct-lift` | Get AI-correlated Direct lift |
| `GET /projects/{projectId}/agents` | List managed agents |
| `GET /projects/{projectId}/agents/runs` | List managed-agent runs |
| `GET /projects/{projectId}/agents/runs/{runId}` | Get a managed-agent run |
| `GET /projects/{projectId}/agents/dex/threads` | List Dex conversation threads |
| `POST /projects/{projectId}/agents/dex/threads` | Start a Dex conversation |
| `PATCH /projects/{projectId}/agents/dex/threads/{threadId}` | Rename a Dex conversation thread |
| `DELETE /projects/{projectId}/agents/dex/threads/{threadId}` | Delete your private Dex chat |
| `GET /projects/{projectId}/agents/dex/threads/{threadId}/messages` | Read Dex conversation events |
| `POST /projects/{projectId}/agents/dex/threads/{threadId}/messages` | Send a Dex conversation message |
| `GET /projects/{projectId}/agents/dex/threads/{threadId}/handoffs` | List pending Dex specialist handoffs |
| `POST /projects/{projectId}/agents/dex/threads/{threadId}/handoffs` | Confirm or cancel a Dex specialist handoff |
| `POST /projects/{projectId}/agents/dex/threads/{threadId}/memory` | Save or dismiss a Dex memory offer |
| `POST /projects/{projectId}/agents/{agentKey}/runs` | Trigger a managed-agent run |
| `GET /projects/{projectId}/visibility/responses` | List recent AI responses |
| `GET /projects/{projectId}/visibility/responses/{executionId}` | Get a retained AI response |
| `GET /projects/{projectId}/visibility/summary` | Get visibility summary metrics |
| `GET /projects/{projectId}/timeline/events` | Get project timeline events |
| `GET /projects/{projectId}/citations/stats` | Get aggregate citation statistics |
| `GET /projects/{projectId}/citations/top-domains` | Get top citation domains |
| `GET /projects/{projectId}/citations/top-pages` | Get top citation pages |
| `GET /projects/{projectId}/visibility/diff` | Get visibility diff |
| `GET /projects/{projectId}/content-gaps/list` | List content gaps |
| `GET /projects/{projectId}/competitive/position` | Get competitive positioning data |
| `GET /projects/{projectId}/adoption/metrics` | Get adoption metrics |
| `GET /projects/{projectId}/actions/from-prompt` | List actions for a prompt |
| `POST /projects/{projectId}/actions/from-prompt` | Create an action from a prompt |
| `GET /projects/{projectId}/actions/list` | List actions |
| `PATCH /projects/{projectId}/actions/{actionId}` | Update an action |
| `GET /projects/{projectId}/actions/{actionId}/events` | List action edits |
| `GET /projects/{projectId}/actions/{actionId}/brief` | Get action brief |
| `POST /projects/{projectId}/actions/{actionId}/brief` | Generate action brief |
| `GET /projects/{projectId}/usage` | Get project status and usage |
| `GET /projects/{projectId}/traffic/summary` | Get traffic summary |
| `GET /projects/{projectId}/traffic/search-rollups` | Get search rollup totals |
| `GET /projects/{projectId}/traffic/platforms` | Get traffic by platform |
| `GET /projects/{projectId}/intelligence/what-works` | Get what-works recommendations |
| `GET /projects/{projectId}/library` | List Library items |
| `POST /projects/{projectId}/library` | Upload a text document to the Library |
| `GET /projects/{projectId}/library/search` | Hybrid-search Library items |
| `GET /projects/{projectId}/library/{itemId}` | Read a Library item |
| `PATCH /projects/{projectId}/library/{itemId}` | Update Library grounding availability or version link |
| `GET /projects/{projectId}/knowledge` | Read the Knowledge Profile and proposal queue |
| `PATCH /projects/{projectId}/knowledge` | Update one Knowledge Profile field |
| `POST /projects/{projectId}/knowledge/proposals/{proposalId}` | Review a Knowledge Profile proposal |
| `GET /projects/{projectId}/webhooks` | List webhook subscriptions |
| `POST /projects/{projectId}/webhooks` | Create webhook subscription |
| `DELETE /projects/{projectId}/webhooks/{webhookId}` | Delete webhook subscription |
| `POST /projects/{projectId}/webhooks/{webhookId}/rotate-secret` | Rotate webhook signing secret |

The legacy intelligence anomaly endpoint and MCP tool are retired. For detected changes and events, use `GET /projects/{projectId}/timeline/events` over REST or the `devtune_get_timeline_events` MCP tool. Both require the `visibility.read` scope.

> **Tip:** Full request/response documentation for each endpoint is available in the **Endpoints** section of the API Reference sidebar, auto-generated from the OpenAPI specification.

The [webhooks guide](/api-reference/webhooks) documents real-time event notifications, and the [MCP server guide](/api-reference/mcp-server) covers agent access. The machine-readable specification is available at `GET /api/v2/openapi.json`.

The [Library guide](/library/overview) covers catalog and version behavior, while [Project context](/library/knowledge) explains which profile changes apply immediately and which require review.

### Actions Endpoint Notes

Every action is in one of four states:

* `suggested` — DevTune proposed it and nobody has decided
* `accepted` — your team wants it done
* `live` — the page is published; its measurement is running or complete
* `archived` — your team took it off the queue

Filter with `status`; without it the list returns every state, suggested actions first in rank order. `blocked` is `true` on accepted work your team has marked blocked. `detailLevel=summary` is default; `detailLevel=context` adds bounded why-now context, scores, metrics, top evidence, brief readiness, and follow-up links.

### Citations vs Mentions

Public citation endpoints are named `/citations/*` because they describe cited sources: pages, domains, classifications, positions, and evidence references. "Mentions" has a separate DevTune meaning: brand or product mentions inside AI answer text.

Public windowed REST endpoints use `windowDays` with endpoint-specific fixed rolling windows.

Citation top-list endpoints use cursor pagination. Pass `pageSize` up to `100`; when a response includes `nextCursor`, send it as `cursor` to retrieve the next page. Citation top-list endpoints support simple prefix matching on URL and/or canonical domain. Content gaps use `offset` and `limit`, with an optional `gapType` and display-label `search`. The public API does not support arbitrary sort columns, classification filters, broad content/source filters, or citation compare requests.

### Content gaps contract change

`GET /projects/{projectId}/content-gaps/list` now returns measured topic, source, and brand rollup facts over a fixed 30- or 90-day window. Each item includes its stable key and label, citation counts split into primary and competitor, average position, primary share when it can be calculated, and the rollup watermark date. `estimated` is always `false`.

Sources and brands you own are excluded, as are topics you hold at least half the citations on. Those are your presence rather than a gap, and they are absent from both the list and `totalCount`. A topic where others hold most of the citations is a gap even when you are cited on it too; read `share` to see how much of it is yours.

Every count on this resource is a citation. Content-gap rollups are built only from cited results, so the endpoint reports no mention counts.

This is a breaking change. The resource no longer returns `impactScore`, `confidenceScore`, `freshnessScore`, `actionabilityScore`, `signalStrength`, `signals`, `evidence`, `candidateKey`, `summary`, prompt counts, or third-party citation counts. Those pipeline-derived fields cannot be reproduced from the measurement rollups, so the API does not substitute estimates.

When the content-gap window has not been rolled up, `coverage.status` is `unavailable` and the list is empty. An available window still reports `availableDays` and `isPartial`, because a finalized rollup can cover fewer days than the window you asked for. Read the counts against `availableDays`, not against `windowDays`. `coverage.asOfDate` and the returned `window` both end on the rollup watermark, which trails today whenever the content-gap lane has not caught up.

### Response Caching

Read-focused analytics endpoints may return short-lived cached responses to reduce repeated polling overhead. Clients should respect the `Cache-Control` response header. If an integration needs to force a fresh read, send `Cache-Control: no-cache` with the request.

### Fixed Windows

* Visibility summaries, competitive position, citation stats, top pages, top domains, content gaps, traffic summary, traffic platforms, adoption metrics, what-works recommendations, and visibility diff accept `windowDays=30` or `90` and default to `30`.
* Page metrics, Audit summary, Audit eligibility, AI referrals, and AI-correlated Direct lift accept `windowDays=7`, `30`, or `90` and default to `30`.
* Results Ledger accepts `windowDays=7`, `30`, `90`, or `365` and defaults to `30`.
* Responses expose the resolved selection as `window` or `windowDays`, depending on the endpoint. Use the response schema for that endpoint instead of assuming one shared shape.

### Action Brief Write Operation

Use `POST /api/v2/projects/{projectId}/actions/{actionId}/brief` to generate or reuse an execution-ready action brief. Briefs exist for actions DevTune suggested, including ones created from a prompt; an action made with **Create Action** has no brief, and its ID returns `Action not found`.

This endpoint requires the `actions.write` API key scope. It does not create duplicate work for briefs that are already ready or generating. The response returns the current state:

* `ready`: a usable brief already exists
* `generating`: background generation is already running
* `queued`: DevTune queued generation and returned an `eventId`

After a `queued` or `generating` response, use `GET /api/v2/projects/{projectId}/actions/{actionId}/brief` to poll for `status: "ready"` and retrieve `briefMarkdown`.

You can optionally send `briefStyle` in the request body to ask for `best_fit` or a specific allowed content format. If project content preferences are enabled, the requested style must be allowed for the project.

## Getting Started

1. **[Create an API key](/api-reference/authentication)** from API Keys in the account sidebar
2. **Make your first request** using the key in the `Authorization` header
3. **Explore the endpoints** to find the data you need

For OAuth-based agent access, connect through the [MCP server](/api-reference/mcp-server) instead of creating an API key.

## Quick Example

```bash theme={null}
curl -H "Authorization: Bearer dtk_live_your_key_here" \
  "https://devtune.ai/api/v2/projects/YOUR_PROJECT_ID/visibility/summary"
```

```json theme={null}
{
  "data": {
    "totalExecutions": 142,
    "shareOfVoice": 23.5,
    "citationPresence": 68.2,
    "brandAwareness": 45.1,
    "avgPrimaryPosition": 2.3,
    "primaryCitations": 97,
    "competitorCitations": 215
  },
  "meta": {
    "timestamp": "2026-02-08T12:00:00.000Z",
    "projectId": "your-project-id"
  }
}
```

### Generate an Action Brief

```bash theme={null}
curl -X POST \
  -H "Authorization: Bearer dtk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"briefStyle":"best_fit"}' \
  "https://devtune.ai/api/v2/projects/YOUR_PROJECT_ID/actions/ACTION_ID/brief"
```

```json theme={null}
{
  "data": {
    "actionId": "ACTION_ID",
    "eventId": "evt_123",
    "message": "Brief generation started in the background.",
    "status": "queued",
    "success": true
  },
  "meta": {
    "timestamp": "2026-02-08T12:00:00.000Z",
    "projectId": "your-project-id"
  }
}
```

## Related Documentation

* **[Authentication](/api-reference/authentication)** - API key creation and usage
* **[Rate Limits](/api-reference/rate-limits)** - Request limits by plan tier
* **[Error Handling](/api-reference/errors)** - Error codes and troubleshooting

## Positioning match

Both positioning endpoints require `attributes.read` and access to positioning match. The list returns each statement's ID, kind, relevant intents, status and creation time. The match endpoint accepts `window=30` or `90`, defaulting to `30`, and optional `platform` and `intent` filters.

Match results include counts, brand IDs and names, daily counts, and `share_of_attribute` for the project's primary brand. Share divides that brand's count by all `brand_counts` plus `another_product`. The `several` and `nobody` counts are returned separately and excluded from the denominator. A denominator below ten returns a null share. Competitor changes and the series start date identify the comparison period.

Each statement also compares with the previous window of the same length, given as `prior_window`. `prior_status` is `comparable` when both windows measured the current competitor set and the previous one was scored on every day, platform and intent it had eligible answers for. `prior` then holds the previous window's totals and its `share_of_attribute`. Otherwise `prior_status` is `competitor_changed` or `incomplete`, and `prior` is null.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.