Onboarding Employment
Prerequisites
Before you begin, ensure that you meet the following requirements:
- You know the process of creating an employment record. If you need guidance, refer to this guide on creating your first company and employment.
- You have obtained company consent to act on their behalf. A company-scoped access token is required to create and manage employments.
Create employment
Check country availability
Before proceeding, confirm that your desired country is supported by the Remote API. You can do this by calling the list countries endpoint. The API response of this call will include a list of supported countries along with their respective country codes. These codes are required to create an employment.
ℹ️ If your desired country is not on the list of supported countries, you can reach out to your Remote contact or email us at api-support@remote.com to express your interest in hiring in that country.
Populate basic information
First, you will need to populate the employment with employee's "basic information". The Remote API requires this information for every supported country. As the required payload may cary by country, you will have to look up the expected payload.
Using JSON schema for expected payload
The Remote API uses JSON schemas to define the expected basic information payload format. You can retrieve the employment_basic_information
JSON schema for your country using the show form schema endpoint. This endpoint required two parameters: country_code
and form
. Let's say, your country of employment is Canada, your request will look like:
$ curl --location \
--header 'Authorization: Bearer eyJraWQiO...' \
--request GET 'https://gateway.remote-sandbox.com/v1/countries/CAN/employment_basic_information'
The resulting JSON schema provides the required fields, labels, descriptions, and validation rules.
{
"data": {
"additionalProperties": false,
"allOf": [
{
"else": {
"properties": {
"seniority_date": false
}
},
"if": {
"properties": {
"has_seniority_date": {
"const": "yes"
}
},
"required": [
"has_seniority_date"
]
},
"then": {
"required": [
"seniority_date"
]
}
}
],
"properties": {
"department": {
"properties": {
"id": {
"description": "(Optional) Select a department or create one.",
"oneOf": [
{
"const": null
}
],
"title": "Department",
"type": [
"string",
"null"
],
"x-jsf-presentation": {
"creatableOn": "name",
"inputType": "select",
"meta": "departments",
"placeholder": "Search or create a department..."
}
},
"name": {
"description": "Name of the department to be created if none is selected",
"maxLength": 255,
"title": "Department name",
"type": [
"string",
"null"
],
"x-jsf-presentation": {
"inputType": "text"
}
}
},
"title": "Department",
"type": [
"object",
"null"
],
"x-jsf-order": [
"id",
"name"
],
"x-jsf-presentation": {
"inputType": "fieldset"
}
},
"email": {
"description": "This is how the employee will access their account.",
"format": "email",
"maxLength": 255,
"title": "Personal email",
"type": "string",
"x-jsf-presentation": {
"inputType": "email"
}
},
"has_seniority_date": {
"description": "If the employee started working for your company before being added to Remote, then select Yes.",
"oneOf": [
{
"const": "yes",
"title": "Yes"
},
{
"const": "no",
"title": "No"
}
],
"title": "Does the employee have a seniority date?",
"type": "string",
"x-jsf-presentation": {
"direction": "row",
"inputType": "radio"
}
},
"job_title": {
"description": "We can hire most roles but there are some we cannot support. This includes licensed roles, blue collar workers, and employees with certain C-level job titles.",
"maxLength": 255,
"pattern": "\\S",
"title": "Job title",
"type": "string",
"x-jsf-presentation": {
"inputType": "text"
}
},
"manager": {
"properties": {
"id": {
"description": "(Optional) The person who will manage this employee day-to-day on the Remote platform.",
"oneOf": [
{
"const": "48359c5f-ff4e-4a2c-83e9-5c6f6f22f8bb",
"title": "Easha Abid",
"x-jsf-presentation": {
"meta": {
"assigned_roles": [
{
"data_scope": "all",
"name": "Owner",
"slug": "6541dadb-d3e0-45a0-9e32-094df0e5ce95",
"type": "owner"
}
]
}
}
},
{
"const": null
}
],
"title": "Manager",
"type": [
"string",
"null"
],
"x-jsf-presentation": {
"inputType": "select",
"meta": "team_members",
"placeholder": "Select a manager"
}
}
},
"title": "Manager",
"type": [
"object",
"null"
],
"x-jsf-order": [
"id"
],
"x-jsf-presentation": {
"inputType": "fieldset"
}
},
"name": {
"description": "Full employee name as it appears on identification document.",
"maxLength": 255,
"pattern": "\\S",
"title": "Full name",
"type": "string",
"x-jsf-presentation": {
"inputType": "text"
}
},
"provisional_start_date": {
"description": "The minimum onboarding time for Canada is 2 working days. We will confirm the start date once you invite the employee to do the self-enrollment. We strongly recommend a later start date if you plan to conduct background checks and want to lower termination risks and costs due to unsatisfactory results.",
"format": "date",
"maxLength": 255,
"title": "Provisional start date",
"type": "string",
"x-jsf-logic-validations": [
"blocked_date_validation"
],
"x-jsf-presentation": {
"blockedDates": [],
"inputType": "date",
"meta": {
"mot": 2
},
"minDate": "2025-03-12",
"softBlockedDates": []
}
},
"seniority_date": {
"description": "Please indicate if different from contract start date",
"format": "date",
"title": "Seniority date",
"type": [
"string",
"null"
],
"x-jsf-presentation": {
"inputType": "date"
}
},
"work_email": {
"description": "The employee's company email. For example, jane@company.com.",
"format": "email",
"maxLength": 255,
"title": "Work email",
"type": "string",
"x-jsf-presentation": {
"inputType": "email"
}
}
},
"required": [
"name",
"email",
"job_title",
"provisional_start_date",
"has_seniority_date"
],
"type": "object",
"x-jsf-logic": {
"validations": {
"blocked_date_validation": {
"errorMessage": "Date is blocked due to the holiday season, and the limited availability of internal/external providers to process onboarding, payroll and benefits enrollments",
"rule": {
"!": {
"in": [
{
"var": "provisional_start_date"
},
[]
]
}
}
}
}
},
"x-jsf-order": [
"name",
"email",
"work_email",
"job_title",
"department",
"provisional_start_date",
"has_seniority_date",
"seniority_date",
"manager"
]
}
}
⚠️ Since employment data schemes are dynamic, we highly recommend dynamically generating UI forms when using the Remote API in production. Learn more from How JSON Schemas Work guide.
Basic information constraints
- Understanding
provisional_start_date
validations
While JSON schemas define validation rules for most fields,provisional_start_date
includes additional complex rules that are only enforced by the API when calling the create employment endpoint. Here's an example schema snippet:Key validation rules include:{ "title": "Provisional start date", "format": "date", "x-jsf-presentation": { "inputType": "date", "meta": { "mot": 3 }, "minDate": "2025-03-10" } }- Minimum onboarding time (MOT): Each country has a minimum number of working days required to onboard an employee before their start date. The
meta.mot
field defines this in the schema. For example, if today is March 10 and the MOT is 3 days, then the selected date needs to be March 13 or after. This is included in the JSON Schema above. - Weekends: Some countries do not allow start dates on weekends, which may differ globally.
- Holidays: National holidays may restrict start dates.
- Arbitrary dates: Certain days (e.g., Christmas Eve) may be disallowed.
The Remote API enforces these rules and if a request violates any of them, an error response will explain the issue.
- Minimum onboarding time (MOT): Each country has a minimum number of working days required to onboard an employee before their start date. The
- Validation flow
The onboarding process may take several days. You can usemeta.mot
to implement an expiration system that notifies customers if a selected start date becomes invalid. For example, let's say the MOT is 3 days, today is Monday and they selected the start date for Friday. The days have passed and now it’s Thursday but the customer hasn’t finished the flow yet. The start date is no longer valid, so throughmeta.mot
, you can automatically notify your customer about it.
Create employment
After retrieving the JSON schema, submit the data using the create employment endpoint. The employment you create will be associated with the company-scoped access token of the company for which you are setting up the employment. Send the required fields as a JSON-encoded payload inside the basic_information
object.
{
"employment": {
"basic_information": {
"email": "jane@smith.com",
"has_seniority_date": "no",
"job_title": "Engineer",
"name": "Jane Smith",
"provisional_start_date": "2022-07-10"
},
"company_id": "20a72f86-company-id-20a72f86",
"country_code": "AUS",
"created_at": "2023-02-01T15:42:03",
"employment_lifecycle_stage": "employment_creation",
"full_name": "Jane Smith",
"id": "663e0b79-c893-45ff-a1b2-f6dcabc098b5",
"job_title": "Engineer",
"personal_email": "jane@smith.com",
"provisional_start_date": "2022-07-10",
"type": "employee",
"updated_at": "2023-02-01T15:42:03"
}
}
In this request,
basic_information
: includes an employee's basic data. Thebasic_information
object may include additional dynamic fields based on the country, such ashas_seniority_date
. Because these fields vary per country, using JSON schemas is essential to ensure each country's specific data requirements are met.company_id
: corresponds to the unique company ID to which the employee needs to be added.country_code
: indicates the country where the employee is located.created_at
: marks the timestamp at which the new employment was created.employment_lifecycle_stage
: (Refer to the detailed section below).provisional_start_date
: refers to the official start date of the new employment.type
: indicates the type of employment being created. The employment can be anemployee
or acontractor
.ℹ️ For the employment types
contractor
,global_payroll_employee
anddirect_employee
, only List employments and Show employment operations are available.updated_at
: refers to the timestamp at which the employment was last updated.
🧪 Sandbox testing:
To test employment creation in a sandbox environment, use the Create employment endpoint. It allows you to create an employment while bypassing the
provisional_start_date
validation, which means you can add a date that's in the past as well.
Employment lifecycle stage
Below is a list of possible stages in the employment lifecycle, represented by the employment_lifecycle_stage
field in the Employment resource of the Remote API.
-
employment_creation
: This is the initial stage when required fields are still missing. Employment data can be submitted once using Create employmentand later completed via Update employment. Once all required information is provided, the stage automatically advances toemployment_self_enrollment
. -
employment_self_enrollment
: At this stage, the employee or contractor must log in to the Remote platform and complete the necessary forms, which vary by country. Some information can be pre-filled with the Update employment endpoint. Refer to the API specification for details. -
right_to_work_check
: Remote verifies the employee's or contractor's work eligibility for the specified country. After passing this check, Remote will facilitate contract signing. There's no need for Remote API at this stage. -
contract_signing
: Once self-enrolment (and, the right-to-work check, if applicable) is complete, the employee remains in this stage until both parties sign the Employment Agreement Contract. This process takes place outside of the Remote API with Remote assisting as needed. -
remote_enrollment
: After contract signing is done, Remote handles benefits enrolment, payroll setup, and other administrative steps. No API action is required at this time. This is the final step before employment begins. -
onboarded
: The employee is officially ready to start work. -
offboarded
: The employment is archived, and the employee is offboarded.The transition to the
offboarded
stage takes time, as it requires both the employment to be archived and thetermination_date
to be reached. Here are some edge cases:- Employee initiated resignation after
provisional_start_date
:
If the employee resigns through Remote's platform and theirtermination_date
is after theprovisional_start_date
, theemployment_lifecycle_stage
remainsonboarded
until thetermination_date
is reached. Once thistermination_date
passes, the employment status changes toarchived
, and the lifecycle stage is updated tooffboarded
. - Termination or resignation before
provisional_start_date
:
If the employee is terminated or resigns before theirprovisional_start_date
and has not started onboarding, Remote will delete the employee without triggering any webhooks. After deletion, API calls to the Employments endpoints will return a 404 response.
- Employee initiated resignation after
ℹ️ The
employment_creation
is the only stage that requires data to be sent through the API. The other stages will move forward automatically based on the events that happen in the Remote Platform or taken by any party — company, employment, or Remote.
When an employment is created, it goes through different stages. Let's take a look at what an employment body looks like after creation:
{
"employment": {
"address_details": {},
"administrative_details": {},
"bank_account_details": [],
"basic_information": {},
"billing_address_details": {},
"company_id": "e31adae1-company-id-af5fba7dd803",
"contract_details": {},
"country": {
},
"created_at": "2021-11-11T18:44:39",
"eligible_for_onboarding_cancellation": true,
"emergency_contact_details": {},
"files": [],
"full_name": "Jane Smith",
"id": "20a72f86-employment-id-9e4942a902ff",
"job_title": "Engineer",
"manager": "John Doe",
"manager_email": "john.doe@company.com",
"manager_employment_id": "20a72f86-employment-id-9e4942a902ff",
"onboarding_tasks": {
},
"provisional_start_date": "2021-07-03",
"status": "created",
"type": "employee",
"updated_at": "2021-11-11T18:44:39",
"user_status": "active",
"work_email": "jane.smith@company.com"
}
}
Here are some new fields that you will notice in this definition:
status
:
Here is a list of all possible values represented bystatus
in the employment API.created
: Indicates that the employment has been created. At this stage, employer can edit employee's data.created_awaiting_reserve
: Indicates that the employment has been created but Remote is waiting for a reserve payment before an employer can invite the employee.created_reserve_paid
: Indicates that the reserve payment has been paid by the employer.invited
: Indicates that the employee has been invited but didn't start the onboarding process. At this stage, employer can no longer make changes to the employee's contract details.initiated
: Indicates that the employee has started their onboarding.
On completion of every onboarding task, the employment.onboarding_task.completed event is triggered.review
: Indicates that the employee has completed onboarding and are being reviewed by the Remote admin.pending
: Indicates that employment is missing necessary fields while onboarding.active
: Indicates that the employment is active. The status is set to active when all user tasks are completed and the user status is alsoactive
. (Learn more about user statuses in the section below).
Onactive
, the employment.onboarding.completed event is triggered.archived
: Indicates that the employment has been archived and no longer in use. When an employment is marked as archived, the user status changes toinactive
.deleted
: Indicates that the employment has been soft deleted by the admin. Accounts are deleted at the request of the users. When this is done, the user will no longer appear on the team page.
user_status
:created
: Indicates that a user was creates but did not start the onboarding.initiated
: Indicates that a user has started their onboarding process.active
: Indicates that a user has completed onboarding. This status is achieved when all onboarding user tasks are completed and the corresponding employment has a statusreview
,pending
,active
, orarchived
.
The employment.user_status.activated webhook is triggered when a user status changes toactive
.cancelled
: Indicates that a user contract was canceled. At this stage, the user can still log in and access their data and documents.deleted
: Indicates that a user has been deleted and can no longer log into Remote platform. Deleted users do not show up on the people page but can be searched in the Users table by a Remote admin.inactive
: Indicates that a user was deactivated and their employment is suspended. At this stage, the user can still log into the platform to access their data and documents but their invoicing capabilities have been revoked. The employer can reactivate a user at any time.
The employment.user_status.deactivated webhook is triggered every time a user status changes toinactive
.
ℹ️ If your company-scoped access token has expired, you'll receive an
Unauthorized
response. To obtain a new valid token, follow the refresh token flow.
The employment_lifecycle_stage
field tracks the employment's progress through different stages. Learn more from the employment lifecycle stages section.
🧪 Sandbox testing:
When providing an email address in sandbox environment, it is recommended to use a unique, valid email that can receive messages. This allows you to verify that the employee is receiving emails as expected.
If you're using Gmail, GSuite, or Outlook, you can create unique email addresses by appending
+randomtext
to your existing address. For example, if your email isbob@example.com
, you can usebob+1@example.com
. This ensures uniqueness while still delivering emails to the same inbox.
Now that we have an employment, we can get started with its onboarding.
Update employment
When an employment record is created, its initial employment_lifecycle_stage
is employment_creation
. To move to the next stage, you need to update the employment record. Employment data can only be updated through the Remote API before an invitation is sent to the employee using the Update employment endpoint.
Add / modify employment information
An already created employment, that is not deleted can be updated at any time. Through this endpoint, you can modify all information submitted during the creation step and add additional details like home address, bank details, emergency contact, etc. But once the onboarding process is complete, only a limited set of employment details such as emergency_contact_details
can be modified. So, if you need to make changes to the employment record, make sure to do so before sending the invite.
ℹ️ Updates are blocked once the invitation has been sent because in certain cases, employees need to agree to the amendments made, for example, changes to their
contract_details
, etc.
To make the required edits, simply make a patch request by passing the employment_id
. When updating an employment, the following events are triggered depending on what change was made to the employment.
- employment.start_date.changed: Triggered when an employer changes an employment's starting date.
- employment.personal_information.updated: This event is triggered every time an employment's personal information is changed.
- employment.details.updated: Triggered when an employment's department or manager is updated.
- employment.account.updated: Triggered whenever an employment's email account is updated.
A few important points to keep in mind while using this endpoint:
- For
created
employment, you can update all basic parameters, onboarding tasks, as well asbasic_information
. - For
active
employment, you can update manager information, emergency contact details, and address details using this endpoint. - Before modifying country-specific data, we recommend viewing the JSON form schema because a country's compliance requirements change frequently, which results in a change in required and returned fields.
- If you are using this endpoint to build an integration, make sure to dynamically collect the latest parameters for each country by calling the show form schema endpoint.
- Updating contractors' details via API is not yet supported. Please reach out to your Remote contact for assistance.
🧪 Sandbox testing:
In a sandbox environment, you can call the Update employment endpoint that allows you to edit the employment status of an employee.
For example, here's how you can use this endpoint to add contract and pricing details to the employment. For this call, you need to provide:
employment_id
: This is theid
returned when you created the employment.contract_details
: This field contains employment contract information, which varies by country. To obtain the necessary fields for a specific country, you can query the show form schema endpoint, passing bothcountry_code
andcontract_details
as path parameters.pricing_plan_details
: To obtain the necessary fields, you can query the show form schema endpoint by passing thecountry_code
andpricing_plan_details
as the form type.
Here's what an example request will look like:
'{
"contract_details": {
"available_pto": 33,
"annual_gross_salary": 100000,
"benefits": {
"employee_assistance_program": "no",
"health": "Basic - Employee Only (Canada Life - Basic Health Employee Only; Canada Life - Basic Dental Employee Only; Canada Life - Basic Vision; Canada Life - Basic Life; Canada Life - Basic AD&D)",
"retirement": "Basic Retirement (Canada Life - Basic Retirement)"
},
"bonus_details": "every year",
"commissions_details": "15% every year",
"contract_duration": "Permanent",
"company_business_description": "We are a consulting company, helping businesses implement the best APIs out there.",
"experience_level": "Level 3 - Associate - Employees who perform independently tasks and/or with coordination and control functions",
"equity_compensation": {
"offer_equity_compensation": "no"
},
"has_bonus": "yes",
"has_commissions": "yes",
"has_signing_bonus": "yes",
"probation_length": 3,
"role_description": "Manage a quickly growing and business-critical team. Contribute to hiring and retaining product designers; help to shape the team culture.",
"province_of_residency": "AB",
"signing_bonus_amount": 15000,
"supervisor_name": "Sally",
"work_address_is_home_address": "yes"
},
"pricing_plan_details": {
"frequency": "annually"
}
}'
Invite employee
Once all the required data has been sent, you can proceed with inviting the employee using the invite employment endpoint. On a successful call, the employee will receive an email from no-reply@remote-sandbox.com
. Upon receiving that email, the employee will begin their self-enrolment process, where they provide any missing details, such as administrative information, home address, and other necessary data.
Show employment
After the invitation has been sent, if you want to check the status of the employment, you can call the show employment endpoint and focus on employment_lifecycle_stage
and status
values.
{
"data": {
"employment": {
,
"employment_lifecycle_stage": "employee_self_enrollment",
,
"id": "9fb23136-bb7c-488a-b5dc-37d3b7c9033b",
"status": "invited",
}
}
}
Congratulations! You have successfully created and invited a new employee. Next up, you can set employment benefits for the created employment.
Updated 17 days ago