---
title: "Update a contact by ID"
method: PATCH
path: "/contacts/{id}"
tags: ["Contacts"]
---

# Update a contact by ID

`PATCH /contacts/{id}`

Update an existing contact identified by its unique `id`.
Include one or more fields to change. Field updates and consent changes
can be combined in a single request.

Mutable fields: `first_name`, `last_name`, `email`, `phone_number`, `tags`, `custom_fields`.

`email` and `phone_number` can only be set when the existing value is
`null`. Once populated, they cannot be changed or cleared.

Consent fields: `email_consent`, `sms_consent`. Use these to subscribe,
unsubscribe, or otherwise manage a contact's marketing consent.

When `sms_consent` is set to `subscribed` and the contact transitions to
a confirmed opt-in state, Privy automatically sends a TCPA-required
welcome SMS. Pass `send_welcome_sms: false` to suppress this message if
you have already collected consent outside of Privy.

**Required scope:** `contacts_write`

## Path parameters

- `id` string, required

## Request body

- UpdateContactByIdRequest — Include one or more fields to update. The contact is identified by the `id` path parameter. Field updates and consent changes can be combined in a single request. Mutable fields: `first_name`, `last_name`, `email`, `phone_number`, `tags`, `custom_fields`. `email` and `phone_number` can only be set when the existing value is `null`. Once populated, they cannot be changed or cleared. Consent fields: `email_consent`, `sms_consent`. Use these to manage a contact's marketing consent instead of the deprecated unsubscribe endpoint.
  - `first_name` string — Updated first name.
  - `last_name` string — Updated last name.
  - `email` string, email — Sets the contact's email address. Only allowed when the contact's current `email` is `null`; once populated, `email` is immutable.
  - `phone_number` string — Sets the contact's phone number in E.164 format. Only allowed when the contact's current `phone_number` is `null`; once populated, `phone_number` is immutable.
  - `tags` string[] — Replaces all existing tags.
  - `custom_fields` object — Replaces all existing custom fields. Must be a flat key-value object.
  - `email_consent` 'subscribed' | 'unsubscribed' | 'never_subscribed' | 'suppressed' — Update the contact's email marketing consent. `compliance_suppressed` is read-only — any write to a compliance-suppressed contact returns `422`. For merchant-suppressed contacts, writing any consent value first unsuppresses, then applies the requested transition (e.g. `subscribed` unsuppresses then subscribes).
  - `sms_consent` 'subscribed' | 'unsubscribed' | 'never_subscribed' | 'single_opt_in' — Update the contact's SMS marketing consent. `pending` is read-only. `subscribed`, `single_opt_in`, and `unsubscribed` require the contact to have a phone number. `single_opt_in` is idempotent when the contact is already in that state, and returns `422` from terminal states (`pending`, `confirmed`, or `unsubscribed`).
  - `send_welcome_sms` boolean — When `sms_consent` is set to `subscribed` and the contact transitions to a confirmed SMS opt-in state, Privy sends a TCPA-required welcome SMS. Set to `false` to suppress this message when you have already collected consent outside of Privy.

## Response `200`

Contact updated successfully.

- object
  - `data` Contact
    - `id` string — Stable, unique identifier for the contact. Use this value in `/v1/contacts/{id}` endpoints.
    - `first_name` string
    - `last_name` string
    - `email` string, email
    - `email_consent` 'subscribed' | 'unsubscribed' | 'never_subscribed' | 'suppressed' | 'compliance_suppressed' — Email marketing consent status. - `subscribed` — contact opted into email (explicit or implicit consent). - `unsubscribed` — contact opted out of email. - `never_subscribed` — no opt-in and no opt-out. - `suppressed` — merchant-suppressed (bounce list, manual action). - `compliance_suppressed` — system-suppressed (CAN-SPAM, abuse complaint). Read-only.
    - `phone_number` string
    - `sms_consent` 'subscribed' | 'unsubscribed' | 'never_subscribed' | 'single_opt_in' | 'pending' — SMS marketing consent status. - `subscribed` — contact has confirmed SMS opt-in. - `unsubscribed` — contact opted out of SMS. - `never_subscribed` — no opt-in and no opt-out. - `single_opt_in` — merchant collected a single opt-in (not yet confirmed). - `pending` — Privy is awaiting a confirmation reply. Read-only.
    - `tags` string[]
    - `custom_fields` object
    - `created_at` string, date-time
    - `updated_at` string, date-time

## Other responses

- `401` — Missing or invalid bearer token.
- `403` — Token lacks the required scope for this endpoint.
- `404` — Contact not found.
- `422` — One or more fields failed validation.
- `429` — Rate limit exceeded. Retry after the specified time.

---

[API](https://skmtc.dev/privy/apis/privy-api.md) · [All operations](https://skmtc.dev/privy/apis/privy-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/privy/privy-api/revisions/5378aff56b9a/schema)
