# Update Contact

`PATCH https://api.inboxjot.com/v1/contacts/{contact_id}`

Updates the fields you send and keeps the others. Needs a Full key. A key limited to one domain answers 403. Send an optional `Idempotency-Key` header to retry safely. See Idempotency.

## Path Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `contact_id` | string | Yes | A contact id, or the contact's email address. |

## Body Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `first_name` | string \| null | No | First name, up to 200 characters. Send `null` to clear it. |
| `last_name` | string \| null | No | Last name, up to 200 characters. Send `null` to clear it. |
| `language` | string \| null | No | A language code, such as `en` or `pt-BR`. |
| `notes` | string \| null | No | Private notes, up to 5,000 characters. Send `null` to clear them. |
| `properties` | object \| null | No | Values for properties you added in Settings, keyed by the property key. Each value must match the property type: text up to 2,000 characters, a number, `true` or `false`, a date, or one of a choice property’s options. `null` clears a value. The values merge with the ones the contact has. |
| `subscribed` | boolean \| null | No | `true` subscribes the contact. `false` unsubscribes the contact from all email. |
| `segment_ids` | string[] \| null | No | The static segments the contact belongs to, up to 50. The contact joins the ones in the list and leaves the static segments that are not in it. Leave it out to keep the segments as they are. |
| `topics` | object[] \| null | No | Topic choices to save, up to 100. Topics you leave out keep their choice. |
| `topics.id` | string | Yes | The topic id. The topic must exist. |
| `topics.status` | string | Yes | `subscribed` or `unsubscribed`. |

## Response

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | No | The contact id. |
| `email` | string | No | The contact address. |
| `first_name` | string \| null | No | First name. |
| `last_name` | string \| null | No | Last name. |
| `status` | string | No | One of `subscribed`, `pending` or `unsubscribed`. |
| `language` | string | No | Language code. |
| `properties` | object | No | Property values, keyed by the property key. |
| `segments` | object[] | No | The segments the contact is in. |
| `segments[].id` | string | No | The segment id. |
| `segments[].name` | string | No | The segment name. |
| `topics` | object[] | No | Every topic in the workspace, with the contact’s choice. |
| `topics[].id` | string | No | The topic id. |
| `topics[].name` | string | No | The topic name. |
| `topics[].status` | string \| null | No | The contact’s choice: `subscribed`, `pending` or `unsubscribed`. `null` when the contact has not chosen. |
| `topics[].subscribed` | boolean | No | Whether the contact gets email for this topic, counting the topic default. |
| `created_at` | string | No | ISO 8601 time. |
| `updated_at` | string | No | ISO 8601 time. |

## Request

cURL:

```bash
curl -X PATCH https://api.inboxjot.com/v1/contacts/con_06d2mfk8r9wq3zh5ka2pe \
  -H "Authorization: Bearer $INBOXJOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Riti",
    "properties": {
      "plan": "enterprise"
    },
    "topics": [
      {
        "id": "top_06d2mfk8r6pn2tc8yw3hd",
        "status": "unsubscribed"
      }
    ]
  }'
```

Node.js:

```javascript
import { Inboxjot } from 'inboxjot';

const inboxjot = new Inboxjot();

const contact = await inboxjot.contacts.update('con_06d2mfk8r9wq3zh5ka2pe', {
  first_name: 'Riti',
  properties: { plan: 'enterprise' },
  topics: [{ id: 'top_06d2mfk8r6pn2tc8yw3hd', status: 'unsubscribed' }],
});
```

Rust:

```rust
use inboxjot::{Inboxjot, TopicChoice, TopicStatus, UpdateContact};
use serde_json::json;

let client = Inboxjot::from_env()?;

let contact = client
    .contacts()
    .update("con_06d2mfk8r9wq3zh5ka2pe", &UpdateContact {
        first_name: Some(Some("Riti".into())),
        properties: json!({ "plan": "enterprise" }).as_object().cloned(),
        topics: Some(vec![TopicChoice {
            id: "top_06d2mfk8r6pn2tc8yw3hd".into(),
            status: TopicStatus::Unsubscribed,
        }]),
        ..Default::default()
    })
    .await?;
```

Go:

```go
client := inboxjot.NewClient("")

contact, err := client.Contacts.Update(ctx, "con_06d2mfk8r9wq3zh5ka2pe", inboxjot.UpdateContactParams{
	FirstName:  inboxjot.Value("Riti"),
	Properties: map[string]any{"plan": "enterprise"},
	Topics: []inboxjot.TopicChoice{
		{ID: "top_06d2mfk8r6pn2tc8yw3hd", Status: inboxjot.TopicUnsubscribed},
	},
})
```

Python:

```python
from inboxjot import Inboxjot

inboxjot = Inboxjot()

contact = inboxjot.contacts.update(
    "con_06d2mfk8r9wq3zh5ka2pe",
    {
        "first_name": "Riti",
        "properties": {"plan": "enterprise"},
        "topics": [{"id": "top_06d2mfk8r6pn2tc8yw3hd", "status": "unsubscribed"}],
    },
)
```

## Responses

| Status | Description |
| --- | --- |
| 200 | Returns the updated contact. |
| 400 | A field is missing or invalid, or the Idempotency-Key header is not valid. |
| 401 | The API key is missing, revoked or expired. |
| 403 | The key is a Sending key or is limited to one domain, or the request comes from outside its IP allowlist. |
| 404 | The contact does not exist in this workspace. |
| 409 | A request with the same Idempotency-Key is still running. Retry after one second. |
| 413 | The body is larger than 2 MB. |
| 415 | The Content-Type header is not application/json. |
| 422 | The Idempotency-Key was already used with a different request. |
| 429 | Too many requests for this key. Wait for the seconds in the Retry-After header. |
| 500 | Something failed on our side. Retry later. |

200:

```json
{
  "id": "con_06d2mfk8r9wq3zh5ka2pe",
  "email": "sukhamoy@example.com",
  "first_name": "Sukha",
  "last_name": "Moy",
  "status": "subscribed",
  "language": "en",
  "properties": {
    "plan": "enterprise"
  },
  "segments": [
    {
      "id": "seg_06d2mfk8r2kd7fq4mx9ab",
      "name": "Customers"
    }
  ],
  "topics": [
    {
      "id": "top_06d2mfk8r6pn2tc8yw3hd",
      "name": "Product Updates",
      "status": "unsubscribed",
      "subscribed": false
    }
  ],
  "created_at": "2026-10-12T09:41:07.000Z",
  "updated_at": "2026-10-15T14:02:33.000Z"
}
```

400:

```json
{
  "name": "validation_error",
  "status": 400,
  "message": "The request body is not valid JSON",
  "errors": [
    {
      "message": "The request body is not valid JSON",
      "location": "body"
    }
  ],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

401:

```json
{
  "name": "unauthorized",
  "status": 401,
  "message": "Unauthorized",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

403:

```json
{
  "name": "forbidden",
  "status": 403,
  "message": "This key cannot be used from 203.0.113.7",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

404:

```json
{
  "name": "not_found",
  "status": 404,
  "message": "Contact not found",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

409:

```json
{
  "name": "concurrent_idempotent_requests",
  "status": 409,
  "message": "A request with this idempotency key is still in progress. Try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

413:

```json
{
  "name": "payload_too_large",
  "status": 413,
  "message": "The request body is too large",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

415:

```json
{
  "name": "unsupported_media_type",
  "status": 415,
  "message": "The Content-Type must be application/json",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

422:

```json
{
  "name": "invalid_idempotent_request",
  "status": 422,
  "message": "This idempotency key was already used with a different request",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

429:

```json
{
  "name": "rate_limit_exceeded",
  "status": 429,
  "message": "Too many attempts. Try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

500:

```json
{
  "name": "unknown_error",
  "status": 500,
  "message": "Something went wrong. Please try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```
