Creating Employees with Remote API

Overview

The Remote API lets you programmatically create and manage employees across 60+ countries. Whether you’re building an HR integration or automating your hiring pipeline, this guide walks you through creating employees for each of Remote’s products: Employer of Record (EOR), Global Payroll (GP), HRIS, and Contractors.

All employment types are created through the same endpoint — POST /v1/employments — but the required fields and onboarding flow differ depending on the type you specify.

Prerequisites

Authentication

Obtain a Bearer token from your Remote account (Integrations > Remote API > Access API). Tokens are environment-specific:

EnvironmentBase URL
Sandboxhttps://gateway.remote-sandbox.com
Productionhttps://gateway.remote.com

All examples below use the sandbox URL. Replace it with the production URL when you’re ready to go live.

Your Company ID

You’ll need your company_id for some operations (e.g., listing legal entities). Your company_id is included in every employment response under the company_id field. You can also find it in Company Settings in the Remote dashboard.

To retrieve it via API, show any existing employment:

curl -X GET https://gateway.remote-sandbox.com/v1/employments \
  -H "Authorization: Bearer$TOKEN"

The company_id appears in each employment object in the detailed (show) response.

Step 1: Check Country Availability

Not every country is supported for every product. Verify your target country first:

curl -X GET https://gateway.remote-sandbox.com/v1/countries \
  -H "Authorization: Bearer$TOKEN"

This returns a list of supported countries with their three-letter country codes (e.g., "AUS" for Australia, "CAN" for Canada). Use these codes in subsequent requests.

Step 2: Fetch the Country-Specific JSON Schema

Remote uses dynamic JSON schemas to define which fields are required for each country. Before creating an employment, fetch the schema for your target country:

curl -X GET https://gateway.remote-sandbox.com/v1/countries/CAN/employment_basic_information \
  -H "Authorization: Bearer$TOKEN"

The response is a standard JSON Schema that tells you exactly which fields to include in basic_information. Common fields across most countries include:

  • name — Employee’s full name
  • email — Personal email address
  • job_title — Position title
  • provisional_start_date — Start date (YYYY-MM-DD)
  • has_seniority_date — Whether the employee has a prior seniority date ("yes" / "no")
  • tax_job_category — Job category for tax purposes (enum, e.g., "engineering_it")
  • tax_servicing_countries — Countries where the employee’s work is consumed (array of country names)

Some countries require additional fields (e.g., mobile_number for Germany). Always generate your form or payload dynamically from the schema — don’t hardcode fields.

💡Tip: The schema’s meta.mot field tells you the Minimum Onboarding Time — the number of working days required between today and the start date. The API enforces this, along with weekend and holiday restrictions on start dates.

Step 3: Look Up Legal Entities (for Global Payroll)

If you’re creating a Global Payroll employee, you need to specify which of your legal entities will employ them. List your company’s legal entities:

curl -X GET https://gateway.remote-sandbox.com/v1/companies/$COMPANY_ID/legal-entities \
  -H "Authorization: Bearer$TOKEN"

The response includes each entity’s id, name, country_code, is_default, and global_payroll_enabled flag. You’ll use the entity id as the engaged_by_entity_slug parameter when creating the employment.

Example response:

{
  "data": {
    "legal_entities": [
      {
        "id": "91bcb900-c56e-41d1-8b46-e76b80f468c2",
        "name": "Acme UK Ltd",
        "country_code": "GBR",
        "is_default": false,
        "global_payroll_enabled": true
      }
    ]
  }
}

Pick an entity where global_payroll_enabled is true and country_code matches the employee’s country.

This step is only required for Global Payroll employees. For EOR employees, Remote’s own local entities act as the legal employer — you don’t need to provide one.

Step 4: Create the Employment

All employment types use the same endpoint with different type values.

4A. EOR Employee (type: "employee")

This is the most common case. Remote acts as the legal employer in the employee’s country, handling payroll, taxes, benefits, and compliance on your behalf.

curl -X POST https://gateway.remote-sandbox.com/v1/employments \
  -H "Authorization: Bearer$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": "your-company-id",
    "country_code": "PRT",
    "type": "employee",
    "basic_information": {
      "name": "Jane Smith",
      "email": "[email protected]",
      "job_title": "Software Engineer",
      "provisional_start_date": "2026-05-04",
      "has_seniority_date": "no",
      "tax_job_category": "engineering_it",
      "tax_servicing_countries": ["United States"]
    }
  }'

A successful response returns the employment nested under data.employment:

{
  "data": {
    "employment": {
      "id": "41381c22-0a0f-4190-ba95-39aa055968f2",
      "type": "employee",
      "status": "created",
      "user_status": "created",
      "employment_lifecycle_stage": "employment_creation",
      "full_name": "Jane Smith",
      "job_title": "Software Engineer",
      "provisional_start_date": "2026-05-04",
      "active_contract_id": "c9a2d695-7005-4e5a-a02b-1981121a49d3"
    }
  }
}

4B. Global Payroll Employee (type: "global_payroll_employee")

Use this when you already have a legal entity in the employee’s country and want Remote to handle payroll processing. The key difference: you must provide engaged_by_entity_slug to specify which of your legal entities will engage this employee.

Use this when you already have a legal entity in the employee’s country and want Remote to handle payroll processing. The key difference: you must provide engaged_by_entity_slug to specify which of your legal entities will engage this employee.

curl -X POST https://gateway.remote-sandbox.com/v1/employments \
  -H "Authorization: Bearer$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": "your-company-id",
    "country_code": "GBR",
    "type": "global_payroll_employee",
    "engaged_by_entity_slug": "91bcb900-c56e-41d1-8b46-e76b80f468c2",
    "basic_information": {
      "name": "John Doe",
      "email": "[email protected]",
      "job_title": "Product Manager",
      "provisional_start_date": "2026-05-04",
      "has_seniority_date": "no"
    }
  }'

⚠️ Important: The engaged_by_entity_slug must match an id from the legal entities endpoint (Step 3) where global_payroll_enabled is true. This tells Remote which of your entities is responsible for this employee’s payroll and billing.

4C. HRIS Employee (type: "hris")

HRIS employees are tracked in Remote for record-keeping purposes. Your company handles employment and payroll directly — Remote provides the platform for managing employee data.

curl -X POST https://gateway.remote-sandbox.com/v1/employments \
  -H "Authorization: Bearer$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": "your-company-id",
    "country_code": "DEU",
    "type": "hris",
    "basic_information": {
      "name": "Anna Müller",
      "email": "[email protected]",
      "job_title": "Designer",
      "provisional_start_date": "2026-05-04",
      "has_seniority_date": "no",
      "tax_job_category": "engineering_it",
      "tax_servicing_countries": ["Germany"]
    }
  }'

ℹ️ Note: Some countries (like Germany) require additional fields such as mobile_number. Always check the JSON schema for your target country first.

4D. Contractor (type: "contractor")

Contractors can be created with type: "contractor". Note that contractor management has some API limitations — check the current API reference for the latest supported operations.

curl -X POST https://gateway.remote-sandbox.com/v1/employments \
  -H "Authorization: Bearer$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": "your-company-id",
    "country_code": "BRA",
    "type": "contractor",
    "basic_information": {
      "name": "Carlos Silva",
      "email": "[email protected]",
      "job_title": "Consultant",
      "provisional_start_date": "2026-05-04"
    }
  }'

The response includes contractor-specific fields like contractor_type (e.g., "standard") and contractor_settings.

Step 5: Update the Employment

After creating an employment, you'll typically need to fill in additional details before the employee can be invited. The update endpoint accepts multiple field sets in a single request.

Discovering required fields per field set

Just as you fetched the employment_basic_information schema in Step 2, you can fetch the schema for any field set by replacing the form name in the URL:

GET /v1/countries/{country_code}/{form_name}

Available form names (check supported_json_schemas in the country response for the full list):

Form nameMaps to update field
employment_basic_informationbasic_information
contract_detailscontract_details
administrative_detailsadministrative_details
address_detailsaddress_details
emergency_contactemergency_contact_details

Additional field sets like personal_details and bank_account_details also have schemas available — query them the same way.

For example, to see what contract_details requires for the UK:

curl -X GET <https://gateway.remote-sandbox.com/v1/countries/GBR/contract_details> \\
  -H "Authorization: Bearer $TOKEN"

The response tells you exactly which fields are required and what values are valid. For GBR contract_details, this includes annual_gross_salary, work_hours_per_week, contract_duration_type, probation_length, benefits, and more.

You can also check which field sets still need to be filled by reading the onboarding_tasks object on the employment — each task shows "status": "pending" or "status": "completed".

Example: updating multiple field sets

curl -X PATCH <https://gateway.remote-sandbox.com/v1/employments/$EMPLOYMENT_ID> \\
  -H "Authorization: Bearer $TOKEN" \\
  -H "Content-Type: application/json" \\
  -d '{
    "basic_information": {
      "name": "Jane Smith",
      "email": "[email protected]",
      "job_title": "Senior Software Engineer",
      "provisional_start_date": "2026-05-04",
      "has_seniority_date": "no",
      "tax_job_category": "engineering_it",
      "tax_servicing_countries": ["United States"]
    },
    "contract_details": {
      "annual_gross_salary": 8500000,
      "contract_duration_type": "indefinite"
    },
    "address_details": {
      "city": "Lisbon",
      "postal_code": "1000-001"
    },
    "emergency_contact_details": {
      "name": "John Smith",
      "phone_number": "+15551234567"
    }
  }'

⚠️ Important: Each field set requires you to send all its fields, not just the ones you're changing. Omitting a field will clear it.

What you can update depends on employment status

The set of allowed fields narrows as the employment progresses through its lifecycle:

Employment statusAllowed field sets
createdbasic_information, contract_details, administrative_details, address_details, emergency_contact_details, pricing_plan_details, personal_details, bank_account_details, work_email, external_id
invitedwork_email, external_id only
activemanager_id, emergency_contact_details, address_details, work_email, external_id

GP-specific differences

  • Active GP employees can also update personal_details — this is not allowed for EOR employees.
  • engaged_by_entity_slug cannot be changed after creation. The legal entity assignment is set at creation time and is not available on the update endpoint. If you need to change which entity engages an employee, this cannot be done via the API.

Step 6: Invite the Employee

Send the onboarding invitation. The employee receives an email from Remote and begins self-enrollment — providing any remaining details themselves:

curl -X POST https://gateway.remote-sandbox.com/v1/employments/$EMPLOYMENT_ID/invite \
  -H "Authorization: Bearer$TOKEN"

A successful response returns {"status": "ok"}. The employment’s employment_lifecycle_stage transitions to "employee_self_enrollment" and the status becomes "invited".

Prerequisite: The employment must have contract_details and pricing_plan_details filled in before you can send the invitation. If these are missing, the API returns: "Can't invite employee missing contract details and pricing plan details".

Step 7: Track Onboarding Progress

Monitor the employment’s status as it moves through the onboarding lifecycle:

curl -X GET https://gateway.remote-sandbox.com/v1/employments/$EMPLOYMENT_ID \
  -H "Authorization: Bearer$TOKEN"

Key fields to watch:

FieldDescription
statusOverall employment status (createdinvitedactive)
user_statusUser account status (createdinvitedactive)
employment_lifecycle_stageCurrent onboarding phase (employment_creationemployee_self_enrollmentonboarded)

The response also includes an onboarding_tasks object showing the status of each task (e.g., address_details, bank_account_details, contract_details) as "pending" or "completed".

Employment Types at a Glance

EORGlobal PayrollHRISContractor
type valueemployeeglobal_payroll_employeehriscontractor
Legal employerRemote’s entityYour entityYour entityN/A
engaged_by_entity_slugNot neededRequiredNot neededNot needed
Onboarding flowFull (invite + self-enrollment)FullLighterVaries
PayrollManaged by RemoteProcessed by RemoteManaged by youInvoicing

Sandbox Tips

  • Start dates are relaxed — In sandbox, the Minimum Onboarding Time (MOT) validation is relaxed and past dates are accepted. However, holiday validation still applies — e.g., May 1st (Labour Day) is rejected in many countries. Pick a regular weekday.
  • Use unique test emails — Append +tag to your email (e.g., [email protected]) to verify invitation emails arrive correctly.
  • No charges — Sandbox employments are free. Create as many as you need.

What's Next