---
title: "Add or update a customer"
method: PUT
path: "/api/v1/customers/{identifier}"
tags: ["Track Customers"]
---

# Add or update a customer

`PUT /api/v1/customers/{identifier}`

Adds or updates a person.

If your request does _not_ include `cio_id` and the identifiers in the request body do not belong to a person, your request adds a person.

If a person already exists with the identifier in the request path, your request updates that person. If the identifier in the path does not belong to a person but you use an identifier in your request body that _does_ belong to a person, your request updates the person and assigns them the identifier in the path.

If the identifier in the path and request body belong to different people, your request may return `200 OK` but produce an *Attribute Update Failure* for the identifier in the payload.

If you want to update a person's identifiers after they are set, you must reference them using their `cio_id` in the format `cio_<cio_id_value>`—unless when updating an `email` with the [Allow updates to email using ID](/accounts/workspaces#update-email-with-id) setting enabled. You can get the `cio_id` value from the [App API](/integrations/api/app/tag/customers/). If your request includes a `cio_id`, we'll attempt to update that person, including any identifiers in the request. If the `cio_id` does not exist or belongs to a person who was deleted, we'll drop the request.

For workspaces using `email` as an identifier, `email` is case-insensitive. The addresses `person@example.com` and `PERSON@example.com` would represent the same person.

**Tip**: If your workspace identifies people by both `email` and `id`, and you send an identify call with a new `id` but an `email` that already belongs to someone, we update the existing person rather than creating a new one. The existing person gets the new `id`. This is a common source of confusion during testing—if you're generating new IDs but reusing the same email address, you're updating one person repeatedly, not creating multiple people.

## Path parameters

- `identifier` union, required
  - string — The unique identifier for a person that you want to create or modify.
  - string — A person's email address. If adding a new person in an email-based workspace, you must use this value.
  - string, cio_[a-zA-Z0-9]* — A canonical identifier assigned by Customer.io when you add a person. When referencing a person by this value, you must prefix the value with `cio_`. You can [look up a person using the App API](/integrations/api/app/tag/customers/) to find their `cio_id`. You must use this value to update a person's other identifiers—their `id` or `email`, unless you enable your workspace's [Allow updates to email using ID](/accounts/workspaces#update-email-with-id) setting.

## Request body

- object — The body of the request contains key-value pairs representing attributes that you want to assign to, or update for, a person. If your request body contains "identifiers" (like `id` or `email`), your request attempts to update that person. If the identifier in the path and identifiers in the request body belong to different people, your request will produce an *Attribute Update Failure*.
  - `id` string — A customer's ID. You can set a person's ID if you identify them by email (in the path); you can update this value if you identify a person by `cio_id`.
  - `email` string, email — The email address of the customer.
  - `anonymous_id` string — An identifier for an anonymous event, like a cookie. If set as an attribute on a person, any events bearing the same anonymous value are associated with this person. This value must be unique and is not reusable.
  - `created_at` integer — The Unix timestamp when the user was created.
  - `_timestamp` integer — The Unix timestamp for when the attribute update occurred. This can be used to control the order of attribute updates when multiple requests are sent in rapid succession.
  - `_update` boolean — If you perform multiple requests in rapid succession when you create a person, there's a danger that you could create multiple profiles. If you know that a profile already exists and you want to update it, set `_update:true`, and Customer.io will _not_ create a new profile, even if the `identifier` in the path isn't found. If the identifiers in your path or request don't belong to an existing person, the request produces a *Failed Attribute Change* event in your activity log.
  - `cio_relationships` V1CioRelationships — Describes relationships to an entity—a non-person object in Customer.io, like a company, educational course, job board, etc.
    - `action` 'add_relationships' | 'delete_relationships' — This determines whether the `relationships` array adds relationships to a person or removes them from a person.
    - `relationships` object[] — Each object in the array represents a relationship you want to add to, or remove from, a person.
      - `identifiers` union — The identifiers for a particular object. You can use either the `object_type_id` and `object_id` (where `object_type_id` represents the type of object and the `object_id` is the individual identifier for the object) or the `cio_object_id`.
        - object
          - `object_type_id` string, required — The object type an object belongs to—like "Companies" or "Accounts". Object type IDs are string-formatted integers that begin at `1` and increment for each new type.
          - `object_id` string, required — The unique identifier for an object. If you use an `object_id` that already exists, we'll update the object accordingly.
        - object
          - `cio_object_id` string, required — A unique value that Customer.io sets for an object when you create it. This ID is immutable.
      - `relationship_attributes` RelationshipAttributes — The attributes associated with a relationship. Passing null or an empty string removes the attribute from the relationship.
  - `unsubscribed` boolean — If true, a person is unsubscribed from all messages. If false, or absent, a person is eligible to receive messages as determined by their `cio_subscription_preferences`. Like subscription preferences, this attribute is automatically set or updated when a person clicks the "unsubscribe" link in your emails. We support any case of true (i.e. TRUE, true, tRUe, etc.), 1, or "1" to represent unsubscribed. Any other value is considered “false”, or subscribed.
  - `cio_subscription_preferences` object — Stores your audience's subscription preferences if you enable our [subscription center](/journeys/channels/subscriptions/center/) feature. These items are set automatically when people use the unsubscribe link in your messages, but you can set preferences outside the subscription flow. To update select topic preferences while preserving those set for other topics, use JSON dot notation `"cio_subscription_preferences.topics.topic_<topic ID>":<boolean>`.
    - `topics` object — Contains active topics in your workspace, named `topic_<id>`.

## Response `200`

A successful request returns an empty object response.

## Other responses

- `401` — Unauthorized request. Make sure that you provided the right credentials.

---

[API](https://skmtc.dev/customer/apis/customer-io-journeys-api-reference.md) · [All operations](https://skmtc.dev/customer/apis/customer-io-journeys-api-reference/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/customer/customer-io-journeys-api-reference/revisions/4b391af7cb06/schema)
