Completing EOR employment onboarding
This guide will help you retrieve, update, and complete an employment onboarding form for an EOR employment using Oyster’s API endpoints. The employment onboarding is necessary to create an employment contract, and by completing the steps in this guide, you will be ready to send a contract out for signature. This guide assumes the employment has a status of In Progress, achieved either via API using this guide or submitted by the Customer Admin in the platform.
Note for Reseller partners using the API - you will need to use the X-Oyster-Customer-Id header for all of the calls in this guide. For more information, see the Reseller guide to using the Oyster API.
1. Retrieve Employment Onboarding Form
You can retrieve the onboarding form associated with a specific employment using the Fetch the onboarding form endpoint. This form contains all necessary information the worker needs to provide during the onboarding process.
Onboarding forms vary based on employment country and when the employment was submitted (i.e. when the engagement state is IN_PROGRESS. To see which countries support employment onboarding via API, see the Hiring API country coverage guide.). For this reason, it is important to get the specific onboarding form for each employment.
Example Request
curl --request GET \
--url https://api.oysterhr.com/v0.1/hiring/employments/urY7zKOm/onboarding/form \
--header 'accept: application/json' \
--header 'authorization: Bearer BEARER_TOKEN_GOES_HERE'Response
The response will contain the details of the onboarding form, which includes sections of information that need to be filled in to complete the onboarding.
Example Response
{
"data": {
"sections": [
{
"title": "A Generic Page",
"fields": [
{
"id": "text_field",
"type": "TEXT",
"label": "A Text Field",
"isRequired": true,
"value": "Lorem the ipsum, dolor the sit"
},
{
"id": "optional_text_field",
"type": "TEXT",
"label": "An Optional Text Field",
"isRequired": false,
"value": null
},
{
"id": "date_field",
"type": "DATE",
"label": "A Date Field",
"isRequired": false,
"value": "1986-01-31"
}
]
},
{
"title": "A page with fields that have limited choices",
"fields": [
{
"id": "dropdown_field",
"type": "SELECT",
"label": "A Dropdown Field",
"isRequired": true,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "DROPDOWN",
"select": "ONE"
},
{
"id": "radio_field",
"type": "SELECT",
"label": "A Radio Field",
"isRequired": true,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "RADIO",
"select": "ONE"
}
]
},
{
"title": "A page with file uploads",
"fields": [
{
"id": "file_upload_1",
"type": "DOCUMENT",
"label": "File Upload 1",
"isRequired": false,
"value": null
}
]
},
{
"title": "A page with checkbox group",
"fields": [
{
"id": "checkbox_group_1",
"type": "SELECT",
"label": "Checkbox Group 1",
"isRequired": false,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "CHECKBOX",
"select": "MULTI"
}
]
},
{
"title": "A page with field groups",
"fields": [
{
"id": "first_field_group",
"type": "GROUP",
"isRequired": false,
"title": "Field group with single field",
"fields": [
{
"id": "field_group_text_field",
"type": "TEXT",
"label": "A Text Field",
"isRequired": true,
"value": null
}
]
},
{
"id": "second_field_group",
"type": "GROUP",
"isRequired": false,
"title": null,
"fields": [
{
"id": "field_group_text_field_2",
"type": "TEXT",
"label": "A Text Field in a Field Group without title",
"isRequired": false,
"value": null
},
{
"id": "field_group_text_field_3",
"type": "TEXT",
"label": "Another Text Field",
"isRequired": false,
"value": null
}
]
}
]
},
{
"title": "A page with bank account",
"fields": [
{
"id": "bank_account_1",
"type": "BANK_ACCOUNT",
"label": "A bank account field",
"isRequired": true,
"value": null
}
]
}
],
"state": "DRAFT"
}
}2. Update Employment Onboarding Form
Once you have the onboarding form from the previous step, you will need to fill out the required details using the Update the onboarding form endpoint.
Note: BANK_ACCOUNT and DOCUMENT field types should be updated using the Create bank account and Update bank account endpoints and Upload a document to the onboarding form endpoints, respectively.
Example Request
curl --request PATCH \
--url https://api.oysterhr.com/v0.1/hiring/employments/urY7zKOm/onboarding/form \
--header 'accept: application/json' \
--header 'authorization: Bearer BEARER_TOKEN_GOES_HERE' \
--header 'content-type: application/json' \
--data '
{
"fields": [
{
"id": "first_name",
"value": "Test"
}
]
}
'Response
If successful, the API will return the updated form details, confirming that the specified fields were modified.
Example Response
{
"data": {
"sections": [
{
"title": "A Generic Page",
"fields": [
{
"id": "text_field",
"type": "TEXT",
"label": "A Text Field",
"isRequired": true,
"value": "Lorem the ipsum, dolor the sit"
},
{
"id": "optional_text_field",
"type": "TEXT",
"label": "An Optional Text Field",
"isRequired": false,
"value": null
},
{
"id": "date_field",
"type": "DATE",
"label": "A Date Field",
"isRequired": false,
"value": "1986-01-31"
}
]
},
{
"title": "A page with fields that have limited choices",
"fields": [
{
"id": "dropdown_field",
"type": "SELECT",
"label": "A Dropdown Field",
"isRequired": true,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "DROPDOWN",
"select": "ONE"
},
{
"id": "radio_field",
"type": "SELECT",
"label": "A Radio Field",
"isRequired": true,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "RADIO",
"select": "ONE"
}
]
},
{
"title": "A page with file uploads",
"fields": [
{
"id": "file_upload_1",
"type": "DOCUMENT",
"label": "File Upload 1",
"isRequired": false,
"value": null
}
]
},
{
"title": "A page with checkbox group",
"fields": [
{
"id": "checkbox_group_1",
"type": "SELECT",
"label": "Checkbox Group 1",
"isRequired": false,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "CHECKBOX",
"select": "MULTI"
}
]
},
{
"title": "A page with field groups",
"fields": [
{
"id": "first_field_group",
"type": "GROUP",
"isRequired": false,
"title": "Field group with single field",
"fields": [
{
"id": "field_group_text_field",
"type": "TEXT",
"label": "A Text Field",
"isRequired": true,
"value": null
}
]
},
{
"id": "second_field_group",
"type": "GROUP",
"isRequired": false,
"title": null,
"fields": [
{
"id": "field_group_text_field_2",
"type": "TEXT",
"label": "A Text Field in a Field Group without title",
"isRequired": false,
"value": null
},
{
"id": "field_group_text_field_3",
"type": "TEXT",
"label": "Another Text Field",
"isRequired": false,
"value": null
}
]
}
]
},
{
"title": "A page with bank account",
"fields": [
{
"id": "bank_account_1",
"type": "BANK_ACCOUNT",
"label": "A bank account field",
"isRequired": true,
"value": null
}
]
}
],
"state": "DRAFT"
}
}Conditional Enabled Fields on the Onboarding Form
Onboarding form fields can carry an enabled condition that controls whether the field is applicable given the current state of the form. There are two types:
- Static: the field is always enabled (
true) or always disabled (false), regardless of other answers. - Conditional rule: the field is enabled or disabled depending on the value of one or more other fields in the form.
When a conditional rule evaluates to false, the field is considered disabled — it is not applicable for the current combination of answers, and any value it holds should be treated as irrelevant.
Behavior on UPDATE (PATCH onboarding form)
When you send answers to the update endpoint, the API applies two distinct checks related to conditional enabled fields:
1. Pre-save validation
Before saving the new answers, the API validates that none of the submitted fields are currently disabled by a conditional rule. If you include a value for a disabled conditional field, the request is rejected with:
HTTP 422 Unprocessable Entity
{
"errors": [{ "message": "The request contains a value for conditionally disabled field(s): <field_id>" }]
}
This applies both to regular fields and to document upload fields — uploading a document to a conditionally disabled document field returns the same 422 response.
2. Automatic cascading clears
After saving the submitted answers, the API re-evaluates all conditional fields against the updated form state. Any field that has become disabled as a result of the new answers — and that still holds a previously saved value — is automatically cleared to blank. This happens silently: no error is raised, and the cleared field IDs are not reported in the response.
This means you do not need to manually clear fields that become disabled due to answers you are submitting — the API handles it.
Behavior on SUBMIT (POST onboarding form submit)
On submission, the API does not validate whether disabled conditional fields hold values. Instead, it performs a cleanup pass: any field that is currently disabled by a conditional rule and still has a saved value is automatically cleared before the form transitions to pending_review. This ensures the final submitted data never contains stale values from fields that conditions have since disabled.
3. Complete Employment Onboarding
Once the onboarding form is filled and ready, including having updated the BANK_ACCOUNT and relevant DOCUMENT fields as outlined here, you must mark it as completed using the Mark onboarding form as complete endpoint. Once you do this, the onboarding form will no longer be editable.
When completing the onboarding form if a field is required (isRequired: true) it must have a value in the valid type for the completion to be successful.
Example Request
curl --request POST \
--url https://api.oysterhr.com/v0.1/hiring/employments/urY7zKOm/onboarding/form/complete \
--header 'accept: application/json' \
--header 'authorization: Bearer BEARER_TOKEN_GOES_HERE'
Response
A successful completion will return a confirmation that the form has been marked as completed.
Example Response
{
"data": {
"sections": [
{
"title": "A Generic Page",
"fields": [
{
"id": "text_field",
"type": "TEXT",
"label": "A Text Field",
"isRequired": true,
"value": "Lorem the ipsum, dolor the sit"
},
{
"id": "optional_text_field",
"type": "TEXT",
"label": "An Optional Text Field",
"isRequired": false,
"value": null
},
{
"id": "date_field",
"type": "DATE",
"label": "A Date Field",
"isRequired": false,
"value": "1986-01-31"
}
]
},
{
"title": "A page with fields that have limited choices",
"fields": [
{
"id": "dropdown_field",
"type": "SELECT",
"label": "A Dropdown Field",
"isRequired": true,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "DROPDOWN",
"select": "ONE"
},
{
"id": "radio_field",
"type": "SELECT",
"label": "A Radio Field",
"isRequired": true,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "RADIO",
"select": "ONE"
}
]
},
{
"title": "A page with file uploads",
"fields": [
{
"id": "file_upload_1",
"type": "DOCUMENT",
"label": "File Upload 1",
"isRequired": false,
"value": null
}
]
},
{
"title": "A page with checkbox group",
"fields": [
{
"id": "checkbox_group_1",
"type": "SELECT",
"label": "Checkbox Group 1",
"isRequired": false,
"value": null,
"options": [
{
"value": "choice_1",
"label": "The first choice"
},
{
"value": "choice_2",
"label": "The second choice"
}
],
"mode": "CHECKBOX",
"select": "MULTI"
}
]
},
{
"title": "A page with field groups",
"fields": [
{
"id": "first_field_group",
"type": "GROUP",
"isRequired": false,
"title": "Field group with single field",
"fields": [
{
"id": "field_group_text_field",
"type": "TEXT",
"label": "A Text Field",
"isRequired": true,
"value": null
}
]
},
{
"id": "second_field_group",
"type": "GROUP",
"isRequired": false,
"title": null,
"fields": [
{
"id": "field_group_text_field_2",
"type": "TEXT",
"label": "A Text Field in a Field Group without title",
"isRequired": false,
"value": null
},
{
"id": "field_group_text_field_3",
"type": "TEXT",
"label": "Another Text Field",
"isRequired": false,
"value": null
}
]
}
]
},
{
"title": "A page with bank account",
"fields": [
{
"id": "bank_account_1",
"type": "BANK_ACCOUNT",
"label": "A bank account field",
"isRequired": true,
"value": null
}
]
}
],
"state": "COMPLETED"
}
}Conclusion
Once you have successfully submitted the onboarding form, the contract can be generated for signature. To see how to handle the contract signature process via API, please see the Managing EOR employment agreements via API guide.
Updated 17 days ago
