Creating and submitting an EOR employment

This guide will show you how to create a draft employment, update the job details, and submit the employment to kick off the employment onboarding and contract generation.

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. Create Employment

First you need to create an employment record, which represents the start of the hiring process for an engagement. In your request, you will need to include the employment’s ISO-3166 Alpha country code, full legal name, email, and nationality.

Example Request

curl --request POST \
     --url https://api.oysterhr.com/v0.1/hiring/employments/ \
     --header 'accept: application/json' \
     --header 'authorization: Bearer BEARER_TOKEN_GOES_HERE' \
     --header 'content-type: application/json' \
     --data '
{
  "personalDetails": {
    "fullLegalName": "Test Hire",
    "email": "[email protected]",
    "nationality": "US"
  },
  "countryCode": "US",
  "subdivisionCode": "CA"
}
'

Response

If successful, the API will return a 201 Created response with the newly created employment details, including an id that you will need for future updates and submission. The employment will then be in a draft phase and ready to continue filling the contractual details.

Example Response

{
  "data": {
    "engagementId": "urY7zKOm",
    "countryCode": "US",
    "subdivisionCode": "CA",
    "personalDetails": {
      "fullLegalName": "Test Hire",
      "email": "[email protected]",
      "nationality": "US",
      "workPermit": null
    },
    "manager": {
      "managerRole": null,
      "managerName": null,
      "managerEmailAddress": null,
      "managerPhoneNumber": null,
      "managerIsExpenseApprover": false
    },
    "role": {
      "newHireStatus": "new_hire",
      "seniorityLevel": null,
      "roleTypeId": null,
      "role": null,
      "jobDescription": null,
      "startDate": null,
      "endDate": null,
      "employmentType": null,
      "probationPeriod": null,
      "terminationNotice": null,
      "resignationNotice": null
    },
    "compensation": {
      "commissionPlanOffered": null,
      "commissionPlan": null,
      "salary": {
        "decimal": "",
        "currencyCode": "USD"
      },
      "paidHolidayDays": null,
      "bonuses": [],
      "allowances": [],
      "reimbursementBudgets": [],
      "remoteWorkCosts": null,
      "privateNotes": null,
      "sickPay": null
    },
    "documents": [],
    "defaultSigner": null
  }
}

2. Update Employment

Once you’ve created the employment, you will need to update the employment with details related to the job position. In the request body, only include the fields you want to update (e.g., job_title, annual_salary, etc.).

Example Request

curl --request PATCH \
     --url https://api.oysterhr.com/v0.1/hiring/employments/urY7zKOm \
     --header 'accept: application/json' \
     --header 'authorization: Bearer BEARER_TOKEN_GOES_HERE' \
     --header 'content-type: application/json' \
     --data '
{
  "role": {
    "role": "Senior Software Engineer"
  },
  "compensation": {
    "salary": {
      "decimal": "95000",
      "currencyCode": "USD"
    },
  }
}
'

To successfully submit an Employment in the next step, most fields are required based on the Employment's designated country.

FieldsRequiredNotes
seniority_levelYes
role_typeYesThis can be looked up using the Role Types endpoint
roleYesThe job title of the employee
job_descriptionYes
start_dateYes
end_dateYes
employment_typeYesThis must be either FULL_TIME or PART_TIME
working_hoursYes
probation_periodYes
salaryYes
resignation_noticeYesThis field is required in: Australia, UK, Ireland, India
termination_noticeYesThis field is required in: Australia, UK, Ireland, India
remote_work_costsYes
vacationYes
sick_payYesThis field is required in: UK, Ireland, Netherlands
default_signerYes

Response

A successful update returns the modified employment details. The status will still be draft until the employment is submitted in the following step.

Example Response

{
  "data": {
    "engagementId": "urY7zKOm",
    "countryCode": "US",
    "subdivisionCode": "CA",
    "personalDetails": {
      "fullLegalName": "Test Hire",
      "email": "[email protected]",
      "nationality": "US",
      "workPermit": null
    },
    "manager": {
      "managerRole": null,
      "managerName": null,
      "managerEmailAddress": null,
      "managerPhoneNumber": null,
      "managerIsExpenseApprover": false
    },
    "role": {
      "newHireStatus": "new_hire",
      "seniorityLevel": "SENIOR",
      "roleTypeId": null,
      "role": "Senior Software Engineer",
      "jobDescription": null,
      "startDate": null,
      "endDate": null,
      "employmentType": null,
      "probationPeriod": null,
      "terminationNotice": null,
      "resignationNotice": null,
      "fullTimeHoursPerWeek": null
    },
    "compensation": {
      "commissionPlanOffered": null,
      "commissionPlan": null,
      "salary": {
        "decimal": "95000",
        "currencyCode": "USD"
      },
      "paidHolidayDays": null,
      "bonuses": [],
      "allowances": [],
      "reimbursementBudgets": [],
      "remoteWorkCosts": null,
      "privateNotes": null,
      "sickPay": null
    },
    "documents": [],
    "defaultSigner": null
  }
}

Optional steps

Depending on the desired contract conditions, the following optional endpoints can be used:


3. Submit Employment

Once all the necessary information is submitted, you can submit the employment for processing. This marks the employment as In Progress, at which point the employment onboarding can take place before the contracts are sent out for signature.

Example Request

curl --request POST \
     --url https://api.oysterhr.com/v0.1/hiring/employments/urY7zKOm/submit \
     --header 'accept: application/json' \
     --header 'authorization: Bearer BEARER_TOKEN_GOES_HERE'

Response

If successful, you will receive a 200 response with the employment information.

Example Response

{
  "data": {
    "engagementId": "urY7zKOm",
    "countryCode": "US",
    "subdivisionCode": "CA",
    "personalDetails": {
      "fullLegalName": "Test Hire",
      "email": "[email protected]",
      "nationality": "US",
      "workPermit": null
    },
    "manager": {
      "managerRole": null,
      "managerName": null,
      "managerEmailAddress": null,
      "managerPhoneNumber": null,
      "managerIsExpenseApprover": false
    },
    "role": {
      "newHireStatus": "new_hire",
      "seniorityLevel": "SENIOR",
      "roleTypeId": 05,
      "role": "Senior Software Engineer",
      "jobDescription": "job description",
      "startDate": "2024-10-14",
      "endDate": null,
      "employmentType": "FULL_TIME",
      "probationPeriod": {
        "value": 12,
        "unit": "MONTHS"
      },
      "terminationNotice": null,
      "resignationNotice": null,
      "fullTimeHoursPerWeek": 40
    },
    "compensation": {
      "commissionPlanOffered": null,
      "commissionPlan": null,
      "salary": {
        "decimal": "95000",
        "currencyCode": "USD"
      },
      "paidHolidayDays": 14,
      "bonuses": [],
      "allowances": [],
      "reimbursementBudgets": [],
      "remoteWorkCosts": {
        "allowancePolicy": {
          "allowancePolicy": "MONTHLY_ALLOWANCE",
          "amount": null,
          "statutoryAmount": null
        },
        "equipmentBudget": null,
        "equipmentListOwnedByTeamMember": null,
        "equipmentListProvidedByCustomer": {
          "equipmentList": [
            "KEYBOARD",
            "MOUSE",
            "PRINTER"
          ],
          "equipmentOther": null
        },
        "equipmentOneTimePayment": null
      },
      "privateNotes": null,
      "sickPay": null
    },
    "documents": [],
    "defaultSigner": {
      "fullName": "Graham Vandervort",
      "email": "[email protected]",
      "jobTitle": "Engineering Manager",
      "phone": {
        "countryCode": "US",
        "number": "555 654 5568"
      }
    }
  }
}

Notes:

  • Hires submitted via API will have statutory Benefits applied.
    • We have an upcoming Benefits API that will allow you to set non-statutory benefits. In the meantime if you want to apply non-statutory benefits for an employment, please get in touch with Oyster.
  • In countries that require values for Termination Notice, Resignation Notice and Sick Pay, statutory values will be applied.
    • Applying non-statutory values for these fields will be added in a future API update. In the meantime if you want to apply non-statutory values for any of these fields, please get in touch with Oyster.

Conclusion

Once you have successfully submitted an employment and it is in the In Progress state, the employment onboarding can begin. That can either be achieved via the platform by sending the team member an invitation or via API by following the Completing EOR employment onboarding via API guide.