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

# Concepts

> The nouns of Jam's GEO API: workspaces, projects, prompts, scans, answers, the Plan, research and credits.

## Workspace and key

An API key belongs to one workspace. Possession of the key is access to that workspace: everything the key reads or changes is scoped to it. `GET /v1/me` names the workspace and the person who created the key.

A key acts with its creator's current role in the workspace. A member's key can do what a member can do in the dashboard; owner-only actions (managing billing) need the owner. If the creator leaves the workspace, their keys stop working. A key cannot create other keys, and can revoke only itself.

## Connecting a founder (agent connect)

An agent with no key starts a session with `POST /v1/agent-connect` and gives the human the link. The human signs in, and the agent polls until it receives a key for the workspace they approved. The agent can also do the whole setup: the site, the brand description, audiences, competitors, prompts and the plan (`onboarding`, with prices from `GET /v1/pricing`). The human then sees one review page, approves and starts the trial with one button, and the agent receives its key once the trial has started and the project exists. While it waits, the poll's `stage` says what is left: `awaiting_signin`, `awaiting_review`, `awaiting_payment` or `setting_up`. A founder whose workspace already has an active plan or a finished project approves for that workspace instead, and the agent's setup is not applied. While approval waits on payment, the poll returns a `resumeUrl` and a `humanMessage` to pass on. See the [quickstart](https://docs.spreadjam.com/agents/quickstart.md).

## Project

A project is one website Jam tracks, with its brand, competitors and prompts. A workspace usually has one. `GET /v1/projects` lists them. Every project-scoped route (analytics, answers, prompts, brand, the Plan, research, opportunities, content, destinations, scans and `/v1/me`) acts on the newest active project unless you send `X-Jam-Project: <projectId>`. Routes for one item by id (`/v1/actions/{actionId}`, `/v1/content/{contentId}`, ...) act on that item wherever it lives in the workspace. A header that is not a project id answers `400 invalid_request`; a project outside the workspace answers `404 not_found`. Over MCP, pass `projectId` to the tool instead.

## Prompts

A prompt is a question a buyer asks an AI assistant, like "best invoicing tool for freelancers". Jam asks each tracked prompt on every platform on every scan. Each prompt has a `topic`, an `intent` and a `persona` (`discoverer`, `buyer`, `evaluator`, `competitor`, `branded` or `control`, the same values `POST /v1/prompts` takes). They are set when the prompt is added; `PATCH /v1/prompts/{promptId}` changes only the wording, so to change a topic or persona, remove the prompt and add it again. Your plan sets how many prompts you can track; `GET /v1/prompts/cap` shows the cap and how much room is left. Add, edit, pause, replace and remove prompts under `/v1/prompts`, or ask Jam to suggest more with `POST /v1/prompts/suggestions`.

## Scans (visibility runs)

A scan asks every tracked prompt on every platform the plan covers: ChatGPT, Gemini, Perplexity, Google AI Mode, Google AI Overviews and Microsoft Copilot. Scans run on the plan's cadence (daily, every other day or weekly). `POST /v1/visibility-runs` starts one now; it answers `202` with a `runId` and the expected minutes, or `409` while a scan is already running.

A run fills in as Jam queues its questions, so `answers.total` grows during the first minutes. Read progress against `expectedTotal`, the prompt and platform pairs the run will ask, which is known up front; `queuing` is `true` until every question is queued. A platform that could not be reached shows its failed answers with a plain cause in `platforms[].errors`, and the project's `healthReasons` names a platform that failed most of the latest scan.

## Answers

Each scan stores the AI answer for every prompt and platform: whether your brand was mentioned or recommended, its position, the brands mentioned in order, and the URLs cited. `GET /v1/answers` lists them newest first; `GET /v1/prompts/{promptId}/answers` is one prompt's history.

## Analytics

The numbers on the dashboard: visibility score, mentions, citation share (a 0 to 100 percentage) and how they moved. `GET /v1/analytics/overview` for the summary, `/v1/analytics/prompts` per prompt, `/v1/analytics/metrics` for chart rows by family:

| `metric` | One row per |
| - | - |
| `visibility`, `competitors` | Day and brand: the visibility score over the window. |
| `citations` | Tracked brand (yours and competitors): its brand citation share, mentions and rank. |
| `sources` | Cited domain: how many cited URLs and answers it appears in, each as a count and a 0 to 100 share, with your own site marked `isOwned: true`. |
| `platforms` | AI platform: its scores, answer count and latest-scan failures. |
| `topics` | Topic and brand: visibility within the topic. |

`citations` answers "which brands get cited"; `sources` answers "which sites the AI assistants cite". Both use the same window (`rangeDays`: 7, 30 or 90).

## Brand and competitors

`GET /v1/brand` is how Jam describes your company and who it compares you with. Change the positioning with `PATCH /v1/brand` and the competitors under `/v1/brand/competitors`.

## Research

Research is what Jam learns about your market from the answers: which pages AI assistants trust, which sources cite competitors, and where your brand is missing. It feeds the Plan and the content opportunities.

## The Plan (actions)

The Plan is the ranked list of actions that should raise your visibility: pages to write or fix, sites to get listed on, people to pitch. `GET /v1/actions` lists them. Each action has a status:

| Status | Meaning |
| - | - |
| `suggested` | On the Plan, not started. |
| `in_progress` | Someone started it. |
| `sent` | Outreach went out; waiting on the third party. |
| `done` | Reported done (`POST /v1/actions/{actionId}/completion`). |
| `verified` / `unverified` | Jam checked whether it took effect. |
| `dismissed` | Taken off the Plan. |
| `superseded` | Research no longer proposes it. |

Transitions are safe to repeat: starting a started action, or dismissing a dismissed one, answers `200` with the status and records nothing. There is no undo for start (the dashboard has none either). To take a started action off the Plan, dismiss it; restoring it (`DELETE /v1/actions/{actionId}/dismissal`) puts it back as `suggested`.

## Content opportunities

Opportunities are pages worth writing. `GET /v1/opportunities` lists them and `GET /v1/opportunities/{id}/brief` returns the brief to write from. An agent can claim one, write it, and store the draft with `POST /v1/content`; Jam can also write it for you (`POST /v1/opportunities/{id}/plan-requests`). Publish to a connected GitHub repository with `PUT /v1/content/{id}/destinations/{destinationId}`.

A draft's text is at `currentRevision.article.bodyMarkdown` on `GET /v1/content/{id}` (the list view carries the title and state, not the body).

## Credits

Work Jam does for you (writing, research, outreach) costs credits. The plan grants an allowance that resets each period. `GET /v1/credits` shows the balance, allowance, reset time and recent charges; each charge has a plain `description` and `spend: false` when it is bookkeeping rather than work. A new account's first row is a `geo_allowance_expiry`: the free allowance replaced by the plan's credits, not a spend. A request that needs more credits than you have answers `402 insufficient_credits`.

> [!NOTE]
>
> When a project's first research run finishes, Jam drafts up to 3 new pages (the highest-ranked `new_page` actions) by itself, once per project, paid from the plan's included credits. They are written one after another, about 5 minutes each, so the third can show as queued for a while. Those actions go `in_progress` with actor `jam`, and `llm_query` charges appear in `recentCharges` without a request from you. The drafts stay in Jam until someone publishes them; nothing is sent to your site. Later research runs draft nothing on their own: more drafts wait for a request (`POST /v1/plan-batches` or a single action).

## Plan state and billing

When a plan ends the workspace becomes read-only: reads keep working and writes answer `402 plan_inactive` until the plan is resumed in the dashboard. Every `402` carries `resolveUrl`, the dashboard page where a person fixes it. `GET /v1/billing` returns the plan state, whether this key's creator can manage billing (`canManage`, owners only) and the links to manage billing, resume the plan, buy credits and change plan. The API never charges a card or opens a checkout itself: a person does that on those pages.

## Lists and pages

Lists that can grow are paged the same way: `limit` (1 to 100) and `cursor` in, and a `pageInfo` object out.

```json theme={}
"pageInfo": { "limit": 100, "hasNextPage": true, "nextCursor": "eyJhIjo...", "totalCount": 326 }
```

When `hasNextPage` is true, send `nextCursor` back as `cursor` with the same filters for the next page. `totalCount` counts every matching item across all pages. A `limit` outside 1 to 100, or a cursor the API did not hand out, is a `400`. This shape is used by `GET /v1/prompts`, `/v1/actions`, `/v1/opportunities`, `/v1/content`, `/v1/analytics/prompts`, `/v1/answers` and `/v1/visibility-runs`. Counts that summarise a list (`countsByStatus` on actions, `counts` on prompts) always cover every page.

Older fields stay for clients that already read them: `/v1/answers` also has `nextCursor` at the top level, and `/v1/visibility-runs` has `nextBefore` (and accepts `before` as well as `cursor`). `/v1/answers` leaves out `totalCount` when you filter by `competitor`, because counting would read every answer. Without `limit`, `GET /v1/prompts` also returns the older `tracked` and `archived` lists beside the first page, so send `limit`.

## Webhooks and notifications

Jam can POST its notifications (plan ready, PR opened, scan failed, ...) to your own URL. Manage the URLs with `/v1/webhooks` and choose which notifications go there with `/v1/notification-rules`. See [Webhooks](https://docs.spreadjam.com/agents/webhooks.md).

## Scored and unscored questions

A question that names your brand (by name, alias, domain or domain label, for example "spreadjam reviews") or names a tracked competitor ("X vs Y", "X alternatives") is tracked and its answers are kept, but it does not count toward visibility, mentions or citation share. Those rates only use questions a buyer asks without naming a vendor. `GET /v1/prompts` returns `branded`, `scored` and `unscoredReason` for each question, and `POST /v1/agent-connect` returns `warnings` for sent questions that will be unscored.

## Name collisions

If another product shares your brand name (Jam and jam.dev), an answer about the other product does not count as a mention of yours. The brand profile has a `notConfusedWith` list (set it in `onboarding.notConfusedWith` or with `PATCH /v1/brand`); research adds to it when answers cite a same-named product on another domain.


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