People
Add, change and remove your organisation's people from your own system, and withdraw an invitation that has not been taken up.
This page is for the developer keeping your organisation's people in InMyWords in step with another system.
It covers listing, adding, changing and removing people, withdrawing an invitation, and the rules every change follows.
Before you start
Calls go to https://app.inmywords.chat/api/integrations/v1/, and every request carries the connection's key: Authorization: Bearer imw_<64 hex characters>
Reading people needs the scope users:read. Adding, changing and removing people, and withdrawing an invitation, need users:write.
- Formats. Ids are strings of digits, such as
"1842". Times are ISO 8601 in UTC. Field names are snake_case. - Answers. One item comes back as
{"data": {...}}. A list comes back as{"data": [...], "next_cursor": "..."}, andnext_cursoris null on the last page. - Lists. A list takes
limit(default 50, at most 100; a larger value is reduced to 100) andcursor.GET /usersalso takesupdated_since, an ISO 8601 time, and returns the people changed since then, a move between groups included.GET /invitationsdoes not take it and answers 400invalid_request. Alimit,cursororupdated_sincethat cannot be read answers 400invalid_request. - Retrying safely. A POST takes an
Idempotency-Keyheader. The same key with the same body within 24 hours answers the first result; the same key with another body answers 422idempotency_key_reused.
Endpoints
| Method | Path | Scope |
|---|---|---|
| GET | /users | users:read |
| GET | /users/{id} | users:read |
| POST | /users | users:write |
| PATCH | /users/{id} | users:write |
| DELETE | /users/{id} | users:write |
| GET | /invitations | users:read |
| DELETE | /invitations/{id} | users:write |
What a person holds
| Field | Type | Notes |
|---|---|---|
id | string | |
email | string | |
display_name | string or null | The name shown on a conversation. |
job_title | string or null | |
group_id | string or null | The person's one group; null for none. |
disabled | boolean | A disabled person cannot sign in. |
last_sign_in | time or null | Null if they have never signed in. |
joined_at | time | When they joined your organisation. |
{
"data": {
"id": "1842",
"email": "[email protected]",
"display_name": "Morag Ross",
"job_title": "Housing officer",
"group_id": "57",
"disabled": false,
"last_sign_in": "2026-10-02T09:14:31Z",
"joined_at": "2026-03-11T15:02:09Z"
}
}
What an invitation holds
| Field | Type |
|---|---|
id | string |
email | string |
invited_at | time |
expires_at | time |
List people
curl "https://app.inmywords.chat/api/integrations/v1/users?limit=100" \
-H "Authorization: Bearer imw_..."
Read one person
curl https://app.inmywords.chat/api/integrations/v1/users/1842 \
-H "Authorization: Bearer imw_..."
Add a person
The body takes email, and optionally display_name, job_title and group_id. What happens next depends on the address.
- An address with no account. An account is made, and the person is emailed a link to set their own password. The answer is 201 with
"status": "created". - An address whose account belongs to no organisation. The person is invited, and nothing changes until they accept. The answer is 202 with
"status": "invited"and the invitation. - An address whose account belongs to another organisation. The answer is 409
in_another_organisation. - An address already in your organisation. The answer is 200 with the person.
A person added this way takes a seat on your organisation's plan like anybody else.
Adding people sends email: an account made gets a link to set a password, and an invited account gets an invitation. A connection may cause 50 such emails an hour. The next answers 429 rate_limited with Retry-After in seconds, and nothing is made. An address already in your organisation sends nothing.
curl -X POST https://app.inmywords.chat/api/integrations/v1/users \
-H "Authorization: Bearer imw_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d8e-7b1a-4c55-9a0e-1f2b3c4d5e6f" \
-d '{"email": "[email protected]", "display_name": "Morag Ross", "job_title": "Housing officer", "group_id": "57"}'
{
"status": "created",
"data": {
"id": "1842",
"email": "[email protected]",
"display_name": "Morag Ross",
"job_title": "Housing officer",
"group_id": "57",
"disabled": false,
"last_sign_in": null,
"joined_at": "2026-10-03T10:21:44Z"
}
}
{
"status": "invited",
"data": {
"id": "311",
"email": "[email protected]",
"invited_at": "2026-10-03T10:21:44Z",
"expires_at": "2026-10-10T10:21:44Z"
}
}
Change a person
The body takes any of display_name, job_title, group_id (null for none) and disabled. Anything you leave out stays as it is.
Setting disabled to true stops the person signing in. Setting it back to false lets them sign in again.
curl -X PATCH https://app.inmywords.chat/api/integrations/v1/users/1842 \
-H "Authorization: Bearer imw_..." \
-H "Content-Type: application/json" \
-d '{"job_title": "Senior housing officer", "group_id": "61"}'
Remove a person
Removing a person takes them out of your organisation and out of its group. Their account still exists, and the API never erases a person's data. The answer is 204 with no body.
curl -X DELETE https://app.inmywords.chat/api/integrations/v1/users/1842 \
-H "Authorization: Bearer imw_..."
Invitations
GET /invitations lists the invitations not yet accepted. DELETE /invitations/{id} withdraws one, and the answer is 204 with no body.
curl -X DELETE https://app.inmywords.chat/api/integrations/v1/invitations/311 \
-H "Authorization: Bearer imw_..."
What the API does not do
- Send a password reset link.
- Remove a person's authenticator or passkeys.
- Erase a person.
These are done in InMyWords, by a person in your organisation.
Rules on every change
- One group each. A person is in one group at most.
- Some permissions cannot be given. Setting a person's group to one that holds
manage_users,manage_billing,manage_integrationsormanage_groupsanswers 403permission_not_grantable. - Somebody can always manage people. Your organisation always keeps at least one enabled person in a group that holds
manage_users. Moving, disabling or removing the last such person answers 409last_people_manager. Two requests that arrive together are taken one after the other, so they cannot both pass this check. - Only your own groups. A group of InMyWords, or of another organisation, answers 404
not_found. - Every change is recorded. Each one is written on your organisation's audit trail under the connection's name.
When something goes wrong
Every error comes back as {"error": {"code": "...", "message": "..."}}.
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | A limit, cursor or updated_since cannot be read, or updated_since was sent to /invitations. |
| 401 | unauthorised | No key, or the key is not valid. |
| 403 | module_off | Integrations are not on for your organisation. |
| 403 | scope_missing | The connection does not hold the scope. |
| 403 | permission_not_grantable | The change would give a person a permission a connection may not give. |
| 404 | not_found | No such person, invitation or group in your organisation. |
| 409 | in_another_organisation | The address belongs to another organisation. |
| 409 | last_people_manager | The change would leave nobody able to manage people. |
| 422 | validation_failed | A field is missing or not valid. |
| 422 | idempotency_key_reused | The key was used with another body. |
| 429 | rate_limited | Too many calls this minute, or 50 emails this hour; wait for Retry-After seconds. |