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

# Update Contact by ID

> Update an existing contact using their ID

<Tip>
  Unlike the [upsert endpoint](/api-reference/core-data/contacts/upsert) which matches by email or phone, this endpoint
  updates a specific contact by their ID. Use this when you need a deterministic update by ID — especially when changing
  a contact's email address.
</Tip>

## When to Use This

| Scenario                     | Use this endpoint | Use upsert instead                                                          |
| ---------------------------- | ----------------- | --------------------------------------------------------------------------- |
| Change a contact's email     | Yes               | Only if phone number is also provided (upsert falls back to phone matching) |
| Update a known contact by ID | Yes               | Either works                                                                |
| Create a new contact         | No (returns 404)  | Yes                                                                         |
| Update by email/phone match  | No                | Yes                                                                         |

## How It Works

* **Only provided fields are updated** — omitted fields are preserved
* **Custom fields are deep merged** — existing custom fields not included in the request are kept
* **Automations are triggered** — field change detection and automation triggers work the same as upsert
* **Soft-deleted contacts are restored** — if the contact was deleted, it will be restored with the provided data

## Marketing Consent

Update channel-specific marketing consent for a contact:

```json theme={null}
{
  "marketingConsent": {
    "email": true,
    "whatsapp": false
  }
}
```

| Field      | Type    | Description                                             |
| ---------- | ------- | ------------------------------------------------------- |
| `email`    | boolean | Email marketing opt-in (`true`) or opt-out (`false`)    |
| `whatsapp` | boolean | WhatsApp marketing opt-in (`true`) or opt-out (`false`) |

<Info>
  Both fields are optional. Omitting a channel leaves its current consent status unchanged. Setting `true` opts the
  contact in, `false` opts them out.
</Info>

<Warning>
  This endpoint does **not** create new contacts. If no contact exists with the given ID, a `404` error is returned.
</Warning>

## Example: Change a Contact's Email

<Steps>
  <Step title="Look up the contact by email">
    ```bash theme={null}
    curl --request GET \
      --url 'https://api.minimo.it/public/v1/contacts/by-email/old@example.com' \
      --header 'Authorization: Bearer mn-YOUR_CLIENT_ID-YOUR_API_KEY'
    ```

    Response: `{ "data": { "id": 42, "email": "old@example.com", ... } }`
  </Step>

  <Step title="Update using the contact ID">
    ```bash theme={null}
    curl --request PUT \
      --url 'https://api.minimo.it/public/v1/contacts/42' \
      --header 'Authorization: Bearer mn-YOUR_CLIENT_ID-YOUR_API_KEY' \
      --header 'Content-Type: application/json' \
      --data '{ "email": "new@example.com" }'
    ```
  </Step>
</Steps>

## Common Errors

| Error          | Cause                   | Solution                               |
| -------------- | ----------------------- | -------------------------------------- |
| `not_found`    | No contact with this ID | Verify the contact ID                  |
| `unauthorized` | Invalid API key         | Verify API key in Authorization header |

## Related Endpoints

* **[Get Contact by Email](/api-reference/core-data/contacts/get-by-email)**: Look up a contact's ID by email
* **[Create or Update Contact](/api-reference/core-data/contacts/upsert)**: Upsert by email or phone
* **[Delete Contact](/api-reference/core-data/contacts/delete)**: Soft-delete a contact


## OpenAPI

````yaml put /public/v1/contacts/{id}
openapi: 3.1.0
info:
  title: API Documentation
  description: Documentation for transactional and subscribe APIs
  version: 1.0.0
servers:
  - url: https://app.minimo.it
security:
  - bearerAuth: []
paths:
  /public/v1/contacts/{id}:
    servers:
      - url: https://api.minimo.it
    put:
      summary: Update contact by ID
      description: >-
        Update an existing contact using their ID. Uses the same deep merge
        logic as the upsert endpoint — only provided fields are updated, custom
        fields are merged. Returns 404 if the contact does not exist.
      operationId: updateContactById
      parameters:
        - name: id
          in: path
          required: true
          description: Contact ID
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: New email address
                phone:
                  type: string
                  description: New phone number
                customFields:
                  type: object
                  additionalProperties: true
                  description: Custom fields to update (merged with existing)
                marketingConsent:
                  $ref: '#/components/schemas/MarketingConsent'
            examples:
              changeEmail:
                summary: Change email address
                value:
                  email: new-email@example.com
              updateCustomFields:
                summary: Update custom fields
                value:
                  customFields:
                    plan: enterprise
                    company: Acme Corp
              updateMarketingConsent:
                summary: Update marketing consent
                value:
                  marketingConsent:
                    email: true
                    whatsapp: false
      responses:
        '200':
          description: Contact updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactIdResponse'
        '404':
          description: Contact not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    examples:
                      - Contact not found
      security:
        - bearerAuth: []
      x-codeSamples:
        - lang: Python
          source: >-
            import requests


            url = 'https://api.minimo.it/public/v1/contacts/42'

            headers = {'Authorization': 'Bearer {{BEARER_TOKEN}}',
            'Content-Type': 'application/json'}

            data = {'email': 'new-email@example.com'}

            response = requests.put(url, json=data, headers=headers)

            print(response.json())
        - lang: JavaScript
          source: >-
            const response = await
            fetch('https://api.minimo.it/public/v1/contacts/42', {
              method: 'PUT',
              headers: {
                'Authorization': 'Bearer {{BEARER_TOKEN}}',
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({ email: 'new-email@example.com' })
            });

            const result = await response.json();

            console.log(result);
        - label: CLI
          lang: cURL
          source: |-
            curl --request PUT \
              --url 'https://api.minimo.it/public/v1/contacts/42' \
              --header 'Authorization: Bearer {{BEARER_TOKEN}}' \
              --header 'Content-Type: application/json' \
              --data '{"email": "new-email@example.com"}'
components:
  schemas:
    MarketingConsent:
      type: object
      description: Channel-specific marketing consent preferences
      properties:
        email:
          type: boolean
          description: Email marketing consent (true = opted in, false = opted out)
          example: true
        whatsapp:
          type: boolean
          description: WhatsApp marketing consent (true = opted in, false = opted out)
          example: false
    ContactIdResponse:
      type: object
      properties:
        id:
          type: integer
          description: Contact ID
          examples:
            - 42
        phone:
          type: string
          nullable: true
          description: Phone number
          examples:
            - '+393391234567'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: mn-API_CLIENT_ID-API_KEY

````