Update client contact
PUT /teams/{teamId}/clients/{clientId}/contacts/{contactId}
Changes the fields you send and keeps all other fields as they are. Returns the updated contact object.
clients:write · Team permission:client_contacts.write · Rate limit: default (120 / 60s)The key holder's role must include Add and edit client contacts (Owner, Admin and Deputy Admin include it), and the key holder must have a seat in the team. See the permissions matrix.
402 PAYMENT_REQUIRED until the subscription is reactivated.Path parameters
How a partial update works
This endpoint uses PUT, but you do not send the full contact. Send only the fields you want to change.
| What you send for a field | Result |
|---|---|
| Field not in the body | The field does not change. |
| A text value | The field gets the new value. |
null or "" | The field is cleared. You can clear lastName, jobTitle and note only. |
firstNameandemailcannot be cleared. A contact always has both. If you sendnull,""or only spaces for one of them, the API returns400.- An empty body (
{}) returns400. Send at least one field. - A field that is not in the list below returns
400. For example, you cannot sendclientIdto move a contact to a different client. - The API removes spaces at the start and end of each value. A value that has only spaces counts as empty.
Request body
null or "" to clear it.[email protected]. It must be 100 characters or fewer after we remove spaces at the start and end. No other contact of the same client can have the same address.null or "" to clear it.null or "" to clear it.Names, job titles and email addresses cannot contain line breaks or hidden characters, such as zero-width or text-direction characters. The note can contain line breaks, but no other hidden characters. Every field must be text or null; a number or a boolean returns 400.
{ "jobTitle": "VP of Marketing", "note": null }
Request
curl -X PUT https://api.twominutereports.com/v1/teams/0190f8b0-1a2b-7c3d-8e4f-5a6b7c8d9e0f/clients/0190f8c0-1a2b-7c3d-8e4f-5a6b7c8d9e0f/contacts/0190f8d2-6b7c-7d8e-9f0a-1b2c3d4e5f6a \
-H "Authorization: Bearer tmrc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"jobTitle": "VP of Marketing", "note": null}'
Response
Returns the full contact object after the change.
{
"success": true,
"data": {
"id": "0190f8d2-6b7c-7d8e-9f0a-1b2c3d4e5f6a",
"clientId": "0190f8c0-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"client": {
"id": "0190f8c0-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"name": "Acme Corp",
"logoUrl": "https://assets.gox.ai/tmr/logos/acme.png"
},
"firstName": "Sarah",
"lastName": "Chen",
"email": "[email protected]",
"jobTitle": "VP of Marketing",
"note": null,
"briefingCount": 2,
"createdAt": "2026-10-02T09:30:00.000Z",
"updatedAt": "2026-10-11T10:20:00.000Z",
"createdBy": {
"id": "0190f8b7-3c4d-7e5f-9a0b-1c2d3e4f5a6b",
"name": "Priya Raman",
"firstName": "Priya",
"lastName": "Raman",
"avatarUrl": null,
"email": "[email protected]"
},
"updatedBy": {
"id": "0190f8b8-4d5e-7f6a-8b1c-2d3e4f5a6b7c",
"name": "Arun Menon",
"firstName": "Arun",
"lastName": "Menon",
"avatarUrl": null,
"email": "[email protected]"
}
}
}
{
"success": false,
"error": { "code": "BAD_REQUEST", "message": "Validation error: Send at least one field to change." }
}
Returned when a field breaks a rule above. The message names the field. Other messages include Enter a first name., Enter a valid email address using standard characters., Keep the note to 500 characters or fewer. and Unrecognized key: "clientId".
{
"success": false,
"error": { "code": "BAD_REQUEST", "message": "Validation error: Keep the job title to 100 characters or fewer. at \"jobTitle\"" }
}
{
"success": false,
"error": { "code": "PAYMENT_REQUIRED", "message": "Your team's plan has been cancelled. Please reactivate your subscription to continue." }
}
The API key does not have the clients:write scope.
{
"success": false,
"error": { "code": "INSUFFICIENT_PERMISSIONS", "message": "This API key is missing the `clients:write` permission required for this endpoint. Grant it to the key under Settings → API Keys (https://hub.twominutereports.com/settings?tab=user-api-keys), or use a key that has it." }
}
The key holder's role does not include Add and edit client contacts.
{
"success": false,
"error": { "code": "INSUFFICIENT_ROLE", "message": "[email protected] is not allowed to use client_contacts.write. This needs a role that includes it; their role is editor." }
}
The key holder's role allows this, but they do not have a seat in the team.
{
"success": false,
"error": { "code": "SEAT_REQUIRED", "message": "[email protected] needs a seat in this team to use client_contacts.write. Their role allows it — an Admin can assign a seat in Team settings." }
}
Returned when the contact does not exist, belongs to a different client, or belongs to a different team. The API does not tell these cases apart.
{
"success": false,
"error": { "code": "NOT_FOUND", "message": "Contact not found" }
}
Returned when another contact of the same client already has this email address.
{
"success": false,
"error": { "code": "CONFLICT", "message": "This email already belongs to Daniel Park at Acme Corp." }
}