Create a person
Required permissions: people:write.
A person is a name, a title, a note, an email, a LinkedIn username and a photo URL. That is the whole record you can WRITE. Phone numbers are only ever found: POST /v1/people/{id}/enrich looks up an email and/or a phone and the results appear on the person as email (with emailSource: "enrichment") and phone.
note is where sourcing and confidence go. It is free text you own — up to 1000 characters, no structure imposed, stored and returned verbatim and NEVER interpreted by Trayo: not parsed, not indexed, not searchable, not shown in the Trayo UI, and nothing in the product branches on it. "sourced from LinkedIn, unverified, 2026-09-02" is exactly the intended use. Set it here, change or clear it with PATCH /v1/people/{id}, read it back on every people route.
Do not put any of that in title. title is the job title, it is published, and humans and downstream systems read it as a job title — so a value like "VP Sales (UNVERIFIED, sourced from LinkedIn)" is a wrong job title for every reader of it, not an annotated one. That workaround is why note exists.
LinkedIn and email are upsert keys. A create that matches an existing person on either key updates that row with the fields you sent, makes it rep-visible, returns its existing id, and answers 200. A new person answers 201. WHERE Trayo looks depends on what you sent: with an accountId or a company, within THAT account only — the same human under two accounts (an advisor, a dual role) is two records and both are created. With neither, across your whole workspace, because you asked "do you have this person" and the answer must not depend on which account Trayo happens to attach them to. A person with neither key can never upsert. If LinkedIn and email point at two different people, the request is a 409 rather than merging those identities.
linkedinUrl is a source for linkedinUsername, not a decoration. Send either. With no linkedinUsername, the username is taken from the URL and stored, so a POST /v1/find contacts row keeps its LinkedIn identity when posted verbatim. A linkedinUsername you send always wins over the URL.
For a new person, a LinkedIn identity also FILLS the fields you left empty. A new row carrying one is looked up in Trayo's own profile mirror, and whatever it finds is used for title and photoUrl when you sent neither, and for the account link when you sent neither accountId nor company — so the response can carry a title, a profileImageUrl and an accountId you never supplied, and a company Trayo does not already have becomes a NEW account under the same name-only rule below. It never overwrites a value you DID send, and it is best-effort: a lookup that misses or takes too long creates the row exactly as you sent it rather than failing it. Supply the fields yourself to keep control of them; there is no other way to opt out. A strong-key upsert writes only fields you sent; it never copies these profile values onto the match.
Note isRepVisible on the response: it comes back true. Creating a person here counts as a deliberate human add, the same as adding one by hand in the app, so the record surfaces to reps. You cannot send the field and you cannot turn it off.
accountId and company are mutually exclusive ways to link the new person to an account — send at most one, or neither to create an unlinked person.
Company auto-link. company: { name } finds-or-creates the linked account by name, case-insensitive, within your workspace. A match reuses the existing account and company.domain is ignored. company.domain takes a bare host or a full website URL; the account is created at https://<host> either way, and a value that is not a usable hostname is refused — validation_failed, param: "company.domain".
A company that does NOT already exist is created anyway — with an empty url when you sent no company.domain, so a name-only row still gets an account rather than being refused. Supply company.domain when you have one so the new account gets a real url. Look up whether an account already exists, and get its id for the accountId route, with GET /v1/accounts?q=<company name>.
Request
- Base URL: https://api.trayo.ai
- URL: https://api.trayo.ai/v1/people
- Auth: HTTP bearer
Request body
Response
Existing person updated.
Changes
No recorded changes to this operation across all 1 revision of this API.