Integrations

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.

  1. Formats. Ids are strings of digits, such as "1842". Times are ISO 8601 in UTC. Field names are snake_case.
  2. Answers. One item comes back as {"data": {...}}. A list comes back as {"data": [...], "next_cursor": "..."}, and next_cursor is null on the last page.
  3. Lists. A list takes limit (default 50, at most 100; a larger value is reduced to 100) and cursor. GET /users also takes updated_since, an ISO 8601 time, and returns the people changed since then, a move between groups included. GET /invitations does not take it and answers 400 invalid_request. A limit, cursor or updated_since that cannot be read answers 400 invalid_request.
  4. Retrying safely. A POST takes an Idempotency-Key header. The same key with the same body within 24 hours answers the first result; the same key with another body answers 422 idempotency_key_reused.

Endpoints

MethodPathScope
GET/usersusers:read
GET/users/{id}users:read
POST/usersusers:write
PATCH/users/{id}users:write
DELETE/users/{id}users:write
GET/invitationsusers:read
DELETE/invitations/{id}users:write

What a person holds

FieldTypeNotes
idstring
emailstring
display_namestring or nullThe name shown on a conversation.
job_titlestring or null
group_idstring or nullThe person's one group; null for none.
disabledbooleanA disabled person cannot sign in.
last_sign_intime or nullNull if they have never signed in.
joined_attimeWhen 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

FieldType
idstring
emailstring
invited_attime
expires_attime

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.

  1. 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".
  2. 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.
  3. An address whose account belongs to another organisation. The answer is 409 in_another_organisation.
  4. 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

  1. Send a password reset link.
  2. Remove a person's authenticator or passkeys.
  3. Erase a person.

These are done in InMyWords, by a person in your organisation.

Rules on every change

  1. One group each. A person is in one group at most.
  2. Some permissions cannot be given. Setting a person's group to one that holds manage_users, manage_billing, manage_integrations or manage_groups answers 403 permission_not_grantable.
  3. 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 409 last_people_manager. Two requests that arrive together are taken one after the other, so they cannot both pass this check.
  4. Only your own groups. A group of InMyWords, or of another organisation, answers 404 not_found.
  5. 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": "..."}}.

StatusCodeWhen
400invalid_requestA limit, cursor or updated_since cannot be read, or updated_since was sent to /invitations.
401unauthorisedNo key, or the key is not valid.
403module_offIntegrations are not on for your organisation.
403scope_missingThe connection does not hold the scope.
403permission_not_grantableThe change would give a person a permission a connection may not give.
404not_foundNo such person, invitation or group in your organisation.
409in_another_organisationThe address belongs to another organisation.
409last_people_managerThe change would leave nobody able to manage people.
422validation_failedA field is missing or not valid.
422idempotency_key_reusedThe key was used with another body.
429rate_limitedToo many calls this minute, or 50 emails this hour; wait for Retry-After seconds.