API
API Reference
Customer
Update Customer

Update Customer

Update an existing customer in Customerscore.io.

For interactive API documentation, see the Swagger reference (opens in a new tab).

Endpoint

MethodURL
PUThttps://api.customerscore.io/api/v1/customer/{customerExternalId}

Path Parameters

ParameterTypeRequiredDescription
customerExternalIdstringYesCustomer external ID

Request Body

All fields in the request body are optional. Only include the fields you want to update.

FieldTypeRequiredDescription
namestringNoCustomer name
is_churnedbooleanNoFlag indicating if the customer has churned
is_unsubscribedbooleanNoFlag indicating if the customer is unsubscribed
churned_datestringNoDate when the customer churned in ISO8601 format (YYYY-MM-DD)
owner_emailstringNoOwner email address. If provided, updates the customer owner to the user with this email
parent_external_idstring | nullNoexternal_id of the parent company. See Setting the parent company
attributesobjectNoAttribute values keyed by property codename. See Updating attributes

Setting the parent company

parent_external_id places the customer under another customer in the company hierarchy — the parent/subsidiary tree shown on the Hierarchy tab of a customer's detail. It holds the external_id of the parent, not its name or internal ID.

{
  "parent_external_id": "acme-group"
}
Value sentResult
field omittedThe current parent company is left untouched
"some-external-id"That customer becomes the parent company
null or ""The parent company is removed

The request fails with 400 and nothing is written when the link cannot be used:

  • parent_external_id matches no customer in your account
  • it is the customer itself
  • it would create a cycle (A under B while B is already under A)
  • the resulting chain would be deeper than 10 levels

Good to know

  • Only companies participate. A contact is never accepted as a parent company, even when it shares an external_id with a customer.
  • A hierarchy synced from a CRM wins. If your account syncs company hierarchy from HubSpot, the next sync overwrites what you set here — exactly like an attribute fed by a data source.
  • To link many customers at once, use parent_external_id on the customers upload endpoint instead of one request per customer.

Updating attributes

Attributes are addressed by their codename (the identifier you set when creating the attribute in Settings → Attributes), not by name or ID.

{
  "attributes": {
    "plan": "enterprise",
    "renewal_date": "2027-03-31",
    "seats": 250
  }
}

Which attributes can be updated

Attributes can be updated regardless of their data source — the API always takes precedence. This includes attributes fed by another source (HubSpot, Stripe, a file import, …). The attribute keeps its data source, so the next sync from that source overwrites the value again.

These are rejected:

  • Metrics — metrics are time-series values and are written via the customers upload endpoint
  • Calculated attributes — they are derived from other attributes and are recalculated automatically
  • Contact properties — use the contact endpoint instead

All-or-nothing

Validation covers the whole request. If any codename is unknown or any value does not match its attribute type, the request fails with 400 and nothing is written — neither the other attributes nor the core fields in the same request.

Value formats

Attribute typeAccepted JSON value
STRINGstring
NUMBERnumber (not a numeric string)
BOOLboolean (not "true" / "false")
DATEstring, ISO 8601 YYYY-MM-DD, or a Unix timestamp in seconds or milliseconds (the time is dropped, only the day is kept)
TIMESTAMPUnix timestamp in seconds or milliseconds (number or numeric string), or an ISO 8601 string such as 2026-12-22T10:30:00Z; stored with hours and minutes in your account's timezone (an ISO string without an offset is read as already being in that timezone)
URLstring
EMAILstring, a valid email address

Send null to clear a value. The attribute keeps existing on the customer with an empty value; it is not removed.

Good to know

  • The next import overwrites a manually set value. This endpoint edits the current value; it does not pin it. When the attribute's data source (if other than API) syncs again, whatever that source reports wins.
  • Health and fit scores are not recalculated. The new value is used from the next data snapshot onwards.
  • The change is recorded in the customer's attribute change log and can trigger Attribute change alerts on the next alert run.
  • name and attributes.name refer to the same attribute, so sending both with different values is rejected.
  • parent_external_id is validated before anything else is written, so a rejected link leaves the rest of the request unapplied too.

Example Request

curl -X PUT "https://api.customerscore.io/api/v1/customer/12345" \
  -H "Content-Type: application/json" \
  -H "customerscore-key: your-generated-key" \
  -d '{
    "name": "Acme Corporation",
    "owner_email": "[email protected]",
    "attributes": {
      "plan": "enterprise",
      "renewal_date": "2027-03-31",
      "seats": 250
    }
  }'

Response Codes

CodeDescription
200The customer has been successfully updated
400Bad request - malformed body, unknown or ineligible attribute codename, a value of the wrong type, or an unusable parent_external_id
401Unauthorized - Missing customerscore-key in the header
403Forbidden - Invalid key
404Customer not found
405Method Not Allowed - Only PUT method is allowed
406Not Acceptable
490Unconfigured scoring - the account has no scoring profile set up yet
491Account blocked