# API reference

> Every call in the Tellfield API, and the MCP tool that does the same.

|  |  |
| --- | --- |
| API | `https://tellfield.com/api/v1` |
| MCP server | `https://tellfield.com/api/mcp`, streamable HTTP |
| Key | `Authorization: Bearer tf_…` |
| OpenAPI | [https://tellfield.com/api/v1/openapi.json](https://tellfield.com/api/v1/openapi.json) |

Bodies are JSON, sent with `Content-Type: application/json`. Every tool takes the same fields as its call: query, path and body together. Errors and limits are in the [guide for agents](https://tellfield.com/docs/agents.md#errors).

## MCP tools

| Tool | Scope | What it does |
| --- | --- | --- |
| `sign_up` | none | Sign your person up |
| `list_plans` | none | List the plans |
| `list_markets` | none | List the markets |
| `get_account` | `read` | Get the account |
| `list_reports` | `read` | List reports |
| `get_report` | `read` | Get a report |
| `get_watchlist` | `read` | Get the watchlist |
| `find_company` | `watchlist` | Find a company |
| `set_watchlist` | `watchlist` | Set the watchlist |
| `add_market` | `watchlist` | Add a market |
| `start_plan` | `billing` | Start or change a plan |
| `list_keys` | `keys` | List keys |
| `create_key` | `keys` | Make a key |
| `revoke_key` | `keys` | Revoke a key |

## No key

### Sign your person up

```http
POST /api/v1/signup
```

Asks for a Tellfield account for your person, or a key to the account they have. Returns an API key at once; it works once they confirm by the link we mail them (within 24 hours). Until then calls answer 401 with code `confirmation_pending`: poll `get_account` about once a minute. Send the market and plan to set up with it.

No key needed. MCP tool: `sign_up`. Answers 202 when it works.

| Body field | Type | Required | What it is |
| --- | --- | --- | --- |
| `email` | string | yes | Your person's work address. We mail them the link to confirm. |
| `agent_name` | string | yes | What your person calls you, shown in the mail and on the confirm page, e.g. "Research assistant". |
| `scopes` | list of `read`, `watchlist`, `billing`, `keys` |  | What the key may do. Leave empty for everything; read is always in. |
| `watchlist` | object |  | The market to set up once your person confirms. |
| `watchlist.market` | `outbound-sales-tools`, `compliance-automation-for-audits`, `other` | yes | One market slug from /api/v1/markets. "other" needs market_description. |
| `watchlist.market_description` | string |  | Your market in a few words, when market is "other". |
| `watchlist.brand` | object | yes | Your own brand. |
| `watchlist.brand.name` | string |  | The brand as people write it, e.g. "Northwind". Optional when website is given. |
| `watchlist.brand.website` | string |  | The brand's own site, e.g. "northwind.example". Preferred. |
| `watchlist.brand.linkedin` | string |  | Its LinkedIn company page address. Optional: we find it. |
| `watchlist.brand.x` | string |  | Its X handle. Optional: we find it. |
| `watchlist.brand.aliases` | list of string |  | Other names people use for it. |
| `watchlist.competitors` | list of object |  | Up to 10 competitors. |
| `watchlist.competitors[].name` | string |  | The brand as people write it, e.g. "Northwind". Optional when website is given. |
| `watchlist.competitors[].website` | string |  | The brand's own site, e.g. "northwind.example". Preferred. |
| `watchlist.competitors[].linkedin` | string |  | Its LinkedIn company page address. Optional: we find it. |
| `watchlist.competitors[].x` | string |  | Its X handle. Optional: we find it. |
| `watchlist.competitors[].aliases` | list of string |  | Other names people use for it. |
| `plan` | object |  | The plan to pick for that market. Paying stays with your person, by a checkout link. |
| `plan.tier` | `market`, `growth`, `full` | yes | A plan key from /api/v1/plans. |
| `plan.part` | `competitors`, `you` |  | For "growth" only: the one part it adds. |
| `plan.interval` | `month`, `year` |  |  |

### List the plans

```http
GET /api/v1/plans
```

The plans, their prices and what each adds. Each market has its own plan.

No key needed. MCP tool: `list_plans`. Answers 200 when it works.

### List the markets

```http
GET /api/v1/markets
```

The markets we read, by slug. Pick "other" and describe yours when none fits.

No key needed. MCP tool: `list_markets`. Answers 200 when it works.

## Read

### Get the account

```http
GET /api/v1/account
```

The team, what this key may do, and each market with its plan and where its brief stands.

Scope: `read`. MCP tool: `get_account`. Answers 200 when it works.

### List reports

```http
GET /api/v1/reports
```

The weeks that have a report for one market, newest first.

Scope: `read`. MCP tool: `list_reports`. Answers 200 when it works.

| Parameter | In | Type | Required | What it is |
| --- | --- | --- | --- | --- |
| `market` | query | integer |  | One of the team's market ids, from get_account or get_watchlist. Leave empty for the first market. |

### Get a report

```http
GET /api/v1/reports/{week}
```

One weekly report, whole or one section. Leave week empty (or "latest") for the latest.

Scope: `read`. MCP tool: `get_report`. Answers 200 when it works.

| Parameter | In | Type | Required | What it is |
| --- | --- | --- | --- | --- |
| `week` | path | string | yes | ISO week, e.g. 2026-W45, or "latest". |
| `section` | query | `summary`, `worked`, `competitors`, `you`, `changes`, `teams` |  | Only this part of the report. |
| `market` | query | integer |  | One of the team's market ids, from get_account or get_watchlist. Leave empty for the first market. |

### Get the watchlist

```http
GET /api/v1/watchlist
```

One market's own brand and competitors, and every market the team watches.

Scope: `read`. MCP tool: `get_watchlist`. Answers 200 when it works.

| Parameter | In | Type | Required | What it is |
| --- | --- | --- | --- | --- |
| `market` | query | integer |  | One of the team's market ids, from get_account or get_watchlist. Leave empty for the first market. |

## Watchlist

### Find a company

```http
GET /api/v1/company
```

Looks a company up by its website (best) or name: its name, site and our market for it, when we read one.

Scope: `watchlist`. MCP tool: `find_company`. Answers 200 when it works.

| Parameter | In | Type | Required | What it is |
| --- | --- | --- | --- | --- |
| `website` | query | string |  | e.g. "northwind.example" |
| `name` | query | string |  | e.g. "Northwind" |

### Set the watchlist

```http
PUT /api/v1/watchlist
```

Sets one market's market, own brand and competitors, replacing what was there. Website first: give each brand's site and we fill in the name and find its pages. With no market id it sets the first market, making it when the team has none. A market without a plan gets its first brief free.

Scope: `watchlist`. MCP tool: `set_watchlist`. Answers 200 when it works.

| Parameter | In | Type | Required | What it is |
| --- | --- | --- | --- | --- |
| `market` | query | integer |  | One of the team's market ids, from get_account or get_watchlist. Leave empty for the first market. |

| Body field | Type | Required | What it is |
| --- | --- | --- | --- |
| `market` | `outbound-sales-tools`, `compliance-automation-for-audits`, `other` | yes | One market slug from /api/v1/markets. "other" needs market_description. |
| `market_description` | string |  | Your market in a few words, when market is "other". |
| `brand` | object | yes | Your own brand. |
| `brand.name` | string |  | The brand as people write it, e.g. "Northwind". Optional when website is given. |
| `brand.website` | string |  | The brand's own site, e.g. "northwind.example". Preferred. |
| `brand.linkedin` | string |  | Its LinkedIn company page address. Optional: we find it. |
| `brand.x` | string |  | Its X handle. Optional: we find it. |
| `brand.aliases` | list of string |  | Other names people use for it. |
| `competitors` | list of object |  | Up to 10 competitors. |
| `competitors[].name` | string |  | The brand as people write it, e.g. "Northwind". Optional when website is given. |
| `competitors[].website` | string |  | The brand's own site, e.g. "northwind.example". Preferred. |
| `competitors[].linkedin` | string |  | Its LinkedIn company page address. Optional: we find it. |
| `competitors[].x` | string |  | Its X handle. Optional: we find it. |
| `competitors[].aliases` | list of string |  | Other names people use for it. |

### Add a market

```http
POST /api/v1/watchlist
```

Adds another market to watch, with its own brand and competitors (up to 5 markets). Each market has its own plan.

Scope: `watchlist`. MCP tool: `add_market`. Answers 201 when it works.

| Body field | Type | Required | What it is |
| --- | --- | --- | --- |
| `market` | `outbound-sales-tools`, `compliance-automation-for-audits`, `other` | yes | One market slug from /api/v1/markets. "other" needs market_description. |
| `market_description` | string |  | Your market in a few words, when market is "other". |
| `brand` | object | yes | Your own brand. |
| `brand.name` | string |  | The brand as people write it, e.g. "Northwind". Optional when website is given. |
| `brand.website` | string |  | The brand's own site, e.g. "northwind.example". Preferred. |
| `brand.linkedin` | string |  | Its LinkedIn company page address. Optional: we find it. |
| `brand.x` | string |  | Its X handle. Optional: we find it. |
| `brand.aliases` | list of string |  | Other names people use for it. |
| `competitors` | list of object |  | Up to 10 competitors. |
| `competitors[].name` | string |  | The brand as people write it, e.g. "Northwind". Optional when website is given. |
| `competitors[].website` | string |  | The brand's own site, e.g. "northwind.example". Preferred. |
| `competitors[].linkedin` | string |  | Its LinkedIn company page address. Optional: we find it. |
| `competitors[].x` | string |  | Its X handle. Optional: we find it. |
| `competitors[].aliases` | list of string |  | Other names people use for it. |

## Plans

### Start or change a plan

```http
POST /api/v1/checkout
```

Picks a plan for one market and returns a link for your person: Stripe Checkout to pay for a new plan, or a page to confirm a change to a plan they pay for. Nothing is charged until they pay or confirm there.

Scope: `billing`. MCP tool: `start_plan`. Answers 200 when it works.

| Body field | Type | Required | What it is |
| --- | --- | --- | --- |
| `tier` | `market`, `growth`, `full` | yes | A plan key from /api/v1/plans. |
| `part` | `competitors`, `you` |  | For "growth" only: the one part it adds. |
| `interval` | `month`, `year` |  |  |
| `market` | integer |  | One of the team's market ids, from get_account or get_watchlist. Leave empty for the first market. |

## Keys

### List keys

```http
GET /api/v1/keys
```

The team's keys that work: name, start of the key, scopes and when each was last used.

Scope: `keys`. MCP tool: `list_keys`. Answers 200 when it works.

### Make a key

```http
POST /api/v1/keys
```

Makes a key with no more scopes than this one. The key is shown once, in this answer.

Scope: `keys`. MCP tool: `create_key`. Answers 201 when it works.

| Body field | Type | Required | What it is |
| --- | --- | --- | --- |
| `name` | string | yes | Who will use it, e.g. "Weekly planner". |
| `scopes` | list of `read`, `watchlist`, `billing`, `keys` |  | Leave empty for read only. |

### Revoke a key

```http
DELETE /api/v1/keys/{id}
```

Stops one of the team's keys at once. Only a key with no more scopes than this one.

Scope: `keys`. MCP tool: `revoke_key`. Answers 200 when it works.

| Parameter | In | Type | Required | What it is |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | The key id, from list_keys. |
