API Docs

Users

Some basic information about each user is stored on the user object directly, instead of in their master CV. Most importantly, the user holds the information to identify them in authentication and integrations (id, email, external_unique_id, upn).

You can build your own user integration on top of this API if you need something more flexible than periodically sending us updated user lists in CSV. See User Sync for the SCIM and CSV options.

Four of the endpoints below (POST /users, GET /users/find, and GET and PUT on /users/<user_id>) also appear in the Integrations API reference, where you can see every field and response code and try a request. This page is the complete narrative and also covers the endpoints the reference does not yet include: user search, the profile changes feed, and deleting a user.

Before you start

  • Every request needs an Authorization header, and requests with a body need Content-Type: application/json. See Authentication & Security.
  • Creating a user needs a key with countrymanager access for its own country, or internationalmanager access for any country. A key with only consultant access cannot create users.
  • <user_id> in the URLs below is the internal Flowcase ID for the user.
  • Language codes are legacy by default (int for English, no for Norwegian). Pass ?use_legacy_codes=false to read and write ISO 639-1 codes instead. See Country & Language Codes and multilingual text fields.

Search users

GET https://<subdomain>.flowcase.com/api/v2/users/search?from=<from>&size=<size>&sort_by=<sort_by>&deactivated=<deactivated>&role=<role>&name=<name>&office_ids[]=<office_id>&office_ids[]=<office_id>

Query parameters

Parameter Type Description
from integer Used for pagination. Specifies the starting index of the results to return. Increase it by size to retrieve the next page. The response is a plain array with no total count, so keep requesting pages until you receive fewer than size results.
size integer [1-500] Used for pagination. Specifies the maximum number of results to return per page. Supports up to 500 items per page.
sort_by string Specifies the field to sort the results by. Supported values are:
- name: Sort by name alphabetically ascending (default if not provided)
- relevance: Sort by how well the name matches the provided name parameter, with more similar matches returned first
- country: Sort by the ISO country code
- role: Deprecated parameter, with no guaranteed consistency in sorting order
deactivated boolean Specifies whether to include deactivated users in the results. Set to true to include deactivated users, false to exclude them.
role string Limits the results to users with the specified role, such as consultant, external, referencemanager, countrymanager, departmentmanager, internationalmanager, or limited_access.
name string Limits the results to users whose name, email address, or external_unique_id matches or is similar to the provided name.
office_ids array[string] Limits the results to users from the specified office IDs. You can provide this parameter multiple times to include multiple office IDs.

Response body

[
  {
    "user_id": "USER_ID",
    "id": "USER_ID",
    "email": "EMAIL",
    "external_unique_id": "EXTERNAL_UNIQUE_ID",
    "upn": "UPN",
    "name": "NAME",
    "telephone": "",
    "default_cv_id": "CV_ID",
    "deactivated": false,
    "deactivated_at": false,
    "created_at": "2016-12-01T13:54:07.000Z",
    "updated_at": "2022-06-14T12:26:13.682Z",
    "profile_updated_at": "2022-06-14T12:26:13.000Z",
    "role": "internationalmanager",
    "roles": ["internationalmanager"],
    "office_id": "OFFICE_ID",
    "office_name": "London",
    "country_id": "COUNTRY_ID",
    "country_code": "uk",
    "language_code": "int",
    "image": {
      "url": null,
      "thumb": { "url": null },
      "fit_thumb": { "url": null },
      "large": { "url": null },
      "small_thumb": { "url": null }
    }
    // Some fields have been omitted
  }
  // More matching users
]

Get a user by ID

GET https://<subdomain>.flowcase.com/api/v1/users/<user_id>

<user_id> is the internal Flowcase ID for the user.

The user must belong to the same account as the API key. An ID from another account returns 404, as does an ID that does not exist or is not a valid ID, so you cannot tell the three apart.

Response body

{
  "user_id": "USER_ID",
  "id": "USER_ID",
  "email": "EMAIL",
  "external_unique_id": "EXTERNAL_UNIQUE_ID",
  "upn": "UPN",
  "name": "NAME",
  "telephone": "",
  "default_cv_id": "CV_ID",
  "deactivated": false,
  "deactivated_at": false,
  "created_at": "2016-12-01T13:54:07.000Z",
  "updated_at": "2022-06-14T12:26:13.682Z",
  "role": "internationalmanager",
  "roles": ["internationalmanager"],
  "role_allowed_office_ids": [],
  "role_allowed_tag_ids": [],
  "office_id": "OFFICE_ID",
  "office_name": "London",
  "country_id": "COUNTRY_ID",
  "country_code": "uk",
  "language_code": "int",
  "image": {
    "url": null,
    "thumb": { "url": null },
    "fit_thumb": { "url": null },
    "large": { "url": null },
    "small_thumb": { "url": null }
  }
  // Some fields have been omitted
}

Three details are worth knowing when you read a user:

  • roles holds the base role plus any extra access roles. Requests set the two separately, as role and extra_roles, but the response reports them together in roles. See User roles.
  • deactivated_at is boolean false while the user is active, and an ISO 8601 timestamp once the user has been deactivated.
  • image URLs are signed and expire after about 20 minutes, so fetch the picture rather than storing the URL. See Profile Pictures for uploads.

For the full field list, see the Integrations API reference.

Find a user by email, external ID or UPN

GET https://<subdomain>.flowcase.com/api/v1/users/find?<field>=<value>

Query parameters

Parameter Type Required Description
email string optional Filter users based on email address match
external_unique_id string optional Filter users based on external_unique_id match
upn string optional Filter users based on upn match

Each field is matched exactly. At least one of the three is needed: a request with none of them, or with only empty values, returns 400. Give two or more and the user has to match all of them. A query that matches nothing returns 404.

The response body is the same as getting a user by ID.

Track profile changes

GET https://<subdomain>.flowcase.com/api/v1/users/changes?profile_updated_since=<timestamp>&after_id=<user_id>&limit=<limit>

Returns the users whose profile data changed at or after profile_updated_since, oldest change first. Poll this endpoint to keep a copy of our user data up to date without reading every user on every run.

Every user carries a profile_updated_at timestamp, and this endpoint filters and orders by it. It moves only when profile data changes, so sign-in activity, password changes, UI preferences and role changes do not bring a user back. The fields that do move it are listed under Profile fields.

This endpoint needs an API key with the internationalmanager or readonly_internationalmanager role, shown as Administrator and Read only Administrator when you create a key, and answers 403 for any other role. It returns every user in the account, deactivated users included, because a profile that changed on the way out is still a change you need.

Query parameters

Parameter Type Required Description
profile_updated_since string required ISO 8601 timestamp. Users stamped at exactly this time are included, which is what makes the cursor below work.
after_id string optional The id of the last user on the previous page. That user is left out of the results.
limit integer optional Maximum number of users per page, must be positive. Default: 100

offset is not supported and returns 400. Page with after_id instead. A created_since parameter is accepted and ignored.

Response body

An array of user objects, each the same shape as getting a user by ID plus the profile_updated_at timestamp the feed orders by, ordered by profile_updated_at and then by id.

[
  {
    "user_id": "USER_ID",
    "id": "USER_ID",
    "email": "EMAIL",
    "name": "NAME",
    "updated_at": "2026-09-01T08:41:02.117Z",
    "profile_updated_at": "2026-09-01T09:12:44.000Z"
    // Same fields as a single user
  }
  // More changed users, later changes last
]

Reading the whole feed

Take the last user on the page you received, and send its profile_updated_at back as profile_updated_since and its id as after_id:

GET https://<subdomain>.flowcase.com/api/v1/users/changes?profile_updated_since=2026-09-01T09:12:44.000Z&after_id=USER_ID&limit=100

Repeat until a page comes back with fewer users than limit, which means you have reached the end. Keep that last cursor and send it again on your next poll.

Two details to respect when you build the cursor:

  • Send the two values back as you received them. Every profile_updated_at is a whole second, and a cursor built from a rounded or reformatted value can step over users.
  • after_id is what separates users who share a timestamp. A bulk import can stamp thousands of users in the same second, so a cursor carrying only the timestamp will either repeat that group for ever or lose the rest of it.
A change becomes visible once the second it was stamped in has passed, so allow a second before expecting it in the feed. Nothing is dropped, it arrives on your next poll.

Profile fields

A change to any of these moves profile_updated_at:

name, name_multilang, title, born_year, email, external_unique_id, upn, telephone, landline, place_of_residence, nationality, twitter, override_language_code, office_id, and the profile picture (image and its dimensions).

Custom tag assignments move it too. Tags are not part of the user object, so a user can appear in the feed with nothing visibly different: read their tags with the Custom Tags API if you track them.

Deactivating or reactivating a user does not move it, and neither does a role change, so neither event brings a user into the feed on its own. If you need to catch leavers or permission changes, read the full list with Search users on a slower schedule.

Create a user

POST https://<subdomain>.flowcase.com/api/v1/users

email, country_id and office_id are required, and the office must belong to that country. The email must be unique in the account, and its domain must be on the account's whitelist unless the user is given the external role.

Request body

{
  "user": {
    "country_id": "<country_id>",
    "email": "<email_address>",
    "upn": "<upn>",
    "external_unique_id": "<employee_id>",
    "office_id": "<office_id>",
    "role": "<role>",
    "extra_roles": [],
    "name": "<name>",
    "telephone": "<telephone>",
    "landline": "<landline>",
    "born_year": <born_year>,
    "title": {
      "no": "<title.no>",
      "int": "<title.int>"
    },
    "nationality": {
      "no": "<nationality.no>",
      "int": "<nationality.int>"
    },
    "ensure_unique_custom_tag_ids_by_category": {
      "<custom_tag_category_id>": "<custom_tag_id>"
    },
    "send_email": <send_email>
  }
}

If send_email is set to true then an email notification is sent to the user. The send_email property should be omitted or false to create the user without sending an email.

ensure_unique_custom_tag_ids_by_category will add the provided custom tags to the user and remove any other custom tag the user has within that category. You have to use the internal ids for this (not the external_unique_id values). To get a list of all the existing tags and categories:

GET https://<subdomain>.flowcase.com/api/v1/masterdata/custom_tags/custom_tag_category

(See the Custom Tags documentation for more details.)

Response

A successful create answers 200, not 201, and returns the full user object.

Status Meaning
400 The user wrapper key is missing from the request body.
403 The key may not create users in that country, or the key is disabled.
404 The country_id or office_id does not exist in the account.
415 The Content-Type header is not application/json.
422 Validation failed: a duplicate email or external_unique_id, or an email or UPN domain that is not whitelisted.

See Response Codes for the full list.

Update a user

When updating a user it is only necessary to provide the fields that are to be updated, any fields omitted from the payload will remain as they were in the database.

PUT https://<subdomain>.flowcase.com/api/v1/users/<user_id>

Changing a user's office or department

In the case of changing the office_id (department), you also need to provide the country_id for the country that the new office is in. Changing the country needs internationalmanager access; moving a user between offices in the same country needs internationalmanager or countrymanager access.

Request body

{
  "user": {
    "country_id": "<country_id>",
    "office_id": "<office_id>", // country_id is also required when changing the office_id
    "email": "<email_address>",
    "external_unique_id": "<employee_id>",
    "name": "<name>",
    "telephone": "<telephone>",
    "landline": "<landline>",
    "born_year": <born_year>,
    "ensure_unique_custom_tag_ids_by_category": {
      "<custom_tag_category_id>": "<custom_tag_id>"
    },
    "role": "consultant", // See User roles section
    "extra_roles": []
  }
}

ensure_unique_custom_tag_ids_by_category will add the provided custom tags to the user and remove any other custom tag the user has within that category.

Use the internal id values for both the category and the tag. A category or tag ID that does not exist in the account returns 400. To assign more than one tag from the same category, or to work with tags on their own, use the Custom Tags API.

Response

A successful update answers 200 and returns the full updated user object. It answers 400 when the user wrapper key is missing, 403 without write access to that user, 404 when no such user exists in the account, 415 when Content-Type is not application/json, and 422 when validation fails, for example a blank email, an email already used by another user, or an email or UPN domain that is not whitelisted.

Deactivate a user

PUT https://<subdomain>.flowcase.com/api/v1/users/<user_id>

<user_id> is the internal Flowcase ID for the user.

Request body

{
  "user": {
    "deactivated": true
  }
}

Reactivate a user

PUT https://<subdomain>.flowcase.com/api/v1/users/<user_id>

<user_id> is the internal Flowcase ID for an existing user that was previously deactivated.

Request body

{
  "user": {
    "deactivated": false,
    "send_email": false
  }
}

If send_email is set to true then a welcome email will be sent to the activated user. The send_email property should be omitted or false to reactivate the user without sending an email.

Delete a user

DELETE https://<subdomain>.flowcase.com/api/v1/users/<user_id>

<user_id> is the internal Flowcase ID for the user.

Note that deleting a user means removing them from our system and that information can not be easily recovered.

User roles

Users can be given one of four basic roles plus some extra roles which grant additional permissions on top.

The base role is one of external, limited_access, consultant or internationalmanager. The extra roles are referencemanager, countrymanager, departmentmanager and bidmanager; pass them in extra_roles, where they are always layered on top of the consultant base role. For what each role can do, see User roles on the User Sync page.

Responses report the base role in role and the base role plus any extra roles together in roles.

When specifying the departmentmanager role when creating or updating a user you will also need to include the role_allowed_office_ids and/or role_allowed_tag_ids fields to specify which departments they have access to.

The role_allowed_tag_ids specifies one or more custom tags which this manager will have access to, making it possible to assign managers to users independent of how they are divided into offices in Flowcase. To assign these tags to users you can use the ensure_unique_custom_tag_ids_by_category attribute when creating or updating users, or use the Custom Tags API if you need more flexibility (like assigning more than one manager tag per user).

Example: update a user to be Department Manager

PUT https://<subdomain>.flowcase.com/api/v1/users/0123456789abcdef01234567

Request body

{
  "user": {
    "role": "consultant",
    "extra_roles": ["departmentmanager"],
    "role_allowed_office_ids": [
      "00112233445566778899aabb",
      "000111222333444555666777"
    ],
    "role_allowed_tag_ids": [
      "aaabbbcccdddeeefff000111",
      "55556666777788889999aaaa"
    ]
  }
}

What's next

  • Try the create, find, read and update calls in the Integrations API reference, which lists every field and response code.
  • Compare this API with the SCIM and CSV options in User Sync.
  • Read a user's CV with the default_cv_id from any user response: see CVs & CV Sections.
  • Manage the tags you assign with ensure_unique_custom_tag_ids_by_category in Custom Tags.
  • Look up the country_id and office_id values you need in Countries & Departments.