Skip to main content

Endpoint

Upsert a company record and optionally link it to an end user. Called automatically when you use identifyCompany().

Authentication

Requires your publishable widget key in the Authorization header:

Request Body

string
required
Your system’s unique identifier for this company.
string
If provided, the user with this external ID is linked to the company.
object
Company attributes. Recognized fields (name, domain, industry, plan, employee_count, signed_up_at, renewal_date, renewal_status, contract_term, payment_terms, on_contract, mrr, arr) are stored in dedicated columns. All other fields are stored in custom_fields.Do not send id, external_id, org_id, created_at, updated_at, health_score, team_size, or last_contacted_at. These are managed by Halo and the endpoint returns HTTP 400 if any of them appear in the body. Use signed_up_at to record the date the company onboarded in your product. See System-managed fields.
object
Structured context entries for AI consumption. Stored in the context jsonb column. Merged with existing context (new keys overwrite).
string
JWT signed with your Identity Secret (HS256). Required when identity verification is enabled for your workspace and a user_id is provided. The token’s user_id claim must match the user_id field. See Identity Verification.

Example

Response:
signed_up_at, created_at, and updated_at are returned as Postgres timestamptz values serialized as ISO 8601 with microsecond precision and a +00:00 offset (the format shown above, e.g. 2026-04-11T12:25:19.492417+00:00, not the ...Z shorthand). created_at and updated_at are read-only Halo-managed timestamps and must not be echoed back into the traits body on subsequent calls. signed_up_at is customer-set and can be updated by sending the new value in traits on a follow-up identify call.

Rejected Traits

These keys trigger HTTP 400 if present in the traits body. See System-managed fields for context.

Behavior

  • If a company with the same company_id exists within your organization, it is updated
  • If it doesn’t exist, it is created
  • If user_id is provided and the user exists, the user is linked to the company
  • Context is merged: existing DB context keys are preserved, new keys are added, matching keys are overwritten
  • The combined size of traits and context must not exceed 50,000 bytes
  • signed_up_at on update uses COALESCE semantics: a new value overwrites, but null is ignored so an integration with a more authoritative date is never wiped.
  • Sending Halo-managed fields (id, external_id, org_id, created_at, updated_at, health_score, team_size, last_contacted_at) in traits returns HTTP 400 with a reserved_keys array naming every offending key, so the caller can fix them all in one round trip.