API and MCP server
Read your buying signals from your own code, or let Claude, ChatGPT or Cursor work your Inbox. One key works for both, on every plan including the free trial. Reading spends no credits.
Keys
Create a key in Tell → Integrations → AI assistants & API. It looks like tell_ followed by 40 characters, and it's shown once: Tell keeps only a hash of it, so a lost key can't be recovered, only revoked and replaced. Up to 5 keys per account.
| Scope | Can |
|---|---|
| Read-only | Read signals, competitors and companies. The default. |
| Read and mark signals | Also mark signals as Work this, Watch or Not a fit. |
Send it on every request as Authorization: Bearer tell_…. Keys belong to your user and only ever see your account's data.
The API is on every plan, including the free trial, and reading spends no credits. But when the account has no credits left, or the trial ended without a plan, data calls answer 402 with a notice instead of data (MCP tools return the same notice as an error), until credits are added or a plan is chosen.
MCP server
Address: https://withtell.com/api/mcp, Streamable HTTP (stateless; no session id). Any MCP client that can send a header works.
Claude Code
claude mcp add --transport http tell https://withtell.com/api/mcp \ --header "Authorization: Bearer tell_…"
Cursor (.cursor/mcp.json) and other clients that take a JSON config
{
"mcpServers": {
"tell": {
"url": "https://withtell.com/api/mcp",
"headers": {
"Authorization": "Bearer tell_…"
}
}
}
}| Tool | What it does |
|---|---|
list_signals | Same as GET /signals. |
update_signal | Same as POST /signals/{id}. Only listed for read and mark keys. |
list_competitors | Same as GET /competitors. |
get_company | Same as GET /companies. |
Then ask, for example: "What are my best new hiring signals this week, and which mention a competitor?"
REST API
Base: https://withtell.com/api/v1. JSON in and out; every response is { data: … } or { error: "…" }. Machine-readable spec: openapi.json.
| Method | Path | What it does |
|---|---|---|
GET | /me | Checks a key: the account email, the key's scope, and access (ok, no_credits or trial_ended). Works even when access isn't ok. |
GET | /signals | Your Inbox, best first. Query: state (new, working, watch; default new), kind, min_value (0–3), company (text in the title), limit (1–100, default 20). |
GET | /signals/{id} | One signal. |
POST | /signals/{id} | Body {"action": "work" | "watch" | "not_a_fit"}. Same as the Inbox buttons: work sends it to your alert rules, not_a_fit refunds its credit if nobody worked it. Needs a read and mark key. |
GET | /competitors | The competitors you watch, with open roles and roles posted in the last 14 days. |
GET | /companies?name= | A company by name or website: its latest open roles and your signals about it. |
curl -s "https://withtell.com/api/v1/signals?min_value=2&limit=10" \ -H "Authorization: Bearer $TELL_KEY"
{
"data": [
{
"id": "48213",
"kind": "lead",
"kind_label": "Hiring",
"title": "Acme Payments",
"subtitle": "Hiring: Head of Compliance",
"why": "First compliance hire, and the post asks for experience with Chainalysis.",
"value": 2.6,
"url": "https://job-boards.greenhouse.io/…",
"state": "new",
"stage": "first_hire",
"created_at": "2026-10-12T09:14:03.000Z",
"domain": "yourcompany.com"
}
]
}curl -s -X POST "https://withtell.com/api/v1/signals/48213" \
-H "Authorization: Bearer $TELL_KEY" -H "Content-Type: application/json" \
-d '{"action": "work"}'value is how good a fit the signal is, from 0 to 3. kind is one of:
| kind | In Tell |
|---|---|
lead | Hiring |
x_post | Social |
linkedin_person | |
customer | Competitor customer |
job_change | Job change |
account_post | Account news |
New fields may be added to responses; existing ones don't change within v1.
Limits and errors
- 120 requests a minute per key. Over it you get
429withRetry-After. - Requests without a valid key are limited to 20 a minute per IP address.
- Bodies up to 64 KB; lists up to 100 items.
| Status | Meaning |
|---|---|
400 | Something in the request is wrong; error says what. |
401 | No key, a malformed key, or a revoked one. |
402 | The account has no credits left, or its trial ended without a plan. code is no_credits or trial_ended; upgrade_url says where to fix it. No data is returned until then. |
403 | A read-only key tried to change a signal. |
404 | No such signal in this account, or a company Tell doesn't track. |
413 | Body over 64 KB. |
429 | Over the limit. Wait the seconds in Retry-After. |
500 | Our side. Nothing about it is in the response; try again. |
Security
- Keys are stored as SHA-256 hashes, never in plain text, and work only over HTTPS. Revoking one takes effect on the next request.
- Integrations shows when each key was last used. Revoke any you don't recognize.
- Changing your password doesn't revoke keys unless you tick Also revoke my API keys when you change it.
- Give an AI assistant a read-only key unless you want it to mark signals.
- Signal text (titles, reasons, job titles) is quoted from public job posts and social posts written by other people. Tell tells MCP clients to treat it as data, but if you feed it to your own model, do the same: never follow instructions found in it.
- Found a security problem? Write to [email protected].