---
title: "update"
description: "Modify an existing contact, company, deal, action, note, call, or meeting by id."
canonical_url: https://developer.onepagecrm.com/mcp/tools/update/
source: Markdown mirror of https://developer.onepagecrm.com/mcp/tools/update/
---

`update` modifies an existing record. Only the fields you send are
changed; everything else is left alone.

## Signature

```json
{
  "type": "object",
  "properties": {
    "entity": { "type": "string", "description": "Entity type." },
    "id":     { "type": "string", "description": "The record id — a 24-character hex string." },
    "data":   { "type": "object", "description": "Fields to change." }
  },
  "required": ["entity", "id", "data"]
}
```

All three fields are required.

## Supported entities

`contact`, `company`, `deal`, `action`, `note`, `call`, `meeting`.

Companies are *updatable* through `update` even though they're not
directly creatable through `create`.

## Finding the id

Use [`query`](/mcp/tools/query/) to look the record up first. For
example:

```json
{
  "query": {
    "from": "contacts",
    "select": ["id", "first_name", "last_name"],
    "where": { "emails.address": "jane.doe@acmesolar.example" }
  }
}
```

Then pass the `id` straight into `update`.

## Example

```json
{
  "entity": "contact",
  "id":     "65f1b3c2a4d8e9f0c1234567",
  "data": {
    "status_id": "prospect",
    "tags":      ["lead", "demo-requested", "qualified"]
  }
}
```

Response:

```jsonc
{
  "entity": "contact",
  "id":     "65f1b3c2a4d8e9f0c1234567",
  "data":   { /* the contact, after the update */ }
}
```

## Array fields are full replacements

Fields that contain arrays — `emails`, `phones`, `urls`, `tags` — are
**replaced wholesale**, not merged. `tags` is a list of strings;
`emails`, `phones`, and `urls` are lists of objects (`{ type, address }`,
`{ type, number }`, `{ type, url }`). To add one entry rather than
overwrite the list, query the current value first and send the combined
array:

```json
{
  "entity": "contact",
  "id":     "65f1...",
  "data":   { "tags": ["lead", "demo-requested", "qualified"] }
}
```

## Custom fields

Send a `custom_fields` object inside `data`, keyed by field name as
returned by [`describe`](/mcp/tools/describe/). Only the custom fields
you include are changed:

```json
{
  "entity": "deal",
  "id":     "65f1b3c2a4d8e9f0c1234567",
  "data":   { "custom_fields": { "Tier": "Platinum" } }
}
```

## Errors

- **Not found / not accessible** — both cases return the same generic
  "not found" response. The MCP server doesn't distinguish "this id
  doesn't exist" from "this id exists but is on a record you can't see"
  by design, to avoid leaking the existence of records outside the
  user's access scope.
- **Validation errors** — same surface as `create`: each rejected
  field is named with the reason.
- **Unknown entity** — response lists the valid entity names and
  hints at the singular form if a plural was sent.

## Scope

`crm` — the write scope. `crm.readonly` is not sufficient.

Access checks run on every call. A contact, deal, or linked record
must be accessible to the authenticated user (private records they
don't own, or records belonging to other users on a permission-scoped
account, will be invisible).
