Use cases by outcome
Real, end-to-end sequences you can copy and adapt. Start with a flagship; the same calls power use cases across the whole employee lifecycle.
Start
Before any call: sign in to create a key, then send it as your bearer token. Key issuance lives in the signed-in portal — the public docs never issue one.
- 1Sign in and create a key
Keys are issued in the signed-in portal. Create one and copy it once — you will not see it again.
Request access - 2Keep it server-side
Set the key as an environment variable on your backend. Never ship it to the browser.
Requestexport THOMAS_KEY="sk_live_…"
- 3Send it on every call
Pass the key as a bearer token on each request. The base URL (shown on every recipe step and in the API reference — it already includes the version) is your one source of truth; set it once as $THOMAS_API_URL. Each key carries only the scopes it needs — no key grants bulk access to raw scoring or the item bank.
Requestcurl "$THOMAS_API_URL/company-individuals" \ -H "Authorization: Bearer $THOMAS_KEY"
Day one: bring your directory into Thomas and trigger everyone's first assessment, so profiles exist before you build anything on top. About 100 batched calls for 10,000 people, not 10,000.
- 1Validate a batch first (dry run)
Send up to 100 rows to validate. Nothing is written — you get a per-row classification (ready, reactivate or rejected) and a summary, so one bad row never blocks the rest.
POSThttps://api.thomas.co/v1/colleagues/bulk/validateRequestPOST /colleagues/bulk/validate { "rows": [{ "email": "alex@acme.com" }] }Response{ "summary": { "ready": 98, "reactivate": 2, "rejected": 0 }, "results": [{ "index": 0, "email": "alex@acme.com", "classification": "ready", "archivedProfile": { "id": "00000000-0000-4000-8000-000000000081", "firstName": "Alex", "lastName": "Taylor" } }] } - 2Commit the batch
Send the confirmed rows. Idempotent by email: people you already have reactivate instead of duplicating, so re-syncing your directory nightly is safe. Email is the persistent identity key; an HRIS id is scoped to your org. Each created or reactivated row returns its individualId; collect those (rejected rows have none) to assign assessments in the next step.
How identity worksPOSThttps://api.thomas.co/v1/colleagues/bulkRequestPOST /colleagues/bulk { "rows": [{ "email": "alex@acme.com", "classification": "ready" }] }Response{ "created": 98, "reactivated": 2, "rejected": 0, "details": [{ "index": 0, "email": "alex@acme.com", "status": "created", "individualId": "00000000-0000-4000-8000-000000000021" }] } - 3Trigger assessments in bulk
Assign the behaviour assessment to up to 100 individuals per call. Already-assessed people are skipped, so it is safe to re-run.
POSThttps://api.thomas.co/v1/assessments/assignments/bulkRequestPOST /assessments/assignments/bulk { "individualIds": ["00000000-0000-4000-8000-000000000021"], "assessmentType": "behaviour" }Response{ "created": 1, "skipped": 0, "results": [{ "id": "00000000-0000-4000-8000-000000000031", "tenantId": "00000000-0000-4000-8000-000000000001", "individualId": "00000000-0000-4000-8000-000000000021", "assessmentType": "behaviour", "assignedBy": "00000000-0000-4000-8000-000000000011", "assignedAt": "2026-10-01T00:00:00.000Z", "status": "PENDING", "createdAt": "2026-10-01T00:00:00.000Z", "updatedAt": "2026-10-01T00:00:00.000Z" }] } - 4Poll an assignment until complete
Poll each assignment until its status is COMPLETED, then read the profile.
GEThttps://api.thomas.co/v1/assessments/assignments/{id}RequestGET /assessments/assignments/00000000-0000-4000-8000-000000000031
Response{ "id": "00000000-0000-4000-8000-000000000031", "tenantId": "00000000-0000-4000-8000-000000000001", "individualId": "00000000-0000-4000-8000-000000000021", "assessmentType": "behaviour", "assignedBy": "00000000-0000-4000-8000-000000000011", "assignedAt": "2026-10-01T00:00:00.000Z", "status": "PENDING", "createdAt": "2026-10-01T00:00:00.000Z", "updatedAt": "2026-10-01T00:00:00.000Z" } - 5List assignments to track progress
List assignments to see how many have completed across the batch.
GEThttps://api.thomas.co/v1/assessments/assignmentsRequestGET /assessments/assignments?status=COMPLETED
Response{ "data": [{ "id": "00000000-0000-4000-8000-000000000031", "tenantId": "00000000-0000-4000-8000-000000000001", "individualId": "00000000-0000-4000-8000-000000000021", "assessmentType": "behaviour", "assignedBy": "00000000-0000-4000-8000-000000000011", "assignedAt": "2026-10-01T00:00:00.000Z", "status": "COMPLETED", "createdAt": "2026-10-01T00:00:00.000Z", "updatedAt": "2026-10-02T09:30:00.000Z" }], "total": 87 } - 6React to completion (webhook)Coming soon
A result webhook (an assessment.completed event) is coming soon. Until then, poll the assignment status as above.
People & profiles
Trigger a Thomas assessment for one person (a candidate who applies, or an employee), then read their behaviour profile.
- 1Resolve the person
Resolve a candidate or employee to one Thomas identity by email — the persistent, case-insensitive identity key — or by your org-scoped HRIS id. Prefer not to send an email? Resolve by your own opaque partner reference instead.
How identity worksPOSThttps://api.thomas.co/v1/individuals/resolveRequestPOST /individuals/resolve { "email": "alex@acme.com" }Response{ "individualId": "00000000-0000-4000-8000-000000000021", "created": true } - 2Enrol as a candidate
Resolve returns a global identity with no tenant membership, so an org-scoped call would reject it. Enrol the resolved person into your tenant as a candidate — relationshipType candidate, never employee — before you assign the assessment.
How identity worksPOSThttps://api.thomas.co/v1/company-individualsRequestPOST /company-individuals { "individualId": "00000000-0000-4000-8000-000000000021", "role": "viewer", "relationshipType": "candidate" } - 3Assign the assessment
Assign the behaviour assessment to the resolved individual.
POSThttps://api.thomas.co/v1/assessments/assignmentsRequestPOST /assessments/assignments { "individualId": "00000000-0000-4000-8000-000000000021", "assessmentType": "behaviour" }Response{ "id": "00000000-0000-4000-8000-000000000031", "tenantId": "00000000-0000-4000-8000-000000000001", "individualId": "00000000-0000-4000-8000-000000000021", "assessmentType": "behaviour", "assignedBy": "00000000-0000-4000-8000-000000000011", "assignedAt": "2026-10-01T00:00:00.000Z", "status": "PENDING", "createdAt": "2026-10-01T00:00:00.000Z", "updatedAt": "2026-10-01T00:00:00.000Z" } - 4The person completes the assessment
Now the person takes the assessment. They complete and submit it themselves in Thomas — the API cannot start, complete, or score it on their behalf. Their behaviour profile becomes available only once they have finished and it has been scored; until then the profile read below returns 404 ("No scored assessment found for this individual").
- 5Poll the assignment
Poll the assignment until its status is COMPLETED. That status flips only once the person has submitted the assessment (the previous step) — not from the assignment being created.
GEThttps://api.thomas.co/v1/assessments/assignments/{id}RequestGET /assessments/assignments/00000000-0000-4000-8000-000000000031
Response{ "id": "00000000-0000-4000-8000-000000000031", "tenantId": "00000000-0000-4000-8000-000000000001", "individualId": "00000000-0000-4000-8000-000000000021", "assessmentType": "behaviour", "assignedBy": "00000000-0000-4000-8000-000000000011", "assignedAt": "2026-10-01T00:00:00.000Z", "status": "COMPLETED", "resultId": "00000000-0000-4000-8000-000000000041", "createdAt": "2026-10-01T00:00:00.000Z", "updatedAt": "2026-10-02T09:30:00.000Z" } - 6Read the behaviour profile
Once the person has completed the assessment and it has been scored, fetch their validated behaviour profile. Before a scored result exists this returns 404 ("No scored assessment found for this individual").
GEThttps://api.thomas.co/v1/assessments/profile/{individualId}RequestGET /assessments/profile/00000000-0000-4000-8000-000000000021
Response{ "connectionPowerType": "action", "traitSpectrums": [ { "dimension": "D", "name": "Dominance", "leftPole": "Accommodating", "rightPole": "Direct", "position": 82, "band": "High" }, { "dimension": "I", "name": "Influence", "leftPole": "Reflective", "rightPole": "Outgoing", "position": 61, "band": "High" }, { "dimension": "S", "name": "Steadiness", "leftPole": "Spontaneous", "rightPole": "Methodical", "position": 34, "band": "Low" }, { "dimension": "C", "name": "Compliance", "leftPole": "Pragmatist", "rightPole": "Perfectionist", "position": 47, "band": "Low" } ], "selfImageScores": { "d": 78, "i": 55, "s": 30, "c": 41 }, "discAdvanced": { "workMaskScores": { "d": 71, "i": 60, "s": 28, "c": 44 }, "underPressureScores": { "d": 66, "i": 52, "s": 35, "c": 49 } }, "scoredAt": "2026-10-02T09:30:00.000Z", "soloInsights": [{ "topic": { "id": "00000000-0000-4000-8000-000000000051", "assessmentType": "behaviour", "slug": "communication-style", "label": "Communication style", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }, "entries": [{ "id": "00000000-0000-4000-8000-000000000061", "topicId": "00000000-0000-4000-8000-000000000051", "contentType": "markdown", "mappingKey": "action-profile", "mappingGranularity": "profile", "title": "Lead with action", "body": "Start with the outcome, then agree clear next steps.", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }] }] } - 7React to completion (webhook)Coming soon
Result webhooks (an assessment.completed event) are coming soon. For now, poll the assignment status.
Pull a person's profile into your review screen, so a manager sees how to get the best from them, not just a rating.
- 1Resolve the person
Resolve the reviewee to one Thomas identity by email — the persistent identity key — or by your org-scoped HRIS id.
How identity worksPOSThttps://api.thomas.co/v1/individuals/resolveRequestPOST /individuals/resolve { "email": "alex@acme.com" }Response{ "individualId": "00000000-0000-4000-8000-000000000021", "created": true } - 2Enrol as a colleague
Resolve returns a global identity with no tenant membership, so the profile read would reject it. Enrol the reviewee as a colleague — createColleague resolves and enrols by email in one call, as relationshipType employee — before you read their profile.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com" } - 3Read the behaviour profile
Fetch the trait spectrums and the "how to work with this person" insight. This reads only once the person has completed a Thomas behaviour assessment — something they do themselves; it cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://api.thomas.co/v1/assessments/profile/{individualId}RequestGET /assessments/profile/00000000-0000-4000-8000-000000000021
Response{ "connectionPowerType": "energy", "traitSpectrums": [ { "dimension": "D", "name": "Dominance", "leftPole": "Accommodating", "rightPole": "Direct", "position": 58, "band": "High" }, { "dimension": "I", "name": "Influence", "leftPole": "Reflective", "rightPole": "Outgoing", "position": 64, "band": "High" }, { "dimension": "S", "name": "Steadiness", "leftPole": "Spontaneous", "rightPole": "Methodical", "position": 41, "band": "Low" }, { "dimension": "C", "name": "Compliance", "leftPole": "Pragmatist", "rightPole": "Perfectionist", "position": 38, "band": "Low" } ], "selfImageScores": { "d": 62, "i": 70, "s": 44, "c": 38 }, "discAdvanced": { "workMaskScores": { "d": 58, "i": 66, "s": 49, "c": 41 }, "underPressureScores": { "d": 64, "i": 61, "s": 40, "c": 45 } }, "scoredAt": "2026-10-02T09:30:00.000Z", "soloInsights": [{ "topic": { "id": "00000000-0000-4000-8000-000000000052", "assessmentType": "behaviour", "slug": "collaboration-style", "label": "Collaboration style", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }, "entries": [{ "id": "00000000-0000-4000-8000-000000000062", "topicId": "00000000-0000-4000-8000-000000000052", "contentType": "markdown", "mappingKey": "energy-profile", "mappingGranularity": "profile", "title": "Keep the conversation lively", "body": "Use discussion and visible momentum to build alignment.", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }] }] } - 4Render the insight in your review UIyour system
Show the trait spectrums and the "how to work with this person" insight alongside the manager's ratings — in your own review screen.
Surface how to communicate with a specific person, right where the conversation already happens.
- 1Resolve the person
Resolve the person to one Thomas identity by email — the persistent identity key — or by your org-scoped HRIS id.
How identity worksPOSThttps://api.thomas.co/v1/individuals/resolveRequestPOST /individuals/resolve { "email": "alex@acme.com" }Response{ "individualId": "00000000-0000-4000-8000-000000000021", "created": true } - 2Enrol as a colleague
Resolve returns a global identity with no tenant membership, so the profile read would reject it. Enrol the person as a colleague — createColleague resolves and enrols by email in one call, as relationshipType employee — before you read their profile.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com" } - 3Read the behaviour profile
Fetch the trait spectrums and the "how to work with this person" insight. This reads only once the person has completed a Thomas behaviour assessment — something they do themselves; it cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://api.thomas.co/v1/assessments/profile/{individualId}RequestGET /assessments/profile/00000000-0000-4000-8000-000000000021
Response{ "connectionPowerType": "energy", "traitSpectrums": [ { "dimension": "D", "name": "Dominance", "leftPole": "Accommodating", "rightPole": "Direct", "position": 58, "band": "High" }, { "dimension": "I", "name": "Influence", "leftPole": "Reflective", "rightPole": "Outgoing", "position": 64, "band": "High" }, { "dimension": "S", "name": "Steadiness", "leftPole": "Spontaneous", "rightPole": "Methodical", "position": 41, "band": "Low" }, { "dimension": "C", "name": "Compliance", "leftPole": "Pragmatist", "rightPole": "Perfectionist", "position": 38, "band": "Low" } ], "selfImageScores": { "d": 62, "i": 70, "s": 44, "c": 38 }, "discAdvanced": { "workMaskScores": { "d": 58, "i": 66, "s": 49, "c": 41 }, "underPressureScores": { "d": 64, "i": 61, "s": 40, "c": 45 } }, "scoredAt": "2026-10-02T09:30:00.000Z", "soloInsights": [{ "topic": { "id": "00000000-0000-4000-8000-000000000052", "assessmentType": "behaviour", "slug": "collaboration-style", "label": "Collaboration style", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }, "entries": [{ "id": "00000000-0000-4000-8000-000000000062", "topicId": "00000000-0000-4000-8000-000000000052", "contentType": "markdown", "mappingKey": "energy-profile", "mappingGranularity": "profile", "title": "Keep the conversation lively", "body": "Use discussion and visible momentum to build alignment.", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }] }] } - 4Nudge in your messaging platformyour system
Surface the "how to work with this person" insight in your messaging platform at the right moment.
Recommend the next learning step from a person's profile.
- 1Resolve the person
Resolve the person to one Thomas identity by email — the persistent identity key — or by your org-scoped HRIS id.
How identity worksPOSThttps://api.thomas.co/v1/individuals/resolveRequestPOST /individuals/resolve { "email": "alex@acme.com" }Response{ "individualId": "00000000-0000-4000-8000-000000000021", "created": true } - 2Enrol as a colleague
Resolve returns a global identity with no tenant membership, so the profile read would reject it. Enrol the person as a colleague — createColleague resolves and enrols by email in one call, as relationshipType employee — before you read their profile.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com" } - 3Read the behaviour profile
Fetch the trait spectrums that inform the recommendation. This reads only once the person has completed a Thomas behaviour assessment — something they do themselves; it cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://api.thomas.co/v1/assessments/profile/{individualId}RequestGET /assessments/profile/00000000-0000-4000-8000-000000000021
Response{ "connectionPowerType": "energy", "traitSpectrums": [ { "dimension": "D", "name": "Dominance", "leftPole": "Accommodating", "rightPole": "Direct", "position": 58, "band": "High" }, { "dimension": "I", "name": "Influence", "leftPole": "Reflective", "rightPole": "Outgoing", "position": 64, "band": "High" }, { "dimension": "S", "name": "Steadiness", "leftPole": "Spontaneous", "rightPole": "Methodical", "position": 41, "band": "Low" }, { "dimension": "C", "name": "Compliance", "leftPole": "Pragmatist", "rightPole": "Perfectionist", "position": 38, "band": "Low" } ], "selfImageScores": { "d": 62, "i": 70, "s": 44, "c": 38 }, "discAdvanced": { "workMaskScores": { "d": 58, "i": 66, "s": 49, "c": 41 }, "underPressureScores": { "d": 64, "i": 61, "s": 40, "c": 45 } }, "scoredAt": "2026-10-02T09:30:00.000Z", "soloInsights": [{ "topic": { "id": "00000000-0000-4000-8000-000000000052", "assessmentType": "behaviour", "slug": "collaboration-style", "label": "Collaboration style", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }, "entries": [{ "id": "00000000-0000-4000-8000-000000000062", "topicId": "00000000-0000-4000-8000-000000000052", "contentType": "markdown", "mappingKey": "energy-profile", "mappingGranularity": "profile", "title": "Keep the conversation lively", "body": "Use discussion and visible momentum to build alignment.", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }] }] } - 4Map to learning pathsyour system
Map the profile to paths in your LMS: a doer gets a short video plus a hands-on exercise, not long reading.
Give a manager grounded guidance on each report, on demand.
- 1Resolve the report
Resolve the report to one Thomas identity by email — the persistent identity key — or by your org-scoped HRIS id.
How identity worksPOSThttps://api.thomas.co/v1/individuals/resolveRequestPOST /individuals/resolve { "email": "alex@acme.com" }Response{ "individualId": "00000000-0000-4000-8000-000000000021", "created": true } - 2Enrol as a colleague
Resolve returns a global identity with no tenant membership, so the profile read would reject it. Enrol the report as a colleague — createColleague resolves and enrols by email in one call, as relationshipType employee — before you read their profile.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com" } - 3Read the report's profile
Fetch the trait spectrums and self-image scores that ground the manager's coaching. This reads only once the person has completed a Thomas behaviour assessment — something they do themselves; it cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://api.thomas.co/v1/assessments/profile/{individualId}RequestGET /assessments/profile/00000000-0000-4000-8000-000000000021
Response{ "connectionPowerType": "energy", "traitSpectrums": [ { "dimension": "D", "name": "Dominance", "leftPole": "Accommodating", "rightPole": "Direct", "position": 58, "band": "High" }, { "dimension": "I", "name": "Influence", "leftPole": "Reflective", "rightPole": "Outgoing", "position": 64, "band": "High" }, { "dimension": "S", "name": "Steadiness", "leftPole": "Spontaneous", "rightPole": "Methodical", "position": 41, "band": "Low" }, { "dimension": "C", "name": "Compliance", "leftPole": "Pragmatist", "rightPole": "Perfectionist", "position": 38, "band": "Low" } ], "selfImageScores": { "d": 62, "i": 70, "s": 44, "c": 38 }, "discAdvanced": { "workMaskScores": { "d": 58, "i": 66, "s": 49, "c": 41 }, "underPressureScores": { "d": 64, "i": 61, "s": 40, "c": 45 } }, "scoredAt": "2026-10-02T09:30:00.000Z", "soloInsights": [{ "topic": { "id": "00000000-0000-4000-8000-000000000052", "assessmentType": "behaviour", "slug": "collaboration-style", "label": "Collaboration style", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }, "entries": [{ "id": "00000000-0000-4000-8000-000000000062", "topicId": "00000000-0000-4000-8000-000000000052", "contentType": "markdown", "mappingKey": "energy-profile", "mappingGranularity": "profile", "title": "Keep the conversation lively", "body": "Use discussion and visible momentum to build alignment.", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }] }] } - 4Open a manager-context conversation
Ask for coaching about the report; the reply streams back (SSE).
POSThttps://api.thomas.co/v1/ai-coaching/conversationsRequestPOST /ai-coaching/conversations { "contextTag": "manager", "entryPoint": "prompt_card" }Response{ "id": "00000000-0000-4000-8000-000000000091", "contextTag": "manager", "entryPoint": "prompt_card", "pageId": "individual", "title": "Coaching conversation", "lastMessageAt": "2026-10-02T09:30:00.000Z", "createdAt": "2026-10-02T09:30:00.000Z", "updatedAt": "2026-10-02T09:30:00.000Z" }
Ask Thomas for grounded coaching, in the flow of work. Two calls, and the reply streams back as Server-Sent Events.
- 1Open a coaching conversation
Create a coaching conversation with a context: personal, manager, or org analyst.
POSThttps://api.thomas.co/v1/ai-coaching/conversationsRequestPOST /ai-coaching/conversations { "contextTag": "personal", "entryPoint": "prompt_card" }Response{ "id": "00000000-0000-4000-8000-000000000091", "contextTag": "personal", "entryPoint": "prompt_card", "pageId": "individual", "title": "Coaching conversation", "lastMessageAt": "2026-10-02T09:30:00.000Z", "createdAt": "2026-10-02T09:30:00.000Z", "updatedAt": "2026-10-02T09:30:00.000Z" } - 2Send a message, stream the reply
POST your intent to the conversation. The answer streams back as Server-Sent Events (tokens), not a single JSON body — render it as it arrives.
POSThttps://api.thomas.co/v1/ai-coaching/conversations/{conversationId}/messagesRequestPOST /ai-coaching/conversations/00000000-0000-4000-8000-000000000091/messages { "intent": "How should I prepare for my own performance review?", "clientMessageId": "00000000-0000-4000-8000-000000000031", "pageId": "individual", "pageParams": { "individualId": "00000000-0000-4000-8000-000000000022" }, "entryPoint": "prompt_card" }Responseevent: token data: {"kind":"token","text":"Start by naming what you want out of the review..."} event: done data: {"kind":"done"} - 3Surface it where work happensyour system
Drop the streamed coaching into your review screen, messaging platform, or wherever work already happens.
Teams & connection
Group resolved people into a team and read its dynamic: the spread of connection powers and where to watch out. No single team score here — that is the tracking recipe.
- 1Enrol the team members
Only enrolled colleagues can be grouped into a team — a resolved-but-unenrolled member is rejected. Enrol every member you will reference in the team in one bulk call (resolves and enrols by email, idempotent) as relationshipType employee: send one row per member, then reference each enrolled individual by individualId when you create the team below.
How identity worksPOSThttps://api.thomas.co/v1/colleagues/bulkRequestPOST /colleagues/bulk { "rows": [{ "email": "alex@acme.com", "classification": "ready" }, { "email": "jordan@acme.com", "classification": "ready" }] }Response{ "created": 2, "reactivated": 0, "rejected": 0, "details": [{ "index": 0, "email": "alex@acme.com", "status": "created" }, { "index": 1, "email": "jordan@acme.com", "status": "created" }] } - 2Create the team
Group the resolved individuals into a team.
POSThttps://api.thomas.co/v1/teamsRequestPOST /teams { "name": "Revenue", "memberIndividualIds": ["00000000-0000-4000-8000-000000000021", "00000000-0000-4000-8000-000000000022"] }Response{ "id": "00000000-0000-4000-8000-000000000041", "tenantId": "00000000-0000-4000-8000-000000000001", "name": "Revenue", "teamType": "explicit", "sourceManagerIndividualId": null, "visibility": "visible", "firstSharedAt": null, "needsOwnerAssignment": false, "deletedAt": null, "inactiveAt": null, "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z", "members": [{ "id": "00000000-0000-4000-8000-000000000061", "teamId": "00000000-0000-4000-8000-000000000041", "individualId": "00000000-0000-4000-8000-000000000021", "companyIndividualId": "00000000-0000-4000-8000-000000000031", "tenantId": "00000000-0000-4000-8000-000000000001", "role": "member", "status": "active", "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z" }] } - 3Read the dynamic
Get the power distribution, the dominant power, and strengths/watch-outs. Privacy-safe: a minimum group of three.
GEThttps://api.thomas.co/v1/teams/{teamId}/dynamicsRequestGET /teams/00000000-0000-4000-8000-000000000041/dynamics
Response{ "teamId": "00000000-0000-4000-8000-000000000041", "members": [{ "individualId": "00000000-0000-4000-8000-000000000021", "displayName": "Alex", "connectionPower": "action", "behaviourScales": { "accommodatingDirect": 72, "reflectiveOutgoing": 45, "spontaneousMethodical": 88, "pragmaticPerfectionist": 33 }, "assessmentStatus": "assessed" }], "powerDistribution": { "action": 1, "energy": 0, "stability": 0, "precision": 0 }, "dominantPower": "action", "narrativeContent": null, "strengthsAndWatchouts": [{ "type": "strength", "title": "Fast execution", "description": "The team moves quickly once aligned.", "narrativeContent": null }], "scaleDescriptions": null }
Read a team's connection score and how it is trending across runs.
- 1Enrol the team members
Only enrolled colleagues can be grouped into a team — a resolved-but-unenrolled member is rejected. Enrol every member you will reference in the team in one bulk call (resolves and enrols by email, idempotent) as relationshipType employee: send one row per member, then reference each enrolled individual by individualId when you create the team below.
How identity worksPOSThttps://api.thomas.co/v1/colleagues/bulkRequestPOST /colleagues/bulk { "rows": [{ "email": "alex@acme.com", "classification": "ready" }, { "email": "jordan@acme.com", "classification": "ready" }] }Response{ "created": 2, "reactivated": 0, "rejected": 0, "details": [{ "index": 0, "email": "alex@acme.com", "status": "created" }, { "index": 1, "email": "jordan@acme.com", "status": "created" }] } - 2Create or reuse the team
Group the individuals whose connection you want to track over time.
POSThttps://api.thomas.co/v1/teamsRequestPOST /teams { "name": "Revenue", "memberIndividualIds": ["00000000-0000-4000-8000-000000000021", "00000000-0000-4000-8000-000000000022"] }Response{ "id": "00000000-0000-4000-8000-000000000051", "tenantId": "00000000-0000-4000-8000-000000000001", "name": "Revenue", "teamType": "explicit", "sourceManagerIndividualId": null, "visibility": "visible", "firstSharedAt": null, "needsOwnerAssignment": false, "deletedAt": null, "inactiveAt": null, "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z", "members": [{ "id": "00000000-0000-4000-8000-000000000071", "teamId": "00000000-0000-4000-8000-000000000051", "individualId": "00000000-0000-4000-8000-000000000021", "companyIndividualId": "00000000-0000-4000-8000-000000000031", "tenantId": "00000000-0000-4000-8000-000000000001", "role": "member", "status": "active", "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z" }] } - 3Read the team results page
Get the team results page: the aggregate score, its six-dimension breakdown, and the trend versus prior runs.
GEThttps://api.thomas.co/v1/teams/{teamId}/runs/{runId}/team-results-pageRequestGET /teams/00000000-0000-4000-8000-000000000051/runs/00000000-0000-4000-8000-000000000052/team-results-page
Response{ "teamResult": { "runId": "00000000-0000-4000-8000-000000000052", "teamId": "00000000-0000-4000-8000-000000000051", "dimensions": [{ "dimension": "appreciation", "score": 78, "banding": "MODERATE" }, { "dimension": "belonging", "score": 74, "banding": "MODERATE" }, { "dimension": "cohesion", "score": 64, "banding": "LOW" }, { "dimension": "contribution", "score": 76, "banding": "MODERATE" }, { "dimension": "trust", "score": 82, "banding": "MODERATE" }, { "dimension": "wellbeing", "score": 70, "banding": "MODERATE" }], "overallScore": 72, "overallBanding": "MODERATE", "participantCount": 8, "scoresAvailable": true, "participantsNeeded": 0, "trendDeltas": null, "overallTrend": null, "focusArea": "cohesion" }, "teamName": "Revenue", "teamId": "00000000-0000-4000-8000-000000000051", "teamType": "explicit", "runPeriod": "2026-07", "closedAt": "2026-07-02T10:15:00Z", "availablePeriods": ["2026-07", "2026-04"], "previousResult": null, "narratives": null, "trailingSeries": { "overall": [68, 72], "dimensions": { "appreciation": [74, 78], "belonging": [70, 74], "cohesion": [60, 64], "contribution": [72, 76], "trust": [80, 82], "wellbeing": [68, 70] } }, "viewerHasCompleted": true } - 4Schedule recurring runs (optional)
Optionally configure a recurring cadence so the trend keeps updating on its own.
PUThttps://api.thomas.co/v1/organisation/teams/{teamId}/recurrenceRequestPUT /organisation/teams/00000000-0000-4000-8000-000000000051/recurrence { "interval": "quarterly", "nextRunDate": "2026-10-01T00:00:00.000Z", "enabled": true }Response{ "interval": "quarterly", "nextRunDate": "2026-10-01T00:00:00.000Z", "enabled": true, "measureId": "00000000-0000-4000-8000-000000000071", "teamId": "00000000-0000-4000-8000-000000000051", "recurrencePersisted": true }
Compose or rebalance a team using its connection dynamic.
- 1Enrol the team members
Only enrolled colleagues can be grouped into a team — a resolved-but-unenrolled member is rejected. Enrol every member you will reference in the team in one bulk call (resolves and enrols by email, idempotent) as relationshipType employee: send one row per member, then reference each enrolled individual by individualId when you create the team below.
How identity worksPOSThttps://api.thomas.co/v1/colleagues/bulkRequestPOST /colleagues/bulk { "rows": [{ "email": "alex@acme.com", "classification": "ready" }, { "email": "jordan@acme.com", "classification": "ready" }] }Response{ "created": 2, "reactivated": 0, "rejected": 0, "details": [{ "index": 0, "email": "alex@acme.com", "status": "created" }, { "index": 1, "email": "jordan@acme.com", "status": "created" }] } - 2Create the team
Group the people you are considering into a team.
POSThttps://api.thomas.co/v1/teamsRequestPOST /teams { "name": "Revenue", "memberIndividualIds": ["00000000-0000-4000-8000-000000000021", "00000000-0000-4000-8000-000000000022"] }Response{ "id": "00000000-0000-4000-8000-000000000041", "tenantId": "00000000-0000-4000-8000-000000000001", "name": "Revenue", "teamType": "explicit", "sourceManagerIndividualId": null, "visibility": "visible", "firstSharedAt": null, "needsOwnerAssignment": false, "deletedAt": null, "inactiveAt": null, "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z", "members": [{ "id": "00000000-0000-4000-8000-000000000081", "teamId": "00000000-0000-4000-8000-000000000041", "individualId": "00000000-0000-4000-8000-000000000021", "companyIndividualId": "00000000-0000-4000-8000-000000000031", "tenantId": "00000000-0000-4000-8000-000000000001", "role": "member", "status": "active", "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z" }] } - 3Read the balance
See the power spread and where to add or rebalance. Privacy-safe: a minimum group of three.
GEThttps://api.thomas.co/v1/teams/{teamId}/dynamicsRequestGET /teams/00000000-0000-4000-8000-000000000041/dynamics
Response{ "teamId": "00000000-0000-4000-8000-000000000041", "members": [{ "individualId": "00000000-0000-4000-8000-000000000021", "displayName": "Alex", "connectionPower": "action", "behaviourScales": { "accommodatingDirect": 72, "reflectiveOutgoing": 45, "spontaneousMethodical": 88, "pragmaticPerfectionist": 33 }, "assessmentStatus": "assessed" }], "powerDistribution": { "action": 1, "energy": 0, "stability": 0, "precision": 0 }, "dominantPower": "action", "narrativeContent": null, "strengthsAndWatchouts": [{ "type": "strength", "title": "Fast execution", "description": "The team moves quickly once aligned.", "narrativeContent": null }], "scaleDescriptions": null }
Lifecycle
Weave Thomas across the systems a new joiner touches, personalised to how they work. The one multi-system example: Thomas calls sit alongside your own HRIS, LMS and calendar.
- 1Create the joiner in your HRISyour system
Your HRIS creates the new-hire record — the source event that kicks everything off.
- 2Enrol the joiner as a colleague
Resolve returns a global identity with no tenant membership, so day-one org-scoped calls would reject the joiner. Enrol them as a colleague — createColleague resolves and enrols by email in one call, as relationshipType employee — as soon as their record exists. Email is the persistent identity key.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "jimmy.page@acme.com" } - 3Assign the assessment on day one
Assign the behaviour assessment straight away, so a profile exists before their first week.
POSThttps://api.thomas.co/v1/assessments/assignmentsRequestPOST /assessments/assignments { "individualId": "00000000-0000-4000-8000-000000000022", "assessmentType": "behaviour" }Response{ "id": "00000000-0000-4000-8000-000000000032", "tenantId": "00000000-0000-4000-8000-000000000001", "individualId": "00000000-0000-4000-8000-000000000022", "assessmentType": "behaviour", "assignedBy": "00000000-0000-4000-8000-000000000011", "assignedAt": "2026-10-01T00:00:00.000Z", "status": "PENDING", "createdAt": "2026-10-01T00:00:00.000Z", "updatedAt": "2026-10-01T00:00:00.000Z" } - 4Read their profile
Once completed, pull the profile to personalise everything downstream. This reads only once the person has completed a Thomas behaviour assessment — something they do themselves; it cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://api.thomas.co/v1/assessments/profile/{individualId}RequestGET /assessments/profile/00000000-0000-4000-8000-000000000022
Response{ "connectionPowerType": "action", "traitSpectrums": [ { "dimension": "D", "name": "Dominance", "leftPole": "Accommodating", "rightPole": "Direct", "position": 71, "band": "High" }, { "dimension": "I", "name": "Influence", "leftPole": "Reflective", "rightPole": "Outgoing", "position": 68, "band": "High" }, { "dimension": "S", "name": "Steadiness", "leftPole": "Spontaneous", "rightPole": "Methodical", "position": 39, "band": "Low" }, { "dimension": "C", "name": "Compliance", "leftPole": "Pragmatist", "rightPole": "Perfectionist", "position": 43, "band": "Low" } ], "selfImageScores": { "d": 74, "i": 58, "s": 36, "c": 40 }, "discAdvanced": { "workMaskScores": { "d": 67, "i": 63, "s": 34, "c": 43 }, "underPressureScores": { "d": 78, "i": 52, "s": 41, "c": 48 } }, "scoredAt": "2026-10-02T09:30:00.000Z", "soloInsights": [{ "topic": { "id": "00000000-0000-4000-8000-000000000053", "assessmentType": "behaviour", "slug": "onboarding-style", "label": "Onboarding style", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }, "entries": [{ "id": "00000000-0000-4000-8000-000000000063", "topicId": "00000000-0000-4000-8000-000000000053", "contentType": "markdown", "mappingKey": "action-onboarding", "mappingGranularity": "profile", "title": "Start with quick wins", "body": "Give this joiner visible progress in their first week.", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }] }] } - 5Add them to their team
Optionally group the joiner with their team to read the dynamic they are joining.
POSThttps://api.thomas.co/v1/teamsRequestPOST /teams { "name": "Sales", "memberIndividualIds": ["00000000-0000-4000-8000-000000000022"] }Response{ "id": "00000000-0000-4000-8000-000000000054", "tenantId": "00000000-0000-4000-8000-000000000001", "name": "Sales", "teamType": "explicit", "sourceManagerIndividualId": null, "visibility": "visible", "firstSharedAt": null, "needsOwnerAssignment": false, "deletedAt": null, "inactiveAt": null, "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z", "members": [{ "id": "00000000-0000-4000-8000-000000000091", "teamId": "00000000-0000-4000-8000-000000000054", "individualId": "00000000-0000-4000-8000-000000000022", "companyIndividualId": "00000000-0000-4000-8000-000000000032", "tenantId": "00000000-0000-4000-8000-000000000001", "role": "member", "status": "active", "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z" }] } - 6Recommend learning in your LMSyour system
Map the profile to onboarding paths in your LMS: an Action-led joiner gets short video plus a hands-on exercise, not long written courses.
- 7Book intros in your calendaryour system
Schedule week-one 1:1s in your calendar and surface "how to work with your new teammate" in chat.
- 8React to completion (webhook)Coming soon
Result webhooks (an assessment.completed event) are coming soon. For now, poll the assignment status.
When someone changes role or team, refresh how they fit.
- 1Resolve the person
Resolve the person to one Thomas identity by email — the persistent identity key — or by your org-scoped HRIS id.
How identity worksPOSThttps://api.thomas.co/v1/individuals/resolveRequestPOST /individuals/resolve { "email": "alex@acme.com" }Response{ "individualId": "00000000-0000-4000-8000-000000000021", "created": false } - 2Enrol as a colleague
Resolve returns a global identity with no tenant membership, so the profile read would reject it. Enrol the person as a colleague — createColleague resolves and enrols by email, as relationshipType employee — before you re-read their profile. The move preserves the same identity.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com" } - 3Re-read the profile
The profile persists across the move — same identity, by email or HRIS id. This reads only once the person has completed a Thomas behaviour assessment — something they do themselves; it cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
How identity worksGEThttps://api.thomas.co/v1/assessments/profile/{individualId}RequestGET /assessments/profile/00000000-0000-4000-8000-000000000021
Response{ "connectionPowerType": "energy", "traitSpectrums": [ { "dimension": "D", "name": "Dominance", "leftPole": "Accommodating", "rightPole": "Direct", "position": 58, "band": "High" }, { "dimension": "I", "name": "Influence", "leftPole": "Reflective", "rightPole": "Outgoing", "position": 64, "band": "High" }, { "dimension": "S", "name": "Steadiness", "leftPole": "Spontaneous", "rightPole": "Methodical", "position": 41, "band": "Low" }, { "dimension": "C", "name": "Compliance", "leftPole": "Pragmatist", "rightPole": "Perfectionist", "position": 38, "band": "Low" } ], "selfImageScores": { "d": 62, "i": 70, "s": 44, "c": 38 }, "discAdvanced": { "workMaskScores": { "d": 58, "i": 66, "s": 49, "c": 41 }, "underPressureScores": { "d": 64, "i": 61, "s": 40, "c": 45 } }, "scoredAt": "2026-10-02T09:30:00.000Z", "soloInsights": [{ "topic": { "id": "00000000-0000-4000-8000-000000000052", "assessmentType": "behaviour", "slug": "collaboration-style", "label": "Collaboration style", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }, "entries": [{ "id": "00000000-0000-4000-8000-000000000062", "topicId": "00000000-0000-4000-8000-000000000052", "contentType": "markdown", "mappingKey": "energy-profile", "mappingGranularity": "profile", "title": "Keep the conversation lively", "body": "Use discussion and visible momentum to build alignment.", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }] }] } - 4Read the new team's dynamic
Check the fit with the team they are joining.
GEThttps://api.thomas.co/v1/teams/{teamId}/dynamicsRequestGET /teams/00000000-0000-4000-8000-000000000041/dynamics
Response{ "teamId": "00000000-0000-4000-8000-000000000041", "members": [{ "individualId": "00000000-0000-4000-8000-000000000021", "displayName": "Alex", "connectionPower": "action", "behaviourScales": { "accommodatingDirect": 72, "reflectiveOutgoing": 45, "spontaneousMethodical": 88, "pragmaticPerfectionist": 33 }, "assessmentStatus": "assessed" }], "powerDistribution": { "action": 1, "energy": 0, "stability": 0, "precision": 0 }, "dominantPower": "action", "narrativeContent": null, "strengthsAndWatchouts": [{ "type": "strength", "title": "Fast execution", "description": "The team moves quickly once aligned.", "narrativeContent": null }], "scaleDescriptions": null }
When someone leaves, capture how to work with them for the handover and gauge the team impact.
- 1Resolve the person
Resolve the person to one Thomas identity by email — the persistent identity key — or by your org-scoped HRIS id.
How identity worksPOSThttps://api.thomas.co/v1/individuals/resolveRequestPOST /individuals/resolve { "email": "alex@acme.com" }Response{ "individualId": "00000000-0000-4000-8000-000000000021", "created": false } - 2Enrol as a colleague
Resolve returns a global identity with no tenant membership, so the profile read would reject it. Enrol the person as a colleague — createColleague resolves and enrols by email, as relationshipType employee — before you read their profile for the handover.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com" } - 3Read their profile
Hand over "how to work with them" to whoever picks up their work. This reads only once the person has completed a Thomas behaviour assessment — something they do themselves; it cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
How identity worksGEThttps://api.thomas.co/v1/assessments/profile/{individualId}RequestGET /assessments/profile/00000000-0000-4000-8000-000000000021
Response{ "connectionPowerType": "energy", "traitSpectrums": [ { "dimension": "D", "name": "Dominance", "leftPole": "Accommodating", "rightPole": "Direct", "position": 58, "band": "High" }, { "dimension": "I", "name": "Influence", "leftPole": "Reflective", "rightPole": "Outgoing", "position": 64, "band": "High" }, { "dimension": "S", "name": "Steadiness", "leftPole": "Spontaneous", "rightPole": "Methodical", "position": 41, "band": "Low" }, { "dimension": "C", "name": "Compliance", "leftPole": "Pragmatist", "rightPole": "Perfectionist", "position": 38, "band": "Low" } ], "selfImageScores": { "d": 62, "i": 70, "s": 44, "c": 38 }, "discAdvanced": { "workMaskScores": { "d": 58, "i": 66, "s": 49, "c": 41 }, "underPressureScores": { "d": 64, "i": 61, "s": 40, "c": 45 } }, "scoredAt": "2026-10-02T09:30:00.000Z", "soloInsights": [{ "topic": { "id": "00000000-0000-4000-8000-000000000052", "assessmentType": "behaviour", "slug": "collaboration-style", "label": "Collaboration style", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }, "entries": [{ "id": "00000000-0000-4000-8000-000000000062", "topicId": "00000000-0000-4000-8000-000000000052", "contentType": "markdown", "mappingKey": "energy-profile", "mappingGranularity": "profile", "title": "Keep the conversation lively", "body": "Use discussion and visible momentum to build alignment.", "sortOrder": 1, "createdAt": "2026-09-01T00:00:00.000Z", "updatedAt": "2026-09-01T00:00:00.000Z" }] }] } - 4Read the team dynamic
See the gap their departure leaves in the team's balance.
GEThttps://api.thomas.co/v1/teams/{teamId}/dynamicsRequestGET /teams/00000000-0000-4000-8000-000000000041/dynamics
Response{ "teamId": "00000000-0000-4000-8000-000000000041", "members": [{ "individualId": "00000000-0000-4000-8000-000000000021", "displayName": "Alex", "connectionPower": "action", "behaviourScales": { "accommodatingDirect": 72, "reflectiveOutgoing": 45, "spontaneousMethodical": 88, "pragmaticPerfectionist": 33 }, "assessmentStatus": "assessed" }], "powerDistribution": { "action": 1, "energy": 0, "stability": 0, "precision": 0 }, "dominantPower": "action", "narrativeContent": null, "strengthsAndWatchouts": [{ "type": "strength", "title": "Fast execution", "description": "The team moves quickly once aligned.", "narrativeContent": null }], "scaleDescriptions": null }
These are starting points, not the full set.