# tags.project.update

Set a project tag's status (planned, active or completed) or keywords (up to 20 words the classifier looks for) with tagId, idempotencyKey and optionally expectedRevision (the project's revision from tags.get). Changing keywords asks the project classifier to look at its transactions again. When the project syncs from Notion, a status set here that differs from Notion's is a conflict to resolve with accounting_tags_notion_resolve.

`POST /api/v1/accounting/tags.project.update`

Permissions: `accounting:read`, `accounting:write` · Roles: admin, finance · Idempotency key required · Send `expectedRevision`

MCP tool: `accounting_tags_project_update`

## Fields

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `tagId` | string (ID) | Yes | The ID of a project tag, from tags.list. |
| `expectedRevision` | integer |  | The record's current revision, from the last time you read it. If someone changed the record since, the request is refused with a conflict so you can reload and check before trying again. at most 9007199254740991; greater than 0. |
| `status` | enum |  | Only include records with this status. One of: `planned`, `active`, `completed`. |
| `keywords` | array of strings |  | at most 20 items; each 2–60 characters. |
| `idempotencyKey` | string | Yes | Any unique text you generate once per intended change, so a retried request only happens once. Send it as the Idempotency-Key header instead if you prefer; if you send both they must match. 8–200 characters. |

## Example request

```bash
curl https://app.getoatmilk.com/api/v1/accounting/tags.project.update \
  -H "Authorization: Bearer $OATMILK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "tagId": "7f0f6c1e-1c1f-4b5e-9c8d-2f5e8e3c1a10",
  "status": "planned"
}'
```

Reference page: https://app.getoatmilk.com/docs/api/tags.project.update
