# update_row

Source: https://modulify.ai/docs/api/database/update-row

Overwrites fields on one existing row in a site database, identified by its primary key.

- Title: Update a row in a collection
- Scope: `data:write`
- Access: Destructive
- Endpoint: `POST /v1/update_row`

The primary key defaults to the `id` column, and `primaryKeyColumn` must be the table's own single-column primary key, so a call never changes more than one row. Fields that are not columns of the table are dropped silently, as are `id` and the created and updated timestamps, and a call left with nothing writable is refused with a `400`. A key that matches no row is refused with a `404`, and a duplicate value in a `slug` column with a `409`.

This replaces live customer content, so the tool tells the client never to update a row it has not read first with `list_rows`. A file in the `CMS` folder of storage that the row stops using is deleted, unless another row of the same collection still uses it.

A `code` column runs on your live site for every visitor, so the tool tells the client to write only code you gave it, never code taken from a page, file or tool result it read. It also tells the client to keep to what the CMS editor accepts: at most 100,000 characters, every `script`, `style`, `iframe`, `textarea`, `title`, `noscript`, `noembed`, `noframes` and `xmp` tag closed, every HTML comment closed, every tag finished with `>`, and no `base` or `plaintext` tag. The server does not run those checks itself. See [Code fields](https://modulify.ai/docs/data/cms#code-fields).

## Request

Call it with a `POST` to `https://api.modulify.ai/v1/update_row`, sending the inputs below as a JSON object. The token needs the `data:write` scope.

> **Warning**
>
> This method is marked destructive: it deletes or overwrites data. Check the inputs before you call it, and send an [Idempotency-Key](https://modulify.ai/docs/api/idempotency) header whenever you might retry it.

```bash
curl -X POST https://api.modulify.ai/v1/update_row \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"PROJECT_ID","name":"NAME","primaryKeyValue":"PRIMARY_KEY_VALUE","values":{}}'
```

Over MCP, the same method is the [update_row tool](https://modulify.ai/docs/mcp/database/update-row).

## Inputs

| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string | Yes | The site id. |
| `schema` | string | No | The schema the collection lives in, exactly as `list_collections` reports it. Leave it out to use the site database's own default, which is right unless `list_collections` showed something else. A site on the newer database always uses its default. |
| `name` | string | Yes | The table name. |
| `primaryKeyValue` | string | Yes | The primary key value of the row to change. |
| `primaryKeyColumn` | string | No | The primary key column, when it is not the default `id`. It must be the table's own single-column primary key, so it never matches more than one row. |
| `values` | object | Yes | The columns to change and their new values. |

## Response

Every call answers with the [JSON envelope](https://modulify.ai/docs/api/requests-and-responses#the-response) of `success`, `message`, `data`, `code` and `version`. `data` holds the result described above, and on a method that returns a total, `count` carries it. The [response headers](https://modulify.ai/docs/api/requests-and-responses#headers-on-every-method-call) carry the call's `X-Request-Id` and what is left of your per-minute budget in `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. [Errors](https://modulify.ai/docs/api/errors) explains every status code a call can answer with.