Loading...
Developers · API
wrrk.ai is programmable in two places today. An MCP connector hands your CRM, WhatsApp, knowledge base, web search, workflows, and email to an MCP client. Signed webhooks start a workflow from any system you run. Everything below is read from the running implementation.
Overview
You do not need a new client library. One of these two surfaces is almost certainly the one you want.
POST /api/mcp/connect
Register wrrk.ai as a connector in Claude Desktop, Claude Code, or another MCP client, and work your CRM, WhatsApp, knowledge base, web search, workflows, and email from there.
POST /api/workflows/webhook/<orgId>
Start a published workflow from any system you run. Sign the request and wrrk.ai verifies it before anything executes.
What is not here yet
There is no published REST resource API for contacts, deals, or tasks, and no official SDK package. If you need one, tell us which resources you would call and what you are building.
Credentials
Every connector request carries a bearer credential in the Authorization header. Two kinds resolve to the same principal, so the rest of the behavior is identical.
What a key can do
A key can do everything its owner can. Write actions are limited by your role, and the role is read live, so a key whose owner is moved down to viewer stops being able to send WhatsApp.
Model Context Protocol
Point an MCP client at the connector and it discovers the tools your role allows, then calls them as you.
claude mcp add --transport http wrrk https://wrrk.ai/api/mcp/connect \
--header "Authorization: Bearer <your-key>"curl -X POST https://wrrk.ai/api/mcp/connect \
-H "Authorization: Bearer wrrk_mcp_<keyId>_<secret>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'| Method | What it returns |
|---|---|
| initialize | Handshake. Echoes the protocol version the client sent, and returns the server capabilities and serverInfo. Authentication is required on this call too. |
| ping | Returns an empty result object. |
| tools/list | Returns the tools this key is allowed to call. The list is filtered by the live role of the user the key belongs to. |
| tools/call | Runs one tool. Takes name and arguments, returns content plus isError. The role check runs again here, so a filtered-out tool cannot be called by name. |
| notifications/initialized | Acknowledged silently. No reply is sent, per JSON-RPC notification rules. |
| notifications/cancelled | Acknowledged silently. No reply is sent. |
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": { "tools": { "listChanged": false } },
"serverInfo": { "name": "wrrk", "version": "1.0.0" }
}
}{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "crm_create_contact",
"arguments": { "name": "Jane Smith", "email": "jane@example.com" }
}
}{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [{ "type": "text", "text": "Created contact Jane Smith" }],
"isError": false
}
}Catalog
Nineteen tools across five modules. tools/list returns only the ones the key owner's role allows, and tools/call checks the role again, so a tool that was filtered out cannot be called by name.
| Tool | What it does | Minimum role |
|---|---|---|
| crm_create_contactCRM | Create a new contact record with a name and optional email, phone, and company. | Agent |
| crm_update_contactCRM | Update fields on an existing contact by its id. | Agent |
| crm_enrich_contactCRM | Enrich a contact with additional company and role details from public information. | Agent |
| crm_create_dealCRM | Create a new deal, optionally linked to a contact, with an amount and stage. | Agent |
| crm_update_deal_stageCRM | Move a deal to a different stage in the sales pipeline. | Manager |
| crm_suggest_next_actionsCRM | Suggest recommended next actions for a contact based on recent activity. | Viewer |
| crm_analyze_pipelineCRM | Summarize sales pipeline metrics for a given time period. | Manager |
| whatsapp_send_messageWhatsApp | Send a WhatsApp message to a phone number. | Manager |
| whatsapp_suggest_replyWhatsApp | Draft a suggested reply for an ongoing WhatsApp conversation. | Agent |
| whatsapp_summarize_chatWhatsApp | Summarize a WhatsApp conversation into key points and open questions. | Agent |
| knowledge_searchKnowledge | Search the organization's knowledge base for relevant documents and answers. | Viewer |
| knowledge_scrape_urlKnowledge | Fetch and extract the readable text content of a web page. | Agent |
| web_searchWeb search | Search the public web and return titles, snippets, and links. | Viewer |
| workflow_listWorkflows & email | List automation workflows, optionally filtered by status or trigger. | Agent |
| workflow_executeWorkflows & email | Run an automation workflow with structured trigger data. | Agent |
| workflow_execution_statusWorkflows & email | Check the status of a workflow execution by its id. | Agent |
| email_list_threadsWorkflows & email | List recent email threads with basic metadata. | Agent |
| email_get_contextWorkflows & email | Retrieve the full context of an email thread or message. | Agent |
| email_analyzeWorkflows & email | Return a structured analysis of an email thread or message. | Agent |
Roles, low to high
Viewer, agent, manager, admin. Read-only lookups need viewer. Writes scoped to the caller need agent. Anything that sends on a channel or reads the pipeline needs manager.
Inbound
A workflow whose trigger is a webhook runs when you POST to your organization's webhook URL. The path segment is your organization id, URL encoded.
| Header | Required | Meaning |
|---|---|---|
| Content-Type | Yes | Must be application/json. Anything else is rejected with 415. |
| x-webhook-signature | If the workflow has a secret | HMAC-SHA256 of the raw request body, hex encoded, with or without a sha256= prefix. Compared in constant time. |
| x-webhook-path | No | Matched against the path configured on the workflow's webhook trigger. Defaults to /. Maximum 256 characters. |
| x-webhook-id | No | Delivery id used to deduplicate retries of the same delivery. x-webhook-delivery, x-idempotency-key and idempotency-key are accepted as aliases. |
curl -X POST https://wrrk.ai/api/workflows/webhook/<orgId> \
-H "Content-Type: application/json" \
-H "x-webhook-signature: sha256=<hex-digest>" \
-H "x-webhook-id: evt_8f21c4" \
-d '{"event":"order.paid","amount":4200}'import { createHmac } from "node:crypto";
// Sign the exact bytes you send. Serialize once, then reuse the string.
const body = JSON.stringify({ event: "order.paid", amount: 4200 });
const signature = createHmac("sha256", process.env.WRRK_WEBHOOK_SECRET)
.update(body)
.digest("hex");
// Header: x-webhook-signature: sha256=<signature>
// The bare hex digest, without the "sha256=" prefix, is also accepted.| Status | When |
|---|---|
| 200 | Accepted. The body carries triggered and executionIds, plus skippedValidation when a workflow's required fields were missing from the payload. |
| 200 (deduplicated) | A delivery id that was already processed. The body is { "triggered": 0, "deduplicated": true } and nothing runs a second time. |
| 400 | Missing or malformed orgId, invalid JSON body, or an invalid x-webhook-path header. |
| 401 | Every matching workflow requires a signature and none was provided or valid. |
| 404 | No active webhook workflows for the organization, or none whose configured path matches. |
| 415 | The request was not sent as application/json. |
| 429 | More than 120 requests in a minute for one organization. |
A payload that fails validation still returns 200
When a workflow declares required fields and your payload is missing one, the workflow does not run, the delivery is recorded on the workflow's failed events tab, and the response lists it under skippedValidation. You get a 200 so a configuration mismatch does not put your sender into a retry storm.
Contracts
Workflow webhooks are limited to 120 requests per minute per organization. Over that, the response is a 429 with a Retry-After header.
| Code | Message | When |
|---|---|---|
| -32700 | Parse error | The body was not valid JSON. HTTP 400. |
| -32001 | Unauthorized | Missing, unknown, or revoked bearer credential. HTTP 401. |
| -32000 | Method Not Allowed | A GET was made to the connector. There is no server-initiated stream. HTTP 405. |
| -32601 | Method not found | A JSON-RPC method the connector does not implement. |
| -32602 | Invalid params | tools/call was sent without a tool name. |
| -32603 | Internal error | Anything that failed server side. The detail is deliberately not returned. |
Errors are deliberately plain
The connector never returns internal error detail, provider names, or build information. If a call fails and the message is generic, that is the design, not a missing field.
Create a connector key in settings, point your MCP client at it, and the tools your AI Employee uses become the tools you call.