---
updatedAt: 2026-07-17T21:49:22.000Z
agentTools:
  projectIndex: https://developer.remote.com/llms.txt
---

# 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:

| Environment | Base URL                             |
| ----------- | ------------------------------------ |
| Sandbox     | `https://gateway.remote-sandbox.com` |
| Production  | `https://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:

```bash
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:

```bash
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:

```bash
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.

> :bulb:**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:

```bash
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:

```json
{
  "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.

```bash
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": "jane@example.com",
      "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`:

```json
{
  "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.

```bash
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": "john@example.com",
      "job_title": "Product Manager",
      "provisional_start_date": "2026-05-04",
      "has_seniority_date": "no"
    }
  }'
```

> :warning: **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.

```bash
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": "anna@example.com",
      "job_title": "Designer",
      "provisional_start_date": "2026-05-04",
      "has_seniority_date": "no",
      "tax_job_category": "engineering_it",
      "tax_servicing_countries": ["Germany"]
    }
  }'
```

> :information\_source: **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](https://developer.remote.com/reference/welcome-to-remote-api) for the latest supported operations.

```bash
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": "carlos@example.com",
      "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 name                      | Maps to update field        |
| ------------------------------ | --------------------------- |
| `employment_basic_information` | `basic_information`         |
| `contract_details`             | `contract_details`          |
| `administrative_details`       | `administrative_details`    |
| `address_details`              | `address_details`           |
| `emergency_contact`            | `emergency_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:

```bash
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

```bash
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": "jane@example.com",
      "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"
    }
  }'
```

> :warning: **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 status | Allowed field sets                                                                                                                                                                                                 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `created`         | `basic_information`, `contract_details`, `administrative_details`, `address_details`, `emergency_contact_details`, `pricing_plan_details`, `personal_details`, `bank_account_details`, `work_email`, `external_id` |
| `invited`         | `work_email`, `external_id` only                                                                                                                                                                                   |
| `active`          | `manager_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:

```bash
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:

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

Key fields to watch:

| Field                        | Description                                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------------------- |
| `status`                     | Overall employment status (`created` → `invited` → `active`)                                |
| `user_status`                | User account status (`created` → `invited` → `active`)                                      |
| `employment_lifecycle_stage` | Current onboarding phase (`employment_creation` → `employee_self_enrollment` → `onboarded`) |

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

|                              | EOR                             | Global Payroll            | HRIS           | Contractor   |
| ---------------------------- | ------------------------------- | ------------------------- | -------------- | ------------ |
| **`type` value**             | `employee`                      | `global_payroll_employee` | `hris`         | `contractor` |
| **Legal employer**           | Remote’s entity                 | Your entity               | Your entity    | N/A          |
| **`engaged_by_entity_slug`** | Not needed                      | **Required**              | Not needed     | Not needed   |
| **Onboarding flow**          | Full (invite + self-enrollment) | Full                      | Lighter        | Varies       |
| **Payroll**                  | Managed by Remote               | Processed by Remote       | Managed by you | Invoicing    |

## 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., `you+test1@gmail.com`) to verify invitation emails arrive correctly.
* **No charges** — Sandbox employments are free. Create as many as you need.

## What's Next

* [Prerequisites](https://developer.remote.com/docs/prerequisites) — JSON schema details and date validation rules
* [Create Employment](https://developer.remote.com/docs/create-new-employment) — Full creation guide
* [Update and Invite](https://developer.remote.com/docs/update-and-invite-employment) — Updating records and sending invitations
* [Onboarding Workflow](https://developer.remote.com/docs/onboarding-an-employee) — End-to-end EOR onboarding
* [JSON Schemas](https://developer.remote.com/docs/how-json-schemas-work) — How country-specific schemas work
* [API Reference](https://developer.remote.com/reference/welcome-to-remote-api) — Full endpoint reference