---
title: "Upsert a contact by phone"
method: PUT
path: "/contacts/by-phone/{phone}"
tags: ["Contacts"]
---

# Upsert a contact by phone

`PUT /contacts/by-phone/{phone}`

## Request

- Base URL: `https://api.textla.com/v1`
- URL: `https://api.textla.com/v1/contacts/by-phone/{phone}`
- Auth: HTTP bearer

Creates or fully replaces a contact under the authenticated account, using its E.164 phone number as the resource key. The account ID is taken from the bearer token. The body phone must match the path phone. Omitted or empty tags, groups, keywords, and custom_fields clear those buckets on replacement. Custom fields may identify an existing definition by its opaque field_id or by name. Returns 201 when created and 200 when replaced, with the resulting Contact and ETag. Contacts Service currently reapplies retries instead of replaying the original response.

## Path parameters

- `phone` string, required: E.164 phone number identifying the contact; must match body.phone

## Request body

- CreateContactBody
  - `$schema` string, uri: A URL to the JSON Schema for this object.
  - `birth_date` string
  - `city` string
  - `company` string
  - `contact_type` 'subscriber' | 'lead': Type of contact: subscriber or lead
  - `country` string
  - `custom_fields` CustomFieldValue[]
    - `field_id` string
    - `name` string
    - `value` unknown, required
  - `email` string
  - `first_name` string
  - `groups` string[]
  - `keywords` string[]
  - `last_name` string
  - `location` Location
    - `lat` number, double, required
    - `lon` number, double, required
  - `manually_added` boolean
  - `opted_in_at` integer, nullable: When the contact opted in, as milliseconds since the Unix epoch. Null is the same as omitting it
  - `phone` string, required
  - `postal_code` string
  - `signed_up_at` integer, nullable: When the contact joined the list, as milliseconds since the Unix epoch. Defaults to the current time if omitted or null
  - `state` string
  - `street` string
  - `tags` string[]

## Response `200`

OK

- Contact
  - `$schema` string, uri: A URL to the JSON Schema for this object.
  - `account_id` string, required
  - `birth_date` string, nullable, required
  - `carrier` string, nullable, required
  - `city` string, nullable, required
  - `company` string, nullable, required
  - `contact_type` string, required
  - `country` string, nullable, required
  - `created_at` integer, required: When the contact record was created, as milliseconds since the Unix epoch
  - `custom_fields` CustomFieldValue[], nullable, required
    - `field_id` string
    - `name` string
    - `value` unknown, required
  - `email` string, nullable, required
  - `first_name` string, nullable, required
  - `groups` string[], nullable, required
  - `id` integer, required
  - `keywords` string[], nullable, required
  - `last_active_at` integer, nullable, required: When the contact was last active (used for aging), as milliseconds since the Unix epoch. Null when never recorded
  - `last_communicated_at` integer, nullable, required: When a message was last sent to this contact, as milliseconds since the Unix epoch. Null until the first send
  - `last_name` string, nullable, required
  - `location` Location, required
    - `lat` number, double, required
    - `lon` number, double, required
  - `marked_invalid_at` integer, nullable, required: When the contact's phone number was marked invalid (for example, after a hard delivery failure), as milliseconds since the Unix epoch. Null while the number is considered valid
  - `opted_in_at` integer, nullable, required: When the contact opted in to messaging, as milliseconds since the Unix epoch. Null if the contact has never opted in
  - `opted_out_at` integer, nullable, required: When the contact opted out of messaging, as milliseconds since the Unix epoch. Null while the contact is opted in. A non-null value means the contact must not be messaged
  - `phone` string, required
  - `postal_code` string, nullable, required
  - `signed_up_at` integer, nullable, required: When the contact signed up, as milliseconds since the Unix epoch. Null when not provided
  - `soft_opted_out_at` integer, nullable, required: When the contact was soft opted out, as milliseconds since the Unix epoch. Null while the contact is not soft opted out
  - `state` string, nullable, required
  - `street` string, nullable, required
  - `tags` string[], nullable, required
  - `updated_at` integer, required: When the contact record was last changed, as milliseconds since the Unix epoch

## Other responses

- `201`: OK
- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `412`: Precondition Failed
- `422`: Unprocessable Entity
- `500`: Internal Server Error
- `502`: Bad Gateway
- `503`: Service Unavailable
- `504`: Gateway Timeout

---

[API](https://skmtc.dev/textla/apis/textla-api.md) - [All operations](https://skmtc.dev/textla/apis/textla-api/llms.txt) - [OpenAPI document](https://skmtc.dev/textla/apis/textla-api/revisions/473f03350bc1?raw)
