> ## Documentation Index
> Fetch the complete documentation index at: https://developers.harvey.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Client Matters

> Create clients and matters, update their details, and manage billing attribution

Use the Client Matters API to sync your firm's client and matter identifiers with Harvey. Create clients first, then create or update their matters. Use the v1 endpoints to list or delete matters.

| Action | Endpoint |
| - | - |
| Create or update clients | `POST /api/v2/clients` |
| Create or update matters | `POST /api/v2/matters` |
| List matters, including deleted matters | `GET /api/v1/client_matters` |
| Delete matters | `DELETE /api/v1/client_matters` |

<Note>
  These endpoints share a rate limit that defaults to **150 requests per minute per workspace**. Each v2 request accepts **1 to 10,000 rows**. Always check the `errors` array in the v2 response, even when the request returns HTTP 200.
</Note>

## Before you start

Use an [API bearer token](/api-reference/authentication) with **Client matters admin** (`write:client_matters`) to create, update, or delete records. To list matters, either this permission or **Access client matters** (`read:client_matters`) is sufficient.

**If your workspace has matters previously created using full names, you must explicitly set the workspace delimiter before using the v2 APIs.** Set it to the separator used in those names. For an existing name such as `10022421-M001`, set the delimiter to `-` and send `client_id: "10022421"` and `matter_id: "M001"`.

Harvey joins `client_id`, the workspace delimiter, and `matter_id` to form a full matter name. The examples below use `.`: client `10022421` and matter `M001` form `10022421.M001`. The v1 list API returns this full name as `name`, and the v1 delete API accepts it.

The optional `client_name` and `matter_name` fields are display labels, such as `Acme Corp` and `Acme Acquisition`.

## Create or update a client

```bash theme={null}
curl -X POST https://api.harvey.ai/api/v2/clients \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "clients": [
      {"client_id": "10022421", "client_name": "Acme Corp"}
    ]
  }'
```

A new client appears in `created`:

```json theme={null}
{
  "created": [{"client_id": "10022421", "client_name": "Acme Corp"}],
  "updated": [],
  "errors": []
}
```

To update a client, send its `client_id` again with the fields you want to change. The response includes the client in `updated`, even if the values are unchanged. If the client was deleted, the request restores it. Restoring a client does not restore its deleted matters; restore those through `POST /api/v2/matters`.

## Create or update a matter

Create or restore the client before sending its matters. This endpoint does not create missing clients.

```bash theme={null}
curl -X POST https://api.harvey.ai/api/v2/matters \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "matters": [
      {
        "client_id": "10022421",
        "matter_id": "M001",
        "matter_name": "Acme Acquisition",
        "description": "Acquisition due diligence",
        "notice": "Confirm the engagement before selecting this matter."
      }
    ]
  }'
```

```json theme={null}
{
  "created": [
    {
      "client_id": "10022421",
      "matter_id": "M001",
      "client_name": "Acme Corp",
      "matter_name": "Acme Acquisition",
      "description": "Acquisition due diligence",
      "allowed": true,
      "notice": "Confirm the engagement before selecting this matter.",
      "harvey_id": "018d856f-0664-772c-9ed9-b2316fd881d3"
    }
  ],
  "updated": [],
  "errors": []
}
```

To update a matter, send the same `client_id` and `matter_id` with the fields you want to change. Harvey first looks for that pair of identifiers. If it finds no match, it checks for a matter with the same full name, such as `10022421.M001`. This lets the request update a matter created through v1. The matched matter appears in `updated` and keeps its `harvey_id`. If it was deleted, the request restores it.

`harvey_id` is the matter's ID in Harvey.

## Update or clear fields

| Field | Omitted from an update | `null` or blank text | Limit |
| - | - | - | - |
| `client_name` | Keep the client label | Clear the label | 256 characters |
| `matter_name` | Keep the matter label | Clear the label | 256 characters |
| `description` | Keep the description | Clear the description | 200 characters |
| `notice` | Keep the selection notice | Clear the notice | 2,000 characters |

For a new record, these fields default to `null` when omitted.

`client_id` must contain 1 to 128 characters, and `matter_id` must not be empty. The full matter name (`client_id` + delimiter + `matter_id`, such as `10022421.M001`) must contain at most 128 characters and match the format configured for the workspace, if any.

For example, this request clears the notice and keeps the matter's other fields:

```json theme={null}
{
  "matters": [{"client_id": "10022421", "matter_id": "M001", "notice": null}]
}
```

`allowed` follows separate rules:

* Omit it to preserve an existing value. New matters default to `true`.
* Sending it requires `use:disallowed_client_matters`, even when setting it to `true`. Without that permission, the whole request returns HTTP 403.
* Use a JSON boolean (`true` or `false`), not a string. With the required permission, `null` returns HTTP 400 with `invalid_request`.

## Handle batch results and errors

Each v2 HTTP 200 response has three arrays: `created`, `updated`, and `errors`. An error in one row does not block valid rows in the same request. For example, a batch can update one matter while rejecting another whose client does not exist:

```json theme={null}
{
  "created": [],
  "updated": [
    {
      "client_id": "10022421",
      "matter_id": "M001",
      "client_name": "Acme Corp",
      "matter_name": "Acme Acquisition",
      "description": "Acquisition due diligence",
      "allowed": true,
      "notice": null,
      "harvey_id": "018d856f-0664-772c-9ed9-b2316fd881d3"
    }
  ],
  "errors": [
    {
      "client_id": "UNKNOWN",
      "matter_id": "M002",
      "error": "client_not_found",
      "detail": "No client with this identifier exists in the workspace"
    }
  ]
}
```

Use `error` codes to handle failures in your integration. The `detail` field explains the error in plain language. Correct failed rows before retrying them.

| Row error | What to check |
| - | - |
| `invalid_client_id`, `invalid_matter_id` | IDs must not be blank; client IDs must contain at most 128 characters. |
| `duplicate_client_id`, `duplicate_pair` | A later row repeats a client ID or client and matter pair. Harvey ignores leading and trailing whitespace when comparing identifiers. Submit each client ID or pair once per batch. |
| `client_not_found` | Create or restore the parent client first. |
| `invalid_client_name`, `invalid_matter_name`, `description_too_long`, `notice_too_long` | Shorten the affected text. |
| `name_too_long`, `name_failed_workspace_regex` | Check the full matter name (`client_id` + delimiter + `matter_id`). |
| `name_collision`, `identity_conflict` | Different identifier pairs produce the same full matter name, or conflict with an existing record. Check the identifiers and delimiter. |

Errors that affect the whole request use these HTTP status codes:

| HTTP status | Meaning |
| - | - |
| 400 | `invalid_request` for an empty batch, missing field, or wrong type; `too_many_items` for more than 10,000 rows; `delimiter_required` when a matter request needs an explicit workspace delimiter. |
| 401 | Missing, invalid, or expired API token, or missing `write:client_matters` permission. |
| 403 | Sending `allowed` without `use:disallowed_client_matters` permission. |
| 429 | Shared client matter rate limit exceeded. |
| 500 | Internal server error. |

`POST /api/v2/matters` uses the delimiter from the API token's active workspace. If it is unset or empty, the endpoint uses `.` unless the workspace requires an explicit delimiter. When an explicit delimiter is required but missing, the endpoint returns HTTP 400:

```json theme={null}
{
  "error": "delimiter_required",
  "detail": "Set a client matter delimiter for this workspace before upserting matters"
}
```

Harvey does not create or update any matters in this batch. Set the workspace delimiter and retry. `POST /api/v2/clients` does not return this error.

## List and delete matters

The v1 read and delete endpoints remain available. Listing includes deleted matters and usage statistics:

```bash theme={null}
curl https://api.harvey.ai/api/v1/client_matters \
  -H "Authorization: Bearer YOUR_API_KEY"
```

The response contains a `client_matters` array. Each row uses these identifiers:

| Field | Meaning |
| - | - |
| `id` | The Harvey matter UUID, returned by v2 as `harvey_id`. |
| `matter_number` | Your firm's matter identifier. May be `null` for legacy matters. |
| `client_id` | The Harvey client UUID. May be `null` for legacy matters. |

The v2 write endpoints expect your firm's client identifier in `client_id`. Do not pass the Harvey client UUID returned by this list endpoint.

Delete using the stored `name` from the read response, such as `10022421.M001`. Do not use the matter label or UUID:

```bash theme={null}
curl -X DELETE https://api.harvey.ai/api/v1/client_matters \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"client_matters": ["10022421.M001"]}'
```

Deleting a matter prevents users from selecting it. It does not remove past queries or their links to the matter. A later request to `POST /api/v2/matters` can restore it.

Check `success_count` and `failed` even when DELETE returns HTTP 200. Missing names appear in `failed`. A retry that deletes no active matters can also return the requested names in `failed`; use GET to check their `deleted_at` values.

Externally linked matters cannot be deleted while ethical-wall enforcement is enabled.

## Migrate from v1 writes

`POST /api/v1/client_matters` is deprecated. To migrate to v2:

1. Explicitly set the workspace delimiter to match your existing full matter names. For example, for `cm_name: "10022421-M001"`, configure `-` and use `client_id: "10022421"` with `matter_id: "M001"`. Joining these identifiers with the delimiter must reproduce the existing name so Harvey can match the matter.
2. Create or update each client with `POST /api/v2/clients`.
3. Create or update its matters with `POST /api/v2/matters`. Map `cm_desc` to `description`. If you send `cm_allowed`, map it to the JSON boolean `allowed` and ensure the token has `use:disallowed_client_matters` permission.
4. Handle `created`, `updated`, and `errors` instead of v1's `success_count` and `failed`.

`client_name` and `matter_name` are optional labels; they do not replace the identifiers. `notice` is available through the v2 matter endpoint. Continue using v1 for reads and deletes.


## Related topics

- [Audit Logs](/guides/audit_logs.md)
- [Get Client Matters](/api-reference/retrieve/get-client-matters.md)
- [Add Client Matters](/api-reference/add/add-client-matters.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.