Profile

The profile area tells your application who the user is, what they do and which companies they are part of. Some of it is fact, from the user's account; the rest bind.co learns from their mailbox. This guide covers each part, how a person's edits always win, and what to do when bind.co has a newer suggestion.

Reading needs profile:read; editing needs profile:write, which includes profile:read.

Facts and inferred values

The profile area has two kinds of values, and you can tell them apart by their shape:

Resource Facts Inferred by bind.co
The user, GET /v1/profile/user All of it: email, full_name, first_name, family_name, preferred_language, timezone, country, default_currency, phones, address, and company_id None
The user profile, GET /v1/profile/user-profile None title, profession, bio, hero_resume
A company profile, GET /v1/profile/company-profile/{company_id} None company_name, aliases, business_vertical, inc_type, tax_numbers, fiscal_year_end, reporting_currency, hero_resume, address, phones

A company's own record, GET /v1/profile/company/{company_id}, holds facts too: its name from the sign-in provider, its email domain and how it was identified, and any detail a member entered.

A fact the user edited is never overwritten by their account again. GET /v1/oauth2/clients/me gives just the user's id and email, for when that is all you need.

The user profile

{
  "user_id": "usr_0d6f2a4e-5b7c-4e1d-9a83-2c4b6e8f1a20",
  "title": {"value": "Founder", "bind_inference_confidence": 0.93},
  "profession": {"value": "Graphic Designer", "bind_inference_confidence": 0.88},
  "bio": {"value": "Runs a small brand studio in Boston.", "bind_inference_confidence": 0.71},
  "hero_resume": {"value": "Brand identity and packaging for consumer start-ups.", "bind_inference_confidence": 0.74},
  "truth_updated_at": null,
  "suggestion_updated_at": null
}

title is the user's position (founder, CEO); profession is what they actually do (bookkeeper, graphic designer); hero_resume sums up their work, clients and expertise. Each value has a bind_inference_confidence between 0 and 1, and a value a person saved has 1. truth_updated_at says when a person last saved the profile; null means bind.co still maintains it.

Until bind.co has built the profile, confirm and reset answer 409. Read the profile after consent.granted. If it is not built yet, profile.first_completed arrives when it is. That event is sent once per user, so an application connecting after the profile was built never receives it; for that application the profile is already there.

Companies

A user is linked to one or more companies. POST /v1/profile/company/search lists them, and GET /v1/profile/company/{company_id} gives one company's facts:

A company and its profile are shared by all its members, so one member's edit is everyone's. Only the company's admins and subjects may edit: anyone else gets 403 access_denied. A company the user is not linked to answers 404, whatever its id.

Who has the last word

The same five steps apply to the user profile and to each company profile:

  1. Nobody has saved it. bind.co fills it in and keeps it up to date from the mail.
  2. A person saves it. PATCH saves the fields sent with confidence 1; confirm keeps it exactly as it is. From then on, new mail never changes it.
  3. The mail says something new. bind.co flags a suggestion instead: suggestion_updated_at is set and your endpoint receives profile.suggestion_available.
  4. The person decides. The suggestions route shows each field that differs, both values with their confidence (example below). To accept, PATCH the suggested values. To keep what is saved, confirm. Either clears the suggestion. Doing nothing leaves the saved profile in place, with the suggestion waiting.
  5. Handing it back. reset gives the profile back to bind.co: the saved values stay until the next refresh from the mail, which then updates them like a profile nobody saved.

A suggestion, as the suggestions route returns it:

{
  "suggestion_updated_at": "2026-10-03T07:41:12Z",
  "title": {
    "current": {"value": "Founder", "bind_inference_confidence": 1.0},
    "suggested": {"value": "Founder and CEO", "bind_inference_confidence": 0.86}
  }
}

For your interface: show a "review suggestion" banner when suggestion_updated_at is not null, with the two values side by side and two buttons, accept (PATCH) and keep (confirm). Offer reset only as an explicit "let bind.co manage this again".

Webhooks

{"type": "profile.suggestion_available", "data": {"user_inbox_fetch_id": null, "resource": "company-profile", "company_id": "cmp_3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b"}}

The webhooks guide has every payload. Contacts and roles follow the same suggest-then-decide steps.