Create new employees for a specified employer. Asynchronous — the response is an Upload object representing queued work, not a final result. Member identifiers are not available in this response; poll GET /uploads/{upload_id} until the status is terminal, then fetch enrolments via GET /uploads/{upload_id}/enrolments and any errors via GET /uploads/{upload_id}/errors. Processing is idempotent: re-submitting the same records will only process those not already enrolled successfully.
Body
Required
Employee creation data.
-
Email address of the employee.
-
The employee's first name.
-
The employee's last name.
-
The employee's title, e.g. Mr., Mrs., Dr., etc.
-
The employee's date of birth, in YYYY-MM-DD format.
-
The first line of the employee's address.
-
The postal code of the employee's address.
-
The employee's National Insurance number.
-
The date the employee started their employment, in YYYY-MM-DD format.
-
Your platform's unique identifier for this employee. Penfold stores it to link the employee back to your platform, for example when the employee signs in to Penfold through your platform. Required for employers managed by a Partner organisation that uses single sign-on with Penfold; omit it otherwise. Maximum 255 characters.
Maximum length is
255.
Responses
-
Submission created successfully for the employees.
-
Bad request, the request is malformed or contains invalid data.
-
Unauthorized, the request requires authentication, and the provided credentials are either missing or incorrect.
-
Employer not found, the specified employer_id does not match any existing employer.
curl \
--request POST 'https://payroll-api.getpenfold.dev/v4/employers/{employer_id}/employees' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '[
{
"email": "john.doe@example.com",
"forename": "John",
"surname": "Doe",
"title": "Mr.",
"date_of_birth": "1990-01-01",
"address_line1": "123 Main Street",
"postcode": "AB12 3CD",
"national_insurance_number": "AA123456C",
"employment_start_date": "2023-01-01",
"external_id": "emp_01HXYZ"
}
]'
[
{
"email": "john.doe@example.com",
"forename": "John",
"surname": "Doe",
"title": "Mr.",
"date_of_birth": "1990-01-01",
"address_line1": "123 Main Street",
"postcode": "AB12 3CD",
"national_insurance_number": "AA123456C",
"employment_start_date": "2023-01-01",
"external_id": "emp_01HXYZ"
}
]
{
"id": "string",
"employer_id": "string",
"put_destination_url": "string",
"created_at": "2026-05-04T09:42:00Z",
"updated_at": "2026-05-04T09:42:00Z",
"processing_started": "2023-03-01T11:00:00Z",
"processing_ended": "2023-03-01T12:00:00Z",
"processing_time": 47,
"total_errors": 10,
"contributions_created": 5,
"contributions_unprocessed": 0,
"contributions_already_existed": 0,
"employer_contributions": "500.34",
"employee_contributions": "734.11",
"total_contributions": "1234.45",
"filename": "papdis.csv",
"status": "Processed"
}
{
"error": "Bad request: invalid data provided.",
"validation_errors": [
{
"field": "email",
"message": "Email address is invalid."
}
]
}
{
"error": "Bad request: invalid data provided."
}
{
"error": "Bad request: invalid data provided."
}