Create employer

Add MCP server to your AI tool

Allow AI tools and LLMs to interact with the API documentation portal through MCP.

MCP server URL

https://docs.getpenfold.dev/mcp

Standard setup for AI tools providing an mcp.json file

mcp.json
{
  "Penfold Payroll API v4 MCP server": {
    "url": "https://docs.getpenfold.dev/mcp"
  }
}

Close
POST /employers

Partner organisations only. A Payroll organisation calling this endpoint receives 405 Method Not Allowed.

Creates a new employer under your organisation.

The company number is validated against Companies House. If an employer with the same company number already exists in your organisation, a 409 is returned with the existing employer's external_reference.

The external_id is your platform's identifier for the employer. Penfold stores it to link the employer back to your platform. If the external_id is already linked to an employer, a 409 is returned and no employer is created.

application/json

Body Required

  • company_number string Required

    Companies House registration number

  • company_name string Required

    Registered company name

  • primary_contact_email string(email) Required

    Email address of the primary contact at the employer

  • primary_contact_role string

    Role of the primary contact at the employer

    Values are CompanyDirector, Finance, or HR.

  • payroll_frequencies array[string] Required

    How often the employer runs payroll. One or more values.

    At least 1 element. Values are Weekly, Fortnightly, FourWeekly, or Monthly.

  • expected_first_pay_period_start_date string(date) Required

    Expected start date of the first pay period (YYYY-MM-DD)

  • expected_pay_period_cadence string Required

    Expected cadence for pay periods

    Values are TaxYear, CalendarYear, or Other.

  • default_employee_contributions_percent number Required

    Default employee contribution percentage

    Minimum value is 0, maximum value is 100.

  • default_employer_contributions_percent number Required

    Default employer contribution percentage

    Minimum value is 0, maximum value is 100.

  • contribution_basis string Required

    Basis on which pension contributions are calculated

  • allows_salary_sacrifice boolean

    Whether the employer allows salary sacrifice arrangements

    Default value is false.

  • payment_method string Required

    How the employer will pay pension contributions. It cannot be changed through this API once the employer is created.

    Values are BankTransfer or DirectDebit.

  • number_of_employees integer Required

    Approximate number of employees to be enrolled

    Minimum value is 1.

  • external_id string Required

    Your platform's unique identifier for this employer. Penfold stores it to link the employer back to your platform, for example when the employer's users sign in to Penfold through your platform. It must be unique across all employers you create; reusing a value that is already linked to an employer returns a 409.

Responses

  • 201 application/json

    Employer created successfully

    Hide response attributes Show response attributes object
    • id string

      The unique identifier for the employer.

    • created_at string(date-time)

      The date and time the employer record was created, in ISO 8601 format.

    • updated_at string(date-time)

      The date and time the employer record was last updated, in ISO 8601 format.

    • name string

      The name of the employer.

    • contribution_basis string

      The basis on which the employer makes pension contributions. Informational only — Penfold does not validate submitted contribution amounts against this basis. Integrators must compute final amounts themselves. Possible values:

      • QualifyingEarnings: contributions calculated on banded earnings (currently £6,240–£50,270).
      • TotalPay: contributions calculated on all earnings, with no banding.
      • BasicPay: contributions calculated on basic pay only.

      Values are QualifyingEarnings, TotalPay, or BasicPay.

    • allows_salary_sacrifice boolean

      Whether the employer allows for salary sacrifice. Informational only — indicates whether the employer permits salary sacrifice arrangements. Penfold processes submissions as-is and makes no amendments to contribution amounts; integrators must provide final amounts regardless of salary sacrifice status.

      Default value is false.

    • external_reference string

      An external reference for the employer. Should be used as the value in the EmployerId column in file uploads.

    • company_number string

      Companies House registration number.

    • payment_method string | null

      The payment method used by the employer.

      Values are BankTransfer or DirectDebit. Default value is DirectDebit.

    • primary_contact_email string(email) | null

      The email address of the primary contact for the employer.

    • primary_contact_role string | null

      Role of the employer primary contact.

      Values are CompanyDirector, Finance, or HR.

    • default_employee_contributions_percent number | null

      Default employee contribution percentage.

      Minimum value is 0, maximum value is 100.

    • default_employer_contributions_percent number | null

      Default employer contribution percentage.

      Minimum value is 0, maximum value is 100.

    • aml_verification_status string

      The status of the employer company's AML verification.

      Values are Pending, Accepted, Failed, or Open.

    • status

      The status of the employer.

      Values are PendingPa, MissingDD, Pending, or Active. Default value is PendingPa.

    • direct_debit_mandate_status string

      The status of the employer's Direct Debit mandate. null means Penfold holds no mandate record for the employer.

      Values are PendingCustomerApproval, PendingSubmission, Submitted, Active, SuspendedByPayer, Failed, Cancelled, Expired, Consumed, or Blocked.

  • 400 application/json

    Bad request, the request is malformed or contains invalid data.

    Hide response attributes Show response attributes object
    • error string

      A descriptive error message.

    • validation_errors array[object]
      Hide validation_errors attributes Show validation_errors attributes object
      • field string Required

        The name of the field that failed validation.

      • message string Required

        A descriptive error message.

  • 401 application/json

    Unauthorized

    Hide response attribute Show response attribute object
    • error string

      A descriptive error message.

  • 403 application/json

    Forbidden

    Hide response attribute Show response attribute object
    • error string

      A descriptive error message.

  • 404 application/json

    Company not found in Companies House

    Hide response attribute Show response attribute object
    • error string

      A descriptive error message.

  • 405 application/json

    Method not allowed

    Hide response attribute Show response attribute object
    • error string

      A descriptive error message.

  • 409 application/json

    An employer already exists for this company number, or the external_id is already linked to an existing employer. Check code to distinguish the two.

    Any of:
  • 500 application/json

    Internal server error

    Hide response attribute Show response attribute object
    • error string

      A descriptive error message.

POST /employers
curl \
 --request POST 'https://payroll-api.getpenfold.dev/v4/employers' \
 --header "Authorization: Bearer $ACCESS_TOKEN" \
 --header "Content-Type: application/json" \
 --data '{
  "company_number": "12345678",
  "company_name": "Acme Ltd",
  "primary_contact_email": "payroll@acme.com",
  "primary_contact_role": "HR",
  "payroll_frequencies": [
    "Monthly"
  ],
  "expected_first_pay_period_start_date": "2025-03-01",
  "expected_pay_period_cadence": "TaxYear",
  "default_employee_contributions_percent": 5,
  "default_employer_contributions_percent": 3,
  "contribution_basis": "QualifyingEarnings",
  "allows_salary_sacrifice": false,
  "payment_method": "DirectDebit",
  "number_of_employees": 50,
  "external_id": "org_01HXYZ"
}'
Request examples
{
  "company_number": "12345678",
  "company_name": "Acme Ltd",
  "primary_contact_email": "payroll@acme.com",
  "primary_contact_role": "HR",
  "payroll_frequencies": [
    "Monthly"
  ],
  "expected_first_pay_period_start_date": "2025-03-01",
  "expected_pay_period_cadence": "TaxYear",
  "default_employee_contributions_percent": 5,
  "default_employer_contributions_percent": 3,
  "contribution_basis": "QualifyingEarnings",
  "allows_salary_sacrifice": false,
  "payment_method": "DirectDebit",
  "number_of_employees": 50,
  "external_id": "org_01HXYZ"
}
Response examples (201)
{
  "id": "e1234-abcd-5678-efgh",
  "created_at": "2023-03-01T12:00:00Z",
  "updated_at": "2023-03-15T12:00:00Z",
  "name": "Acme Corp.",
  "contribution_basis": "QualifyingEarnings",
  "allows_salary_sacrifice": false,
  "external_reference": "ABC123",
  "company_number": "12345678",
  "payment_method": "DirectDebit",
  "primary_contact_email": "john.doe@example.com",
  "primary_contact_role": "HR",
  "default_employee_contributions_percent": 5,
  "default_employer_contributions_percent": 3,
  "aml_verification_status": "Pending",
  "status": "Active",
  "direct_debit_mandate_status": "PendingCustomerApproval"
}
Response examples (400)
{
  "error": "Bad request: invalid data provided.",
  "validation_errors": [
    {
      "field": "email",
      "message": "Email address is invalid."
    }
  ]
}
Response examples (401)
{
  "error": "Bad request: invalid data provided."
}
Response examples (403)
{
  "error": "Bad request: invalid data provided."
}
Response examples (404)
{
  "error": "Bad request: invalid data provided."
}
Response examples (405)
{
  "error": "Bad request: invalid data provided."
}
Response examples (409)
{
  "code": "EmployerAlreadyExists",
  "error": "employer already exists",
  "external_reference": "PEN12345678"
}
{
  "code": "ExternalIdAlreadyMapped",
  "error": "external_id already mapped to an employer",
  "external_id": "org_01HXYZ"
}
Response examples (500)
{
  "error": "Bad request: invalid data provided."
}