leads.enrich
leads.enrich is dispatched on 2 endpoints. Which one runs depends on the URL you post to, not on the name.
run leads.enrich
Enrich one lead from a natural-language instruction.
| Endpoint | POST /mcp/run |
| Scope | pipeline |
| Sandbox key | refused |
| Extra entitlement | none |
| MCP tools | none, HTTP only |
| Convex function | leads/enrichBatch:enrichLead |
A free sandbox key is refused: it resolves real people’s contact details through a paid provider, which costs money per call.
Arguments
| Argument | Type | Required | Notes |
|---|---|---|---|
leadId | string | required | |
roles | string[] | optional | |
language | string | optional |
What Selda fills in
You never send these. The HTTP layer overwrites them from the API key, which is what keeps one organisation’s data out of another’s reach.
| Argument | Filled in from |
|---|---|
orgId | your organisation, resolved from the API key |
Example request
Required arguments only. Values in angle brackets are yours to fill in; the optional ones are in the table above.
curl -X POST https://api.selda.ai/mcp/run \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "fn": "leads.enrich", "args": { "leadId": "<leadId>" } }'{
"fn": "leads.enrich",
"args": {
"leadId": "<leadId>"
}
}Example response
Every endpoint answers in the same envelope.
{
"value": <the function's return value>,
"request_id": "req_..."
}The shape of value is not documented here. leads/enrichBatch:enrichLead declares no returns validator, so there is nothing to derive it from, and a shape written out by hand here is a shape that goes stale without anything noticing. Call it once against a test key and read what comes back.
On failure the body is { "error": { "type", "code", "message", "request_id" }, "request_id" } and request_id is echoed in the X-Request-Id header.
run leads.enrich
Enrich a workspace’s leads from a natural-language instruction (legacy path).
| Endpoint | POST /mcp/run |
| Scope | pipeline |
| Sandbox key | refused |
| Extra entitlement | none |
| MCP tools | none, HTTP only |
| Convex function | leads/enrichBatch:enrichBatch |
A free sandbox key is refused: it resolves real people’s contact details through a paid provider, which costs money per call.
INTERNAL_ACTIONS) declares leads.enrich on /mcp/run too, and the dispatcher checks that one first. This entry can never be the one that runs. It is documented because it exists in the registry, not because you can call it.Arguments
| Argument | Type | Required | Notes |
|---|---|---|---|
projectId | id<"projects"> | required | |
instruction | string | required | |
concurrency | number | optional |
What Selda fills in
You never send these. The HTTP layer overwrites them from the API key, which is what keeps one organisation’s data out of another’s reach.
| Argument | Filled in from |
|---|---|
orgId | your organisation, resolved from the API key |
Example request
Required arguments only. Values in angle brackets are yours to fill in; the optional ones are in the table above.
curl -X POST https://api.selda.ai/mcp/run \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "fn": "leads.enrich", "args": { "projectId": "<projectId>", "instruction": "<instruction>" } }'{
"fn": "leads.enrich",
"args": {
"projectId": "<projectId>",
"instruction": "<instruction>"
}
}Example response
Every endpoint answers in the same envelope.
{
"value": <the function's return value>,
"request_id": "req_..."
}The shape of value is not documented here. leads/enrichBatch:enrichBatch declares no returns validator, so there is nothing to derive it from, and a shape written out by hand here is a shape that goes stale without anything noticing. Call it once against a test key and read what comes back.
On failure the body is { "error": { "type", "code", "message", "request_id" }, "request_id" } and request_id is echoed in the X-Request-Id header.
Generated from convex/lib/mcpRegistry.ts. Nothing in this reference sends: launchRun is in no
registry and never will be, so a script can prepare a campaign completely and a person still
presses send in the app.