Skip to content

Vacancies

Manage open positions and the hiring pipeline. Vacancies represent roles that need to be filled, with target dates, salary ranges, and team assignments. When a candidate is hired, you can "fill" a vacancy to atomically convert it into an employee record.

New to Flowstate?

Read the Domain Model to understand the vacancy-to-employee fill workflow and how vacancies feed into headcount forecasting.

Vacancy Object

FieldTypeDescription
idstringUnique identifier (CUID format). System-generated. Read-only.
externalIdstring | nullYour external identifier for this vacancy. Unique within your organization. Use for lookups via path parameters.
rolestringVacancy title / role name (e.g. "Senior Backend Engineer").
descriptionstring | nullDetailed description of the role and responsibilities.
statusstringVacancy status: "open", "filled", "cancelled", or "on_hold".
ftenumberFull-Time Equivalent for this vacancy. 1.0 = full-time, 0.5 = half-time. Range: 0--1.
targetStartDatedate (YYYY-MM-DD) | nullDesired start date for the new hire. Used in headcount forecasting.
targetFillDatedate (YYYY-MM-DD) | nullTarget date to fill this vacancy by. Used for recruitment planning.
jobRoleIdstring | nullJob role classification. Use GET /job-roles for valid IDs.
workTypeIdstring | nullWork arrangement type. References a Work Type.
geographyIdstring | nullTarget hire location/region. References a Location. Affects salary range expectations.
salaryMinnumber | nullMinimum annual salary for the role. Decimal with 2 decimal places.
salaryMaxnumber | nullMaximum annual salary for the role. Decimal with 2 decimal places.
currencyCodestring | nullISO 4217 currency code for the salary range (e.g. "GBP").
filledByLiveEmployeeIdstring | nullID of the employee who filled this vacancy. Set automatically by the Fill endpoint, or manually via PATCH. References an Employee.
hiringManagerIdstring | nullID of the employee responsible for hiring this role. References an Employee.
createdAtdatetime (ISO 8601)When the record was created. Read-only.
updatedAtdatetime (ISO 8601)When the record was last modified. Read-only.
customAttributesarrayCustom attribute values for this vacancy. Returned on GET-by-ID. See Custom Attributes.

Endpoints

MethodPathDescription
GET/org/:orgId/vacanciesList vacancies
GET/org/:orgId/vacancies/:idGet vacancy
POST/org/:orgId/vacanciesCreate vacancy
PATCH/org/:orgId/vacancies/:idUpdate vacancy
DELETE/org/:orgId/vacancies/:idDelete vacancy
POST/org/:orgId/vacancies/:id/fillFill a vacancy (convert to employee)

External ID Support

The :id path parameter accepts either a Flowstate CUID (e.g. clx1a2b3c4d5e6f7g8h9) or your externalId. The format is auto-detected.


List Vacancies

GET /org/:orgId/vacancies

Returns a paginated list of vacancies in the organization.

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number (1-based).
limitinteger20Records per page. Min 1, max 100.
searchstring--Free-text search by role or description.
sortBystringroleField to sort by.
sortDirstringascSort direction: asc or desc.
scenarioIdstring--Scenario ID for what-if queries.

Example Request

bash
curl -X GET "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/vacancies?sortBy=targetStartDate&sortDir=asc" \
  -H "Authorization: Bearer private_..."

Example Response

json
{
  "data": [
    {
      "id": "clx5v6w7x8y9z0a1b2c3",
      "externalId": null,
      "role": "Senior Backend Engineer",
      "description": "Backend engineer for the payments team, focusing on billing infrastructure.",
      "status": "open",
      "fte": 1.0,
      "targetStartDate": "2026-06-01",
      "targetFillDate": "2026-05-15",
      "jobRoleId": "clx9r8q7w6e5t4r3",
      "workTypeId": "clx2w3x4y5z6a7b8",
      "geographyId": "clx3g2h1j0k9l8m7",
      "salaryMin": 120000,
      "salaryMax": 160000,
      "currencyCode": "USD",
      "filledByLiveEmployeeId": null,
      "hiringManagerId": "clx9m4n5o6p7q8r9",
      "createdAt": "2026-01-15T10:00:00Z",
      "updatedAt": "2026-03-01T16:45:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 23,
    "hasNextPage": true
  }
}

Get Vacancy

GET /org/:orgId/vacancies/:id

Returns a single vacancy by ID.

Include KeyDescription
assignmentsAll team and project assignments for this vacancy.
filledByEmployeeThe employee record that filled this vacancy (if status is "filled").
GET /org/:orgId/vacancies/:id?include=assignments,filledByEmployee

Example Request

bash
curl -X GET "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/vacancies/clx5v6w7x8y9z0a1b2c3?include=assignments" \
  -H "Authorization: Bearer private_..."

Example Response

json
{
  "data": {
    "id": "clx5v6w7x8y9z0a1b2c3",
    "role": "Senior Backend Engineer",
    "description": "Backend engineer for the payments team, focusing on billing infrastructure.",
    "status": "open",
    "fte": 1.0,
    "targetStartDate": "2026-06-01",
    "targetFillDate": "2026-05-15",
    "jobRoleId": "clx9r8q7w6e5t4r3",
    "workTypeId": "clx2w3x4y5z6a7b8",
    "geographyId": "clx3g2h1j0k9l8m7",
    "salaryMin": 120000,
    "salaryMax": 160000,
    "currencyCode": "USD",
    "filledByLiveEmployeeId": null,
    "hiringManagerId": "clx9m4n5o6p7q8r9",
    "createdAt": "2026-01-15T10:00:00Z",
    "updatedAt": "2026-03-01T16:45:00Z",
    "customAttributes": [
      {
        "id": "clx0a1b2c3d4e5f6g7h8",
        "definitionId": "clx2d3e4f5g6h7i8j9k0",
        "entityType": "VACANCY",
        "entityId": "clx5v6w7x8y9z0a1b2c3",
        "stringValue": "ENG-001",
        "numberValue": null,
        "dateValue": null,
        "dateRangeStart": null,
        "dateRangeEnd": null,
        "definition": {
          "id": "clx2d3e4f5g6h7i8j9k0",
          "name": "Cost Centre Code",
          "attributeKey": "cost_centre_code",
          "fieldType": "STRING"
        }
      }
    ],
    "assignments": [
      {
        "id": "clx8a9b0c1d2e3f4",
        "type": "team",
        "targetId": "clx6t7u8v9w0x1y2",
        "fte": 1.0,
        "startDate": "2026-06-01",
        "endDate": null,
        "createdAt": "2026-01-15T10:00:00Z",
        "updatedAt": "2026-01-15T10:00:00Z"
      }
    ]
  }
}

Create Vacancy

POST /org/:orgId/vacancies

Creates a new vacancy record.

Create Request Body

FieldTypeRequiredDescription
rolestringYesVacancy title or role name.
externalIdstring | nullNoYour external identifier. Must be unique within the organization. Cannot resemble a CUID format. Max 255 characters.
descriptionstring | nullNoDetailed role description.
statusstringNoVacancy status. Default: "open".
ftenumberNoFTE value (0--1). Default: 1.0.
targetStartDatedate (YYYY-MM-DD) | nullNoDesired start date for the new hire.
targetFillDatedate (YYYY-MM-DD) | nullNoTarget date to fill the vacancy.
jobRoleIdstring | nullNoJob role ID. Takes precedence over jobRole.
jobRoleobjectNoResolve-or-create a job role by externalId or title. Ignored when jobRoleId is supplied. See Employees → Nested jobRole Object for the shape and semantics — identical here.
workTypeIdstring | nullNoWork Type ID.
geographyIdstring | nullNoLocation ID.
salaryMinnumber | nullNoMinimum annual salary. Must be >= 0.
salaryMaxnumber | nullNoMaximum annual salary. Must be >= 0.
currencyCodestring | nullNoISO 4217 currency code (3 uppercase letters).
hiringManagerIdstring | nullNoID of the hiring manager (an employee).

Example Request

bash
curl -X POST "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/vacancies" \
  -H "Authorization: Bearer private_..." \
  -H "Content-Type: application/json" \
  -d '{
    "role": "DevOps Engineer",
    "description": "Cloud infrastructure engineer to support the platform team.",
    "fte": 1.0,
    "targetStartDate": "2026-09-01",
    "targetFillDate": "2026-08-15",
    "salaryMin": 110000,
    "salaryMax": 145000,
    "currencyCode": "USD",
    "hiringManagerId": "clx9m4n5o6p7q8r9"
  }'

Example Response

json
{
  "data": {
    "id": "clx2b3c4d5e6f7g8h9i0",
    "externalId": null,
    "role": "DevOps Engineer",
    "description": "Cloud infrastructure engineer to support the platform team.",
    "status": "open",
    "fte": 1.0,
    "targetStartDate": "2026-09-01",
    "targetFillDate": "2026-08-15",
    "jobRoleId": null,
    "workTypeId": null,
    "geographyId": null,
    "salaryMin": 110000,
    "salaryMax": 145000,
    "currencyCode": "USD",
    "filledByLiveEmployeeId": null,
    "hiringManagerId": "clx9m4n5o6p7q8r9",
    "createdAt": "2026-04-08T09:30:00Z",
    "updatedAt": "2026-04-08T09:30:00Z"
  }
}

Status: 201 Created


Update Vacancy

PATCH /org/:orgId/vacancies/:id

Updates one or more fields on an existing vacancy. Only include the fields you want to change. You can set or update the externalId field.

Update Request Body

All fields from the Create Request Body are accepted, and all are optional.

Example Request

bash
curl -X PATCH "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/vacancies/clx5v6w7x8y9z0a1b2c3" \
  -H "Authorization: Bearer private_..." \
  -H "Content-Type: application/json" \
  -d '{
    "status": "on_hold",
    "targetFillDate": "2026-07-01"
  }'

Delete Vacancy

DELETE /org/:orgId/vacancies/:id

Deletes a vacancy record.

Example Request

bash
curl -X DELETE "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/vacancies/clx5v6w7x8y9z0a1b2c3" \
  -H "Authorization: Bearer private_..."

Status: 204 No Content


Fill a Vacancy

POST /org/:orgId/vacancies/:id/fill

Converts a vacancy into a new employee. This is an atomic operation that:

  1. Creates a new employee with the provided details.
  2. Creates an initial salary adjustment for the new employee.
  3. Transfers all team/project assignments from the vacancy to the new employee.
  4. Sets the vacancy status to "filled" and links it to the new employee.

Fields not provided in the fill request fall back to the vacancy's values (e.g. jobRoleId, geographyId, workTypeId).

Fill Request Body

FieldTypeRequiredDescription
firstNamestringYesNew employee's first name.
lastNamestringYesNew employee's last name.
emailstring | nullNoWork email. If omitted, a placeholder is generated.
startDatedate (YYYY-MM-DD)YesEmployee start date. Vacancy assignments transfer from this date.
salarynumberYesAnnual base salary. Must be >= 0.
currencyCodestringYesISO 4217 currency code for the salary (e.g. "GBP").
managerIdstring | nullNoEmployee ID of the new hire's manager. Falls back to the vacancy's hiringManagerId.
jobRoleIdstring | nullNoJob role ID. Falls back to the vacancy's jobRoleId. Takes precedence over jobRole.
jobRoleobjectNoResolve-or-create a job role by externalId or title (same shape as on employees). Ignored when jobRoleId is supplied.
workTypeIdstring | nullNoWork type ID. Falls back to the vacancy's workTypeId.
geographyIdstring | nullNoGeography ID. Falls back to the vacancy's geographyId.

Example Request

bash
curl -X POST "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/vacancies/clx5v6w7x8y9z0a1b2c3/fill" \
  -H "Authorization: Bearer private_..." \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Sarah",
    "lastName": "Okonkwo",
    "email": "sarah.okonkwo@example.com",
    "startDate": "2026-06-01",
    "salary": 140000,
    "currencyCode": "USD"
  }'

Example Response

The response contains the newly created employee:

json
{
  "data": {
    "id": "clx7n8m9k0j1h2g3f4e5",
    "firstName": "Sarah",
    "lastName": "Okonkwo",
    "email": "sarah.okonkwo@example.com",
    "internalEmployeeId": null,
    "startDate": "2026-06-01",
    "endDate": null,
    "noticeDate": null,
    "managerId": "clx9m4n5o6p7q8r9",
    "jobRoleId": "clx9r8q7w6e5t4r3",
    "workTypeId": "clx2w3x4y5z6a7b8",
    "geographyId": "clx3g2h1j0k9l8m7",
    "defaultCurrencyCode": null,
    "createdAt": "2026-04-08T10:00:00Z",
    "updatedAt": "2026-04-08T10:00:00Z"
  }
}

Status: 201 Created

What happens behind the scenes

After a successful fill:

  • The vacancy's status becomes "filled" and filledByLiveEmployeeId points to the new employee.
  • A salary adjustment is created with the provided salary, currencyCode, and the employee's startDate as the effectiveDate.
  • All vacancy team/project assignments are duplicated as employee assignments, starting from the employee's startDate.
  • The managerId defaults to the vacancy's hiringManagerId if not provided.
  • The jobRoleId, workTypeId, and geographyId default to the vacancy's values if not provided.

External IDs

You can assign your own externalId during creation or update. This allows you to reference vacancies by your system's identifier instead of the Flowstate CUID.

  • Setting: Pass externalId in the POST or PATCH request body.
  • Lookups: Use the external ID directly in path parameters (e.g. GET /vacancies/MY-EXT-ID).
  • Uniqueness: External IDs must be unique per entity type within your organization.
  • Format restriction: External IDs cannot match the CUID format (25 lowercase alphanumeric characters starting with a letter).

Error Responses

Validation Error (400)

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed.",
    "details": [
      { "field": "role", "message": "role is required" }
    ],
    "errorId": "err_clx9a8b7c6d5e4f3"
  }
}

Not Found (404)

json
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Vacancy not found.",
    "errorId": "err_clx9a8b7c6d5e4f3"
  }
}

Flowstate Documentation