Get started
Coding agents and MCP
If you code with Claude Code, Codex or Cursor, these are the four steps for your agent to send and receive WhatsApp messages with heysteff, plus the commands to connect the MCP server. In the dashboard, Settings → Developers → Quick start gives you the same prompt with your workspace name and slug.
Four steps#
1. Create an API key#
In the dashboard, Settings → Developers → API Keys. Keep it in an environment variable: do not paste it into code or into your agent chat. Scopes are in Authentication.
export HEYSTEFF_API_KEY=sk_live_...2. Install the CLI and log in#
heysteff login asks for the key without showing it, checks it against the API and saves it on your machine. Every command is in CLI.
npm install -g @heysteff/cli
heysteff login3. Connect a channel#
In the dashboard, Settings → Channels: your WhatsApp number, Instagram, Messenger, SMS or email. API messages go out through it. No number yet? With an sk_test_ key you try the API through the shared heysteff number, only with the phones you join to the sandbox.
4. Give your agent the context#
Paste this prompt into your coding agent. It inspects your repository and proposes the smallest step to send and receive a real WhatsApp message. Replace <your workspace name> and <slug> with your workspace values.
You are going to integrate this project with heysteff, a messaging platform (WhatsApp, Instagram, Messenger, SMS and email) with a REST API.
Context
- heysteff workspace: <your workspace name> (slug: <slug>)
- API: https://app.heysteff.com/api/v1, with the header Authorization: Bearer $HEYSTEFF_API_KEY.
- The API key is already in the HEYSTEFF_API_KEY environment variable. Never write it in code, in a repository file or in this conversation.
- Docs for agents: https://app.heysteff.com/api/v1/llms-full.txt (read it before writing code), the spec at https://app.heysteff.com/api/v1/openapi.json and the rules in https://developers.heysteff.com/AGENTS.md.
- TypeScript SDK: @heysteff/sdk. CLI: @heysteff/cli (the heysteff command).
What I need
1. Inspect the repository: language, framework, how environment variables are handled and whether there is any messaging code already.
2. Propose the smallest step to send a real WhatsApp message and receive the reply in this project. Wait for my go-ahead before implementing it.
3. To send, use POST /v1/messages (in TypeScript, heysteff.messages.send) with an Idempotency-Key header.
4. To receive, create an endpoint for the message:received webhook: verify the X-Heysteff-Signature over the raw body, deduplicate by X-Heysteff-Delivery-Id and answer 2xx right away. The webhook secret goes in HEYSTEFF_WEBHOOK_SECRET.
5. To test the webhook locally, use heysteff webhooks trigger http://localhost:<port>/<path> --secret <secret>.
6. If the key starts with sk_test_, everything goes through the heysteff sandbox and you can only message the phones that joined the sandbox.
Do not invent endpoints or fields: if something is not in llms-full.txt, tell me.Connect your own AI#
To have your own model answer customers: the message:received webhook reaches your server, your model writes the reply and you send it with POST /v1/messages. When it does not know or should not continue, POST /v1/conversations/{id}/escalate hands the conversation to a person from the team, who answers from the heysteff inbox, and pauses the bot. The full flow is in Bring your own AI.
This prompt asks your agent to first ask what your business does, to test with your own conversation and not to reply to real customers without your permission:
I want to connect my own AI agent to heysteff so it answers my business customers on WhatsApp and the other connected channels. Act as my integration engineer and go step by step.
Context
- heysteff workspace: <your workspace name> (slug: <slug>)
- API: https://app.heysteff.com/api/v1, with the header Authorization: Bearer $HEYSTEFF_API_KEY.
- The API key is already in the HEYSTEFF_API_KEY environment variable. Never write it in code, in a repository file or in this conversation.
- Docs for agents: https://app.heysteff.com/api/v1/llms-full.txt (read it before writing code), the spec at https://app.heysteff.com/api/v1/openapi.json and the rules in https://developers.heysteff.com/AGENTS.md.
- TypeScript SDK: @heysteff/sdk. CLI: @heysteff/cli (the heysteff command).
Before writing code
1. Ask me what my business does, what the agent should handle on its own and when a person from the team has to step in.
2. Check access with heysteff whoami (or GET /v1/conversations?limit=1). Never ask me to paste an API key or a secret into this conversation: if one is missing, tell me how to set it in the environment variable.
3. Check whether a channel is already connected with heysteff conversations list --limit 5. If there is none, recommend connecting WhatsApp in the dashboard (Settings → Channels) or testing first with the sandbox and an sk_test_ key.
4. Inspect the repository and recommend the smallest setup. Wait for my go-ahead.
The integration
- An endpoint for the message:received webhook: verify X-Heysteff-Signature over the raw body, deduplicate by X-Heysteff-Delivery-Id, answer 2xx immediately and process in the background.
- The webhook already carries who to answer (channel, external_user_id and channel_connection_id) and bot_paused. When bot_paused is true, a person has the conversation: do not reply. Read the history with GET /v1/conversations/{id}/messages.
- Pass the history and my instructions to my model and reply with POST /v1/messages (heysteff.messages.send), with an Idempotency-Key derived from the received message so it never replies twice.
- The agent instructions live in a repository file, not inside the code: what the business does, the tone, what it can and cannot promise, and when to hand off to a person.
- Handoff to a person: when the agent does not know or should not continue, it tells the customer someone from the team will take over and calls POST /v1/conversations/{id}/escalate (heysteff.conversations.escalate) with the reason in reason. That pauses the bot, opens the case in the inbox and alerts my team; from then on events arrive with bot_paused set to true. When the team is done, the conversation comes back with POST /v1/conversations/{id}/bot and paused set to false, or with POST /v1/conversations/{id}/resolve. Do not keep that state on your side: read it with GET /v1/conversations/{id}. The key needs conversations:write.
- If the heysteff agent is on (Agent → Profile in the dashboard), turn it off before enabling yours, or both will reply.
Testing
- Test first with my own conversation: I message the number from my phone (or use heysteff webhooks trigger locally) and we review the reply.
- Do not reply to real customers without my explicit permission: keep replies limited to my test phone until I tell you to turn them on for everyone.
Do not invent endpoints or fields: if something is not in llms-full.txt, tell me.Claude Code plugin#
The heysteff plugin sets everything up at once: it registers the MCP server with the fixed address, adds the skills below, adds the /heysteff:setup command (MCP, CLI and API key without writing the key to any file) and, at the start of each session, runs heysteff whoami if you have the CLI, without showing the key. It also ships a safety rule: before sending anything to a real person, the agent confirms the recipient and the text with you.
/plugin marketplace add heysteff-com/agent-plugins
/plugin install heysteff@heysteffThen type /mcp, pick heysteff and authorize. The same repository has equivalents for Cursor (.cursor/mcp.json and the heysteff-safety.mdc rule) and for Codex (config.toml and AGENTS.md).
heysteff skills#
Three skills, each with its own SKILL.md and dependency-free scripts (Node 20+) that only use the v1 API. They read the key from HEYSTEFF_API_KEY, never print it, and the scripts that send anything do nothing without --confirm. They are written in Spanish; models read them fine in any language.
- heysteff-integrate: API key, sending on any channel with
POST /v1/messages, webhooks, customers and connection links. - heysteff-automate: API-triggered flows, campaigns (bulk sends) and WhatsApp templates.
- heysteff-observe: message status, webhook deliveries, retries, API logs and plan usage.
To install them in Claude Code, Codex, Cursor or another compatible agent:
npx skills add heysteff-com/agent-skillsThe general heysteff skill (v1 API, SDK, CLI, MCP, webhooks, sandbox and errors in one file) is still available. To install it for your user:
mkdir -p ~/.claude/skills/heysteff && curl -fsSL https://developers.heysteff.com/skills/heysteff/SKILL.md -o ~/.claude/skills/heysteff/SKILL.mdFor a single project, save it as .claude/skills/heysteff/SKILL.md inside the repository. In Cursor, Codex or another agent, add it as a rule or as project context (for example, link it from your AGENTS.md).
MCP server#
The MCP server lets your agent set up the workspace (agent, channels, flows, campaigns, inbox) from the chat. The address is the same for everyone: https://mcp.heysteff.com/mcp. It does not use API keys: you authorize with OAuth in the browser and pick the workspace on the authorization screen. The grant is bound to that workspace and does not work on another one; to use another, authorize again and pick it. Authorize with an account that has the Owner role. In developer workspaces the MCP is on by default; in the others, turn it on in Settings → MCP. Older addresses with ?tenant= keep working.
Claude Code#
Then, in Claude Code, type /mcp and pick heysteff to authorize. If you installed the plugin, the server is already registered.
claude mcp add --transport http heysteff "https://mcp.heysteff.com/mcp"Codex#
codex mcp login opens the browser to authorize.
codex mcp add heysteff --url "https://mcp.heysteff.com/mcp"
codex mcp login heysteffCursor#
Save the file at the project root (or in ~/.cursor/mcp.json for every project) and authorize from Cursor's MCP settings. Any other client that speaks MCP over HTTP uses the same address.
{
"mcpServers": {
"heysteff": {
"url": "https://mcp.heysteff.com/mcp"
}
}
}