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, exchange the client ID and secret Thomas gave you for a short-lived access token. Then send it as your bearer token. Thomas issues credentials to each Partner integration. There is no self-serve sign-up.
- 1Get your client credentials from Thomas
Thomas gives you a client ID and secret for your integration. Keep them on your backend, never in the browser.
Requestexport THOMAS_CLIENT_ID="…" export THOMAS_CLIENT_SECRET="…"
- 2Request a token
The token lasts one hour. There is no refresh token, so request a new one when it expires.
Requestcurl -X POST "$THOMAS_TOKEN_URL" \ -u "$THOMAS_CLIENT_ID:$THOMAS_CLIENT_SECRET" \ -d grant_type=client_credentials
- 3Send it on every call
Pass the token as a bearer token on each request. The base URL is shown on every recipe step, and it already includes the version. It is your one source of truth. Set it once as $THOMAS_API_URL. Most calls also need one Thomas-Tenant-Id header naming the customer they act in. Your Grant carries only the scopes it needs. The token itself carries identity only, and scope authority is checked against the live Grant on every request. No credential grants bulk access to raw scoring or the item bank.
Requestcurl "$THOMAS_API_URL/company-individuals" \ -H "Authorization: Bearer $THOMAS_TOKEN" \ -H "Thomas-Tenant-Id: $THOMAS_TENANT_ID"
Create a customer, sync its people, and, while you are still building, withdraw a test customer and recover it. These three customer-lifecycle calls act above a tenant, so they take no Thomas-Tenant-Id header. Every call you make inside the customer does.
- 1Create the customer
`POST /tenants` creates one customer and returns its `tenantId`. This call acts above a tenant, so it sends no Thomas-Tenant-Id header. There are three outcomes. `created` returns the new customer's `tenantId`. The other two carry no id, deliberately: they tell you nothing about a customer that is not yours. `request_access` means this customer is already on Thomas, so ask your Thomas account manager to arrange access; there is no self-serve route. `admin_resolution_required` means the details you sent match more than one customer, and your Thomas account manager will resolve it with you.
Requestcurl -X POST "$THOMAS_API_URL/tenants" \ -H "Authorization: Bearer $THOMAS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"legalName":"Acme Ltd","countryCode":"GB"}' - 2Sync its people
Now you are working inside the customer, so every call names it in the Thomas-Tenant-Id header. Send up to 100 rows per call. Every row carries your own partnerReference for the person and the sourceVersion of your record. Re-sending a version you already sent replays it, so re-running your directory sync is safe.
How identity worksPOSThttps://api.thomas.co/v1/colleagues/bulkRequestPOST /colleagues/bulk { "rows": [{ "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 }] } - 3Withdraw a test customer
`POST /tenants/{tenantId}/withdraw` withdraws a customer you created, which is the call you want while building against throwaway customers. It acts above a tenant, so it sends no Thomas-Tenant-Id header: the customer is named in the path.
Requestcurl -X POST "$THOMAS_API_URL/tenants/$THOMAS_TENANT_ID/withdraw" \ -H "Authorization: Bearer $THOMAS_TOKEN"
- 4Recover it within 30 days
`POST /tenants/{tenantId}/recover` restores a customer you withdrew, within 30 days, to the exact lifecycle it held before: the customer, its Grant, its Service Membership and its source-of-record claims become live again under their original identities.
Requestcurl -X POST "$THOMAS_API_URL/tenants/$THOMAS_TENANT_ID/recover" \ -H "Authorization: Bearer $THOMAS_TOKEN"
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, each with your partnerReference and sourceVersion. 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://api.thomas.co/v1/colleagues/bulk/validateRequestPOST /colleagues/bulk/validate { "rows": [{ "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 }] }Response{ "results": [ { "index": 0, "partnerReference": "worker-uk-004271", "classification": "ready" } ], "summary": { "ready": 98, "reactivate": 2, "rejected": 0 } } - 2Commit the batch
Send the confirmed rows, each with your partnerReference and sourceVersion. Every row gets its own outcome: created, reconciled (the person was already in the organisation), replayed (you sent this version before), reactivate (an archived profile Thomas offers to restore through the reactivate route) or failed. A failed row leaves the others committed, so retry only the failed rows. Email is the persistent identity key. An HRIS id is scoped to your org. Each created, reconciled or replayed row returns its individualId. Collect those to assign assessments in the next step.
How identity worksPOSThttps://api.thomas.co/v1/colleagues/bulkRequestPOST /colleagues/bulk { "rows": [{ "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 }] }Response{ "results": [ { "index": 0, "partnerReference": "worker-uk-004271", "outcome": "created", "companyIndividualId": "00000000-0000-4000-8000-000000000031", "individualId": "00000000-0000-4000-8000-000000000021", "sourceVersion": 1 } ], "summary": { "created": 98, "reconciled": 2, "replayed": 0, "reactivate": 0, "failed": 0 } } - 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" }], "outcomes": [{ "individualId": "00000000-0000-4000-8000-000000000021", "status": "created" }] } - 4Poll an assignment until complete
Poll each assignment until its status is COMPLETED or EXPIRED, then read the profile of each COMPLETED one.
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, "nextCursor": null } - 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 colleague, then read their behaviour profile.
- 1Resolve the person
Resolve the person 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? Create and update employees with your own partner reference. Thomas matches it within your connection.
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, which is not available to org-scoped calls. Enrol the person as a colleague: createColleague resolves and enrols by email in one call, as relationshipType employee, before you assign the assessment. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 } - 3Assign the assessment
Assign the behaviour assessment to the resolved individual. The assignment call takes a list of individualIds, so send a list of one. A created assignment comes back in results, with the id you poll below.
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" }], "outcomes": [{ "individualId": "00000000-0000-4000-8000-000000000021", "status": "created" }] } - 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 or EXPIRED. A scored result becomes available 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" } - 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 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. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 } - 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://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://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. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 } - 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://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://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. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 } - 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://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. One step acts on behalf of the report, when they choose to share.
- 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 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. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 } - 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://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" } - 4Enrol the manager as a colleague
Enrol the manager in this tenant before the report shares with them. On a created or reconciled result, keep the returned tenant membership UUID for the share recipient in the next step. If Thomas returns a reactivation offer, complete that path before sharing. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "sam.manager@acme.com", "partnerReference": "worker-uk-004273", "sourceVersion": 1 } - 5Let the report share their overview with their manager
Sharing is the report's own choice, so this call is made on behalf of the report, never by your integration as itself. Make it only when the report asks to share, in your product, while you are serving them. Name the report in the Thomas-On-Behalf-Of header, as thomas: followed by their Thomas id, or partner: followed by your own reference for them. Your Grant needs users:w. Set recipientCompanyIndividualId to the manager's tenant membership UUID returned by the preceding enrol step, rather than the global identity returned by resolve. A report cannot share with themselves: that is refused 400. Show person-only data only to that person, and act on their behalf only while you are serving them.
How identity worksPOSThttps://api.thomas.co/v1/share-grantsRequestPOST /share-grants { "mode": "single", "recipientCompanyIndividualId": "00000000-0000-4000-8000-000000000041", "dataType": "behaviour_overview" }Response{ "id": "00000000-0000-4000-8000-000000000051", "tenant_id": "00000000-0000-4000-8000-000000000001", "sharer_company_individual_id": "00000000-0000-4000-8000-000000000022", "recipient_company_individual_id": "00000000-0000-4000-8000-000000000041", "data_type": "behaviour_overview", "source": "voluntary", "recipient_role": "manager", "created_at": "2026-10-02T09:30:00.000Z", "revoked_at": null } - 6Surface the insight to the manageryour system
Only after the report chooses to share and createShareGrant succeeds, show the permitted behaviour overview and guidance to that manager in your own product.
Ask Thomas for grounded coaching for one named person, in the flow of work. Two calls on behalf of that person, and the reply streams back as Server-Sent Events.
- 1Open a coaching conversation
Coaching is always for one named person, never for your integration itself. Name them in the Thomas-On-Behalf-Of header, as thomas: followed by their Thomas id, or partner: followed by your own reference for them. Your Grant needs users:w. The conversation belongs to that person; their permissions and your Grant's users:w scope still apply. Show person-only data only to that person, and act on their behalf only while you are serving them. Pick a context: personal, manager, or org_analyst.
How identity worksPOSThttps://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 the person's intent to the conversation, on behalf of the same person. The answer streams back as Server-Sent Events (tokens), not a single JSON body, so render it as it arrives. A stream cannot be replayed, so do not send an Idempotency-Key here: retry with the same clientMessageId instead. Coaching calls are limited per person and per integration, and a 429 tells you when to try again.
How identity worksPOSThttps://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": "home", "pageParams": {}, "entryPoint": "prompt_card" }Responseevent: metadata data: {"kind":"metadata","mlflowTraceId":"tr-00000000000000000000000000000091","conversationId":"00000000-0000-4000-8000-000000000091","messageId":"00000000-0000-4000-8000-000000000092"} event: token data: {"kind":"token","text":"Start by naming what you want out of the review..."} event: done data: {"kind":"done","outputTokens":42} - 3Surface it where work happensyour system
Drop the streamed coaching into your review screen, messaging platform, or wherever work already happens, for the person you named.
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): send one row per member, each carrying its email, your partnerReference for them and the sourceVersion of your record, 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", "partnerReference": "worker-uk-004271", "sourceVersion": 1 }, { "email": "jordan@acme.com", "partnerReference": "worker-uk-004272", "sourceVersion": 1 }] }Response{ "results": [ { "index": 0, "partnerReference": "worker-uk-004271", "outcome": "created", "companyIndividualId": "00000000-0000-4000-8000-000000000031", "individualId": "00000000-0000-4000-8000-000000000021", "sourceVersion": 1 }, { "index": 1, "partnerReference": "worker-uk-004272", "outcome": "created", "companyIndividualId": "00000000-0000-4000-8000-000000000032", "individualId": "00000000-0000-4000-8000-000000000022", "sourceVersion": 1 } ], "summary": { "created": 2, "reconciled": 0, "replayed": 0, "reactivate": 0, "failed": 0 } } - 2Create the team
Group the resolved individuals into a team. Send your own externalTeamReference in the body: it is recorded against your API client and read back beside the Thomas id, but it is never an address. sourceVersion records which version of your own record this write came from. It is provenance, not an ordering key. List every owner in ownerIndividualIds, because your API client is never added, and keep owners out of memberIndividualIds. Omitting visibility creates the team hidden, which is what the response below shows; send visibility "visible" to share it with its members, and firstSharedAt is stamped the first time you do. Keep the id the response returns: every later call to this team addresses that Thomas team id. Creating again with a reference you have already bound is refused 409, naming the Thomas team it belongs to.
POSThttps://api.thomas.co/v1/teamsRequestPOST /teams { "externalTeamReference": "team-revenue", "sourceVersion": 1, "name": "Revenue", "ownerIndividualIds": ["00000000-0000-4000-8000-000000000021"], "memberIndividualIds": ["00000000-0000-4000-8000-000000000022"] }Response{ "id": "00000000-0000-4000-8000-000000000041", "externalTeamReference": "team-revenue", "tenantId": "00000000-0000-4000-8000-000000000001", "name": "Revenue", "teamType": "explicit", "sourceManagerIndividualId": null, "visibility": "hidden", "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": "owner", "status": "active", "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z" }, { "id": "00000000-0000-4000-8000-000000000062", "teamId": "00000000-0000-4000-8000-000000000041", "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" }] } - 3Read the dynamic
Get the power distribution, the dominant power, and strengths/watch-outs. Privacy-safe: a minimum group of three. Address the team by the Thomas team id the create returned.
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", "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): send one row per member, each carrying its email, your partnerReference for them and the sourceVersion of your record, 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", "partnerReference": "worker-uk-004271", "sourceVersion": 1 }, { "email": "jordan@acme.com", "partnerReference": "worker-uk-004272", "sourceVersion": 1 }] }Response{ "results": [ { "index": 0, "partnerReference": "worker-uk-004271", "outcome": "created", "companyIndividualId": "00000000-0000-4000-8000-000000000031", "individualId": "00000000-0000-4000-8000-000000000021", "sourceVersion": 1 }, { "index": 1, "partnerReference": "worker-uk-004272", "outcome": "created", "companyIndividualId": "00000000-0000-4000-8000-000000000032", "individualId": "00000000-0000-4000-8000-000000000022", "sourceVersion": 1 } ], "summary": { "created": 2, "reconciled": 0, "replayed": 0, "reactivate": 0, "failed": 0 } } - 2Create or reuse the team
Group the individuals whose connection you want to track over time. Send your own externalTeamReference in the body: it is recorded against your API client and read back beside the Thomas id, but it is never an address. sourceVersion records which version of your own record this write came from. It is provenance, not an ordering key. List every owner in ownerIndividualIds, because your API client is never added, and keep owners out of memberIndividualIds. Omitting visibility creates the team hidden, which is what the response below shows; send visibility "visible" to share it with its members, and firstSharedAt is stamped the first time you do. Keep the id it returns: the results and recurrence calls below address the team by that Thomas id. If you have lost which Thomas id your reference maps to, list your teams with listConnectionTeams, following nextCursor until it is null, rather than creating again: a repeat create on a bound reference is refused 409.
POSThttps://api.thomas.co/v1/teamsRequestPOST /teams { "externalTeamReference": "team-revenue", "sourceVersion": 1, "name": "Revenue", "ownerIndividualIds": ["00000000-0000-4000-8000-000000000021"], "memberIndividualIds": ["00000000-0000-4000-8000-000000000022"] }Response{ "id": "00000000-0000-4000-8000-000000000051", "externalTeamReference": "team-revenue", "tenantId": "00000000-0000-4000-8000-000000000001", "name": "Revenue", "teamType": "explicit", "sourceManagerIndividualId": null, "visibility": "hidden", "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": "owner", "status": "active", "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z" }, { "id": "00000000-0000-4000-8000-000000000072", "teamId": "00000000-0000-4000-8000-000000000051", "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" }] } - 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": "2030-01-01T00:00:00.000Z", "enabled": true }Response{ "interval": "quarterly", "nextRunDate": "2030-01-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): send one row per member, each carrying its email, your partnerReference for them and the sourceVersion of your record, 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", "partnerReference": "worker-uk-004271", "sourceVersion": 1 }, { "email": "jordan@acme.com", "partnerReference": "worker-uk-004272", "sourceVersion": 1 }] }Response{ "results": [ { "index": 0, "partnerReference": "worker-uk-004271", "outcome": "created", "companyIndividualId": "00000000-0000-4000-8000-000000000031", "individualId": "00000000-0000-4000-8000-000000000021", "sourceVersion": 1 }, { "index": 1, "partnerReference": "worker-uk-004272", "outcome": "created", "companyIndividualId": "00000000-0000-4000-8000-000000000032", "individualId": "00000000-0000-4000-8000-000000000022", "sourceVersion": 1 } ], "summary": { "created": 2, "reconciled": 0, "replayed": 0, "reactivate": 0, "failed": 0 } } - 2Create the team
Group the people you are considering into a team. Send your own externalTeamReference in the body: it is recorded against your API client and read back beside the Thomas id, but it is never an address. sourceVersion records which version of your own record this write came from. It is provenance, not an ordering key. List every owner in ownerIndividualIds, because your API client is never added, and keep owners out of memberIndividualIds. Omitting visibility creates the team hidden, which is what the response below shows; send visibility "visible" to share it with its members, and firstSharedAt is stamped the first time you do. Keep the id the response returns: every later call to this team addresses that Thomas team id.
POSThttps://api.thomas.co/v1/teamsRequestPOST /teams { "externalTeamReference": "team-revenue", "sourceVersion": 1, "name": "Revenue", "ownerIndividualIds": ["00000000-0000-4000-8000-000000000021"], "memberIndividualIds": ["00000000-0000-4000-8000-000000000022"] }Response{ "id": "00000000-0000-4000-8000-000000000041", "externalTeamReference": "team-revenue", "tenantId": "00000000-0000-4000-8000-000000000001", "name": "Revenue", "teamType": "explicit", "sourceManagerIndividualId": null, "visibility": "hidden", "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": "owner", "status": "active", "createdAt": "2026-07-02T10:00:00.000Z", "updatedAt": "2026-07-02T10:00:00.000Z" }, { "id": "00000000-0000-4000-8000-000000000082", "teamId": "00000000-0000-4000-8000-000000000041", "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" }] } - 3Read the balance
See the power spread and where to add or rebalance. Privacy-safe: a minimum group of three. Address the team by the Thomas team id the create returned.
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", "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. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "jonah.pierce@acme.com", "partnerReference": "worker-uk-004274", "sourceVersion": 1 } - 3Assign the assessment on day one
Assign the behaviour assessment straight away, so a profile exists before their first week. Send the joiner as a one-element individualIds list.
POSThttps://api.thomas.co/v1/assessments/assignments/bulkRequestPOST /assessments/assignments/bulk { "individualIds": ["00000000-0000-4000-8000-000000000022"], "assessmentType": "behaviour" }Response{ "created": 1, "skipped": 0, "results": [{ "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" }], "outcomes": [{ "individualId": "00000000-0000-4000-8000-000000000022", "status": "created" }] } - 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://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 add the joiner to a team you already created, to read the dynamic they are joining. Address it by the Thomas team id you kept from the create. Your own externalTeamReference is not an address, and it comes back on the read. memberIndividualIds is a full replacement set, so send the whole roster including the joiner. Omit ownerIndividualIds to leave the owners unchanged. There is no version to send and no staleness refusal: the last write wins, so serialise your own updates to a team.
PATCHhttps://api.thomas.co/v1/teams/{teamId}RequestPATCH /teams/00000000-0000-4000-8000-000000000054 { "memberIndividualIds": ["00000000-0000-4000-8000-000000000021", "00000000-0000-4000-8000-000000000022"] }Response{ "id": "00000000-0000-4000-8000-000000000054", "externalTeamReference": "team-sales", "tenantId": "00000000-0000-4000-8000-000000000001", "name": "Sales", "teamType": "explicit", "sourceManagerIndividualId": null, "visibility": "hidden", "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-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" }, { "id": "00000000-0000-4000-8000-000000000092", "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 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. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 } - 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://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. Address the team by its Thomas team id; if you only hold your own partner reference for it, list your teams first with listConnectionTeams and read the Thomas id beside it.
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", "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://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. Send your own partnerReference for the person and the sourceVersion of your record with it.
How identity worksPOSThttps://api.thomas.co/v1/colleaguesRequestPOST /colleagues { "email": "alex@acme.com", "partnerReference": "worker-uk-004271", "sourceVersion": 1 } - 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://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. Address the team by its Thomas team id; if you only hold your own partner reference for it, list your teams first with listConnectionTeams and read the Thomas id beside it.
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", "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.