---
title: "Call the updateLead MCP tool"
method: POST
path: "/api/v1/actions/updateLead"
tags: ["Actions"]
---

# Call the updateLead MCP tool

`POST /api/v1/actions/updateLead`

## Request

- Base URL: `https://app.reachium.io`
- URL: `https://app.reachium.io/api/v1/actions/updateLead`
- Auth: HTTP bearer

Update ONE lead: status (new | active | contacted | qualified | lost | unsubscribed), notes, custom_fields, identity fields, add/remove tags, or fill a blank work email through a connected enrichment provider (positive_reply, not_a_fit, booked_in, no_engagement, off_platform_activity, follow_up_later, do_not_contact, customer). Get the lead_id from findLeads or getCampaignLeads. IMPORTANT: every tag except follow_up_later permanently ends the lead's active campaign sequences when added (no more automated sends), and removing it never restarts them. custom_fields REPLACES the whole object for this workspace (it is not merged key by key) - include every key you want to keep, not just the ones changing; it is per-workspace, never shared with other workspaces holding the same lead. first_name, last_name, email, position, headline, company and linkedin_url edit the single SHARED record for this person: the same person can be a lead in more than one workspace, and these fields change what every one of those workspaces sees for them, not just this one. company is freetext, resolved to a company record the same way CSV import resolves it (an empty string clears the company link). linkedin_url is the globally unique identifier for that person across all of Reachium, so setting it to a URL already used by a different lead fails instead of overwriting. enrich_email:true is vendor-credit spending and is two-step confirmation-gated; an existing email is never overwritten. Surface anything in the returned warnings array to the user.

Called through the Actions bridge: the response is that tool's own result, wrapped as `{ data: <tool result> }` under HTTP 200. Billing, daily-cap, and confirm-step outcomes are embedded INSIDE `data`, never remapped to an HTTP status (see the templated `/api/v1/actions/{toolName}` operation above for the full protocol, and `x-mcp-actions` for this tool's machine-readable scope/cap/confirm_behavior fields). Authentication, request-shape, and optional idempotency-protocol failures still use their documented non-200 statuses.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `lead_id` string, uuid, required
  - `status` 'new' | 'active' | 'contacted' | 'qualified' | 'lost' | 'unsubscribed'
  - `notes` string: Replaces the lead notes. Pass an empty string to clear.
  - `custom_fields` object: Replaces this workspace's entire custom_fields object for the lead (not merged) - include every key you want to keep.
  - `first_name` string: Edits the shared leads record (affects every workspace with this lead).
  - `last_name` string: Edits the shared leads record (affects every workspace with this lead).
  - `email` string: Edits the shared leads record (affects every workspace with this lead).
  - `position` string: Current job title. Edits the shared leads record.
  - `headline` string: LinkedIn headline. Edits the shared leads record.
  - `company` string: Company name as freetext, resolved to company_id (creates a stub company if no match). Empty string clears it. Edits the shared leads record.
  - `linkedin_url` string: The globally unique LinkedIn URL identifying this person. Edits the shared leads record; fails if another lead already has it.
  - `add_tags` string[]
  - `remove_tags` string[]
  - `enrich_email` boolean: true: confirmation-gated Prospeo/Apollo work-email lookup. Existing email always wins.
  - `confirm_token` string: enrich_email only: return the exact token from the preview after user approval.

## Response `200`

The result of calling this tool.

- object
  - `data` unknown, required
  - `error` unknown, required

## Other responses

- `400`: The request body was not a JSON object (code invalid_request), or Idempotency-Key is malformed (code invalid_idempotency_key).
- `401`: Missing or invalid API key. Send `Authorization: Bearer rmcp_...` (code unauthorized).
- `403`: This tool is out of the key’s granted scope (code insufficient_scope).
- `409`: This Idempotency-Key has an unresolved in-flight or ambiguous result (code request_in_flight). Reconcile before using a new key.
- `422`: This Idempotency-Key was already used with a different request body (code idempotency_key_reuse).
- `429`: Rate limited: shared `mcp:ip:{ip}` (600/60s) or `mcp:key:{keyId}` (120/60s) bucket, the SAME buckets the MCP endpoint uses (code rate_limited).
- `500`: Unhandled server error (code internal_error).

---

[API](https://skmtc.dev/reachium/apis/reachium-api.md) · [All operations](https://skmtc.dev/reachium/apis/reachium-api/llms.txt) · [OpenAPI document](https://skmtc.dev/reachium/apis/reachium-api/revisions/11682826692b?raw)
