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 is shown on every recipe step and in the API reference, and it already includes the version. It 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. If a row needs attention, the rest can still proceed.
POSThttps://dev-cxi-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: archived people are reactivated, while active duplicates are rejected, 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 to assign assessments in the next step. Rejected rows have none.
How identity worksPOSThttps://dev-cxi-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://dev-cxi-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://dev-cxi-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://dev-cxi-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://dev-cxi-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, which is not available to org-scoped calls. Enrol the resolved person into your tenant as a candidate, with relationshipType candidate rather than employee, before you assign the assessment.
How identity worksPOSThttps://dev-cxi-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://dev-cxi-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
The person must complete and submit the assessment 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 until the assignment status is COMPLETED. A scored result becomes available only once the person has submitted the assessment (the previous step), not from the assignment being created.
GEThttps://dev-cxi-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://dev-cxi-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" } - 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://dev-cxi-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 requires enrolment. 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://dev-cxi-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. Completing it is something only they can do. It cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://dev-cxi-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" } - 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://dev-cxi-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 requires enrolment. 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://dev-cxi-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. Completing it is something only they can do. It cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://dev-cxi-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" } - 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://dev-cxi-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 requires enrolment. 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://dev-cxi-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. Completing it is something only they can do. It cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://dev-cxi-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" } - 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://dev-cxi-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 requires enrolment. 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://dev-cxi-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. Completing it is something only they can do. It cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://dev-cxi-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" } - 4Open a manager-context conversation
Ask for coaching about the report. The reply streams back (SSE).
POSThttps://dev-cxi-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://dev-cxi-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://dev-cxi-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 is available 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://dev-cxi-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://dev-cxi-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://dev-cxi-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", "strengthsAndWatchouts": [{ "type": "strength", "title": "Fast execution", "description": "The team moves quickly once aligned.", "narrativeContent": null }], "teamProfileSummary": 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://dev-cxi-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://dev-cxi-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://dev-cxi-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://dev-cxi-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://dev-cxi-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://dev-cxi-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://dev-cxi-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", "strengthsAndWatchouts": [{ "type": "strength", "title": "Fast execution", "description": "The team moves quickly once aligned.", "narrativeContent": null }], "teamProfileSummary": 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. This is 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 instead: 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://dev-cxi-api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "jonah.pierce@acme.com" } - 3Assign the assessment on day one
Assign the behaviour assessment straight away, so a profile exists before their first week.
POSThttps://dev-cxi-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. Completing it is something only they can do. It cannot be triggered on their behalf through the API, and until then it returns 404 ("No scored assessment found for this individual").
GEThttps://dev-cxi-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" } - 5Add them to their team
Optionally group the joiner with their team to read the dynamic they are joining.
POSThttps://dev-cxi-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://dev-cxi-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 requires enrolment. 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://dev-cxi-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. Completing it is something only they can do. 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://dev-cxi-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" } - 4Read the new team's dynamic
Check the fit with the team they are joining.
GEThttps://dev-cxi-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", "strengthsAndWatchouts": [{ "type": "strength", "title": "Fast execution", "description": "The team moves quickly once aligned.", "narrativeContent": null }], "teamProfileSummary": 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://dev-cxi-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 requires enrolment. 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://dev-cxi-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. Completing it is something only they can do. 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://dev-cxi-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" } - 4Read the team dynamic
See how the team's balance shifts once they leave.
GEThttps://dev-cxi-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", "strengthsAndWatchouts": [{ "type": "strength", "title": "Fast execution", "description": "The team moves quickly once aligned.", "narrativeContent": null }], "teamProfileSummary": null }
These are starting points, not the full set.