Inviting an Employee
This guide walks you through the POST /employees/invite endpoint — how to invite employees, contractors, and admins to a company through the Friday API. You'll learn which fields are required for each employment type, how plan tiers affect validation, and how to handle common edge cases.
Prerequisites
- You have an API key for the company. See Getting API Access.
- You know the company's plan tier (timetracking, payroll, or premium), as it determines which employment types and fields are available.
- If inviting a payroll employee, you know the workplace ID. You can look up available workplaces with
GET /workplaces.
The Basics
Every invite request requires five fields, regardless of plan or employment type:
{
"first_name": "Jane",
"last_name": "Smith",
"email": "[email protected]",
"employment_type": "employee",
"start_date": "2026-04-01T00:00:00.000Z"
}| Field | Type | Description |
|---|---|---|
first_name | string | First name. |
last_name | string | Last name. |
email | string | Email address (must be lowercase). This is used to create the employee's account. |
employment_type | string | One of "admin", "employee", or "contractor". |
start_date | date-time | The employee's start date. |
Beyond these, which additional fields are accepted (or required) depends on the plan tier and employment type.
Plan Tiers and What They Accept
Timetracking plan
Timetracking plans support admin and employee employment types only. Contractors are not available.
On a timetracking plan, you send just the five core fields plus optional middle_name and department_id. No payroll-specific fields are accepted — the API will reject them with a 400 error.
No
timetrack_onlyflag — On timetracking plans,timetrack_onlyis not accepted in the request. All employees on a timetracking plan are inherently time-track-only because payroll is not available on this plan.
Payroll plan
Payroll plans support all three employment types: admin, employee, and contractor. You can also send payroll-specific fields like wage information, workplace, and the timetrack_only flag.
Premium plan
Premium plans have everything payroll plans have, plus manager_type for admin employees.
Employment Type Field Matrix
This table shows every field, whether it's required/optional/not accepted for each employment type, and any plan conditions.
Always required (all types, all plans)
| Field | Notes |
|---|---|
first_name | |
last_name | |
email | Must be lowercase |
employment_type | "admin", "employee", or "contractor" |
start_date | ISO 8601 date-time |
Always optional (all types, all plans)
| Field | Notes |
|---|---|
middle_name | Middle name or initial |
department_id | Integer ID of an existing department in the company |
Admin fields
| Field | Required? | Notes |
|---|---|---|
manager_type | Optional | Premium plans only. One of: "admin_manager", "payroll_manager", "timesheet_manager". Rejected on timetracking/payroll plans. |
Admins have the simplest invite payload. They don't take wage fields, workplace, SSN, or timetrack_only.
Employee fields (payroll/premium plans)
| Field | Required? | Condition |
|---|---|---|
timetrack_only | Optional | Defaults to false. When true, skips all payroll fields. Not accepted on timetracking plans. |
workplace | Required | When timetrack_only is false. This is the workplace ID from GET /workplaces. |
payment_unit | Required | When timetrack_only is false. One of: "hour", "salary", "hourly_salary". |
payment_amount | Required | When payment_unit includes "hour". Hourly rate. |
overtime_amount | Required | When payment_unit includes "hour". Overtime rate. |
salary | Required | When payment_unit includes "salary". Salary amount. Max: 999,999,999. |
salary_type | Required | When payment_unit includes "salary". One of: "yearly", "quarterly", "monthly", "semimonthly", "weekly", "biweekly". |
default_hours | Optional | Default weekly hours (0–168). |
pto_payment_amount | Optional | Hourly rate for PTO payouts. |
daily_time_limit | Optional | Daily time limit in hours. |
weekly_time_limit | Optional | Weekly time limit in hours. |
paid_lunch_time | Optional | Paid lunch time in minutes. |
is_i9_form_required | Optional | Whether the employee needs I-9 verification. |
ssn | Optional | Social Security Number (9 digits, no dashes). |
working_state | Optional | Two-letter state code for the employee's working state. |
Employee fields (timetracking plan)
On a timetracking plan, none of the payroll fields above are accepted. You send only the core fields plus middle_name and department_id.
Contractor fields (payroll/premium plans only)
| Field | Required? | Condition |
|---|---|---|
timetrack_only | Optional | Defaults to false. When true, skips all payroll fields. |
type | Optional | Contractor entity type (e.g. "individual", "business"). |
ein | Optional | Employer Identification Number for business contractors. |
business_name | Optional | Business name for business contractors. |
payment_unit | Conditional | Same wage branching logic as employees (required when timetrack_only is false). |
payment_amount | Conditional | Same as employees. |
overtime_amount | Conditional | Same as employees. |
salary | Conditional | Same as employees. |
salary_type | Conditional | Same as employees. |
default_hours | Optional | Same as employees. |
pto_payment_amount | Optional | Same as employees. |
daily_time_limit | Optional | Same as employees. |
weekly_time_limit | Optional | Same as employees. |
paid_lunch_time | Optional | Same as employees. |
ssn | Optional | Social Security Number. |
working_state | Optional | Working state. |
No workplace required — Unlike employees, contractors don't require a
workplacevalue.Contractors are not available on timetracking plans. Attempting to invite a contractor on a timetracking plan returns a
400error.
Wage Branching Logic
When timetrack_only is false (the default) and the employment type is employee or contractor on a payroll/premium plan, you must specify how the person is paid.
The payment_unit field determines which additional wage fields are required:
Hourly (payment_unit: "hour")
payment_unit: "hour"){
"payment_unit": "hour",
"payment_amount": 32.50,
"overtime_amount": 1.5
}| Field | Required? |
|---|---|
payment_amount | Yes — the hourly rate (0 is allowed) |
overtime_amount | Yes — the overtime rate |
default_hours | Optional |
Salary (payment_unit: "salary")
payment_unit: "salary"){
"payment_unit": "salary",
"salary": 85000,
"salary_type": "yearly"
}| Field | Required? |
|---|---|
salary | Yes — the salary amount (0 is allowed) |
salary_type | Yes — the period the salary represents |
Hourly + Salary (payment_unit: "hourly_salary")
payment_unit: "hourly_salary")This hybrid type requires both the hourly and salary fields:
{
"payment_unit": "hourly_salary",
"payment_amount": 25.00,
"overtime_amount": 1.5,
"salary": 52000,
"salary_type": "yearly"
}Full Examples by Scenario
Timetracking plan — Admin
The simplest possible invite. Just the core fields:
POST /employees/invite
{
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"employment_type": "admin",
"start_date": "2026-04-01T00:00:00.000Z"
}Timetracking plan — Employee
Identical structure. No payroll fields, no timetrack_only:
POST /employees/invite
{
"first_name": "Jane",
"last_name": "Smith",
"email": "[email protected]",
"employment_type": "employee",
"start_date": "2026-04-01T00:00:00.000Z"
}Payroll plan — Hourly employee
Includes workplace and hourly wage fields:
POST /employees/invite
{
"first_name": "Alex",
"last_name": "Johnson",
"email": "[email protected]",
"employment_type": "employee",
"start_date": "2026-04-01T00:00:00.000Z",
"workplace": "wrk_abc123",
"payment_unit": "hour",
"payment_amount": 32.50,
"overtime_amount": 1.5,
"default_hours": 40,
"department_id": 5
}Payroll plan — Salaried employee
POST /employees/invite
{
"first_name": "Morgan",
"last_name": "Lee",
"email": "[email protected]",
"employment_type": "employee",
"start_date": "2026-04-01T00:00:00.000Z",
"workplace": "wrk_abc123",
"payment_unit": "salary",
"salary": 85000,
"salary_type": "yearly"
}Payroll plan — Timetrack-only employee
When timetrack_only is true, no wage or workplace fields are needed:
POST /employees/invite
{
"first_name": "Pat",
"last_name": "Taylor",
"email": "[email protected]",
"employment_type": "employee",
"timetrack_only": true,
"start_date": "2026-04-01T00:00:00.000Z"
}Payroll plan — Contractor
Contractors don't require a workplace. Include contractor-specific fields like type and business_name:
POST /employees/invite
{
"first_name": "Chris",
"last_name": "Miller",
"email": "[email protected]",
"employment_type": "contractor",
"start_date": "2026-04-01T00:00:00.000Z",
"type": "business",
"business_name": "Miller Consulting LLC",
"ein": "123456789",
"payment_unit": "hour",
"payment_amount": 75.00,
"overtime_amount": 1.5
}Premium plan — Admin with manager type
POST /employees/invite
{
"first_name": "Sam",
"last_name": "Lee",
"email": "[email protected]",
"employment_type": "admin",
"start_date": "2026-04-01T00:00:00.000Z",
"manager_type": "payroll_manager"
}The Response
A successful invite returns 201 Created with a summary of the new employee record:
{
"data": {
"employee_id": 123,
"first_name": "Alex",
"middle_name": null,
"last_name": "Johnson",
"email": "[email protected]",
"employment_type": "employee",
"timetrack_only": false,
"is_active": false,
"onboarding_status": "blocking",
"status": null,
"start_date": "2026-04-01T00:00:00.000Z"
}
}Note that newly invited employees:
- Start with
is_active: false— they become active after completing onboarding. - Start with
onboarding_status: "blocking"— the employee needs to complete their onboarding steps. - Have
status: nulluntil their status is set through the onboarding process.
Use GET /employees/:employee_id to fetch the full employee detail once the record is created.
Inviting the Same Person Twice
A single person (identified by email) can hold multiple employment types at the same company. For example, you might invite [email protected] as both an admin and an employee. Each invite creates a separate employee record with its own employee_id.
However, you cannot invite the same email with the same employment type twice. If you try, the API returns:
{
"error": "Employee already exists"
}This applies per employment type. If [email protected] already has an employee record, inviting her again as employee fails — but inviting her as admin succeeds and creates a second record.
Common Pitfalls
-
Sending payroll fields on a timetracking plan — The API strictly rejects payroll-specific fields (
workplace,payment_unit,salary, etc.) when the company is on a timetracking plan. If you get a400error about payroll fields, check the company's plan withGET /companies. -
Missing wage fields — When
timetrack_onlyisfalseon a payroll/premium plan, thepayment_unitfield is required for employees. Forgetting it (or forgetting the dependent fields likepayment_amountfor hourly workers) results in a400. -
Setting
timetrack_onlyon an admin — Thetimetrack_onlyflag is not valid for admin employment types. Admins are never included in payroll by definition, so the flag has no meaning. The API returns a400if you try. -
Setting
manager_typeon a non-premium plan — Manager types are exclusive to premium plans. Sendingmanager_typeon a timetracking or payroll plan returns a400. -
Setting
manager_typeon a non-admin — Only admin employment types acceptmanager_type. Sending it for an employee or contractor returns a400. -
Forgetting the workplace — On payroll/premium plans, employees (when
timetrack_onlyisfalse) require aworkplacevalue. Contractors do not. If you're not sure which workplaces are available, callGET /workplacesfirst. -
Email case sensitivity — The
emailfield must be lowercase. The API enforces this — if you send mixed case, it will be normalized, but it's best to send lowercase from the start. -
Duplicate invites — The API checks for existing records with the same email and employment type at the same company. If a match is found, you'll get a
400. This does not prevent inviting the same email under a different employment type.
Quick Reference
| Scenario | employment_type | timetrack_only | Key required fields |
|---|---|---|---|
| Timetracking admin | admin | — | Core fields only |
| Timetracking employee | employee | — | Core fields only |
| Payroll admin | admin | — | Core fields only |
| Payroll employee (full) | employee | false | Core + workplace + payment_unit + wage fields |
| Payroll employee (TT only) | employee | true | Core fields only |
| Payroll contractor | contractor | false | Core + payment_unit + wage fields |
| Payroll contractor (TT only) | contractor | true | Core fields only |
| Premium admin w/ manager | admin | — | Core + manager_type |
What's Next
- Understand the employee object — See The Employee Object guide for a full field reference and explanation of employment types, timetrack-only, and earnings.
- Update employees — Use
PATCH /employees/:employee_idto modify profile fields, addresses, departments, and workplaces after creation. - Set up webhooks — Subscribe to
employee.createdevents to be notified when employees are added (whether through the API or the Friday dashboard). See the Webhooks guide.
Updated about 9 hours ago
