Quickstart

Securely and reliably integrate payroll into your product.

This guide will demonstrate how to create Companies, Workplaces, Employees, and Payrolls, which are the required steps for employees to get paid reliably and on time.

As of API version 2025-01-01, Check supports processing payrolls with up to 1,500 payroll items or 1,500 contractor payments by previewing payrolls asynchronously. Payrolls with up to 500 payroll items or 500 contractor payments can still be processed synchronously.

💭

Should you build against synchronous or asynchronous payroll preview?

The answer to this question depends on the size of employers that you expect to support now and into the future.

If you expect to never exceed 500 payroll items or 500 contractor payments on a given payroll, then the synchronous preview path offers a more straightforward path to processing payrolls for your customers.

However, if you think it's a possibility that you will support employers with more than 500 payroll items or 500 contractor payments on a given payroll in the future, then we recommend integrating with the asynchronous API from the outset. This will ensure that you are ready for scale, and you will not need to change your integration when you have a large employer attempt to process payroll in the future.

The variations for sync vs async processing will become apparent from step 5 in this guide.

Set up a test environment (Postman)

To make it easy to follow along we've created this Postman collection.

Run in Postman

To use the collection, click "Run in Postman" above to download it to your local machine.

Next select the "Check" environment and set the Current Value for the apiKey variable to your personal Check api key. If there is no "Check" environment present, a new one will need to be created following these steps Postman - Create Environment. Name this environment "Check", and create two variables in this environment: 'apiUrl' with a "Current Value" of "https://sandbox.checkhq.com" and 'apiKey' with a value of your personal Check api key.

1. Create a company

The first action is to create a company, the employer that is paying employees. Each company is a separate tax entity to tax agencies and has one federal Employer Identification Number (EIN).

curl -X POST \
  https://sandbox.checkhq.com/companies \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>' \
  -d '{
    "address": {
      "line1": "20 W 34th St",
      "postal_code": "10001",
      "city": "New York",
      "state": "NY"
    },
    "start_date": "2020-05-20",
    "trade_name": "Good Web Design",
    "legal_name": "Good Web Design, Inc."
  }'

You should store at least the returned company ID for future interactions with the Check API.

2. Create a workplace

In order to properly calculate taxes for an employee, Check needs to know the physical location where they do their work. Let's create some workplaces associated with our new company where we can assign those employees.

curl -X POST \
  https://sandbox.checkhq.com/workplaces \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>' \
  -d '{
    "company": "<COMPANY_ID>",
    "address": {
      "line1": "175 Varick St",
      "line2": "2nd Floor",
      "postal_code": "10014",
      "city": "New York",
      "state": "NY"
    }
  }'

You should store at least the returned workplace ID for future interactions with the Check API.

3. Create a company bank account

For a company to run payroll through Check, a business bank account from which the payroll will be funded needs to be linked. We will create employees next, but first, let's create a bank account associated with our new company that we can use to fund payroll.

curl -X POST \
  https://sandbox.checkhq.com/bank_accounts \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>' \
  -d '{
    "company": "<COMPANY_ID>",
    "raw_bank_account": {
      "account_number": "123456789",
      "routing_number": "026009593",
      "type": "depository",
      "subtype": "checking"
    }
  }'

4. Create employees

Creating an employee is very similar to creating a company. You will make an API request to create an employee entity in Check's systems.

curl -X POST \
  https://sandbox.checkhq.com/employees \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>' \
  -d '{
    "first_name": "Bob",
    "last_name": "Smith",
    "company": "<COMPANY_ID>",
    "workplaces": ["<WORKPLACE_ID>"],
    "start_date": "2019-03-01",
    "dob": "1975-11-28",
    "residence": {
      "line1": "123 Main St.",
      "postal_code": "11201",
      "city": "Brooklyn",
      "state": "NY",
      "country": "US"
    }
  }'

You should store at least the returned employee ID for future interactions with the Check API.

5a. Create a payroll with payroll items included

You can now create a payroll. The payroll object defines a pay period, which is the timespan in which wages were earned, and a payday, which is the date on which the payment for those wages will be made.

Example Request to Create a Payroll:

curl -X POST \
  https://sandbox.checkhq.com/payrolls \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>' \
  -d '{
    "company": "<COMPANY_ID>",
    "period_start": "<YYYY-MM-DD>",
    "period_end": "<YYYY-MM-DD>",
    "payday": "<YYYY-MM-DD, non-bank holiday weekday>",
      }'

You can create the payroll items and contractor payments in the same request as the one where you create the payroll, by using the optional include_items and include_contractor_payments flags. These flags can only be set to true if the payroll has 500 or fewer payroll items and 500 or fewer contractor payments.

curl -X POST \
  'https://sandbox.checkhq.com/payrolls?include_items=true&include_contractor_payments=true' \
  -H 'Authorization: Bearer <API_KEY>'
  -d '{
    "id": "pay_bQbbxLQeghmGG7W5HxeY",
    "company": "com_dFmjg0e9SqJZb9WYEyag",
    "period_start": "2019-06-16",
    "period_end": "2025-11-14",
    "approval_deadline": "2025-11-29T01:00:00Z",
    "reopen_deadline": null,
    "approved_at": null,
    "payday": "2025-11-28",
    "status": "draft",
    "managed": true,
    "type": "regular",
    "pay_frequency": "biweekly",
    "pay_schedule": null,
    "funding_payment_method": "ach",
    "processing_period": "three_day",
    "off_cycle_options": null,
    "totals": null,
    "items": [
        {
            "id": "itm_PlLfuNmPzd9NmR5ENQK2",
            "payroll": "pay_bQbbxLQeghmGG7W5HxeY",
            "employee": "emp_TB70nh2y9OZh8tGm9hP0",
            "status": "draft",
            "void_of": null,
            "voided_by": null,
            "payment_method": "manual",
            "supplemental_tax_calc_method": "aggregate",
            "pto_balance_hours": null,
            "sick_balance_hours": null,
            "state_covid_sick_balance_hours": null,
            "net_pay": null,
            "net_pay_split": null,
            "earnings": [
                {
                    "amount": "5384.61",
                    "piece_units": null,
                    "hours": 40.0,
                    "type": "regular",
                    "code": null,
                    "description": null,
                    "earning_code": null,
                    "earning_rate": null,
                    "workplace": "wrk_Vt1s0wIPTpEbolesJwzj",
                    "tip_credit_amount": null,
                    "metadata": {}
                }
            ],
            "reimbursements": [],
            "taxes": null,
            "benefits": null,
            "benefit_overrides": [],
            "post_tax_deductions": null,
            "post_tax_deduction_overrides": [],
            "warnings": null,
            "paper_check_number": null,
            "paystub_info": {},
            "metadata": {}
        }
    ],
    "contractor_payments": [],
    "is_void": false,
    "metadata": {},
    "warnings": [],
    "bank_account": "bnk_fpwKprUwnYj9lAbG5KNh",
    "simulation_mode": "automatic",
    "preview": null
}

If you have more than 500 items in your payroll, you will need to create additional payroll items as laid out in step 5c.

5b. Create additional employees for payroll item

This is an optional step to follow if you would like to add additional employees to payroll items. To create a new employee, refer to step 4.

5c. Add employee to payroll item

Payroll items represent the various earning amounts, hours, and workplaces for each employee during the pay period of the payroll. You can now proceed to add the new employee in step 5b to a payroll item.

Bulk Requests:

You can create payroll items in bulk by making a POST request to the /payroll_items endpoint with an array of payroll item objects, and similarly for /contractor_payments. Additionally, using this endpoint to PATCHwill prevent recreating a whole payroll when you only want to update one item.

Example Request to Create Payroll Items:

curl -X POST \
  'https://sandbox.checkhq.com/payroll_items' \
  -H 'Authorization: Bearer <API_KEY>'
  -d '{
      "payroll": "pay_1234567890abcdef",
      "employee": "emp_1234567890abcdeg",
      "earnings": [
        {
          "type": "hourly",
          "workplace": "wrk_1234567890abcdef",
          "amount": "390.00",
          "hours": 40
        }
      ],
      "reimbursements": [
        {
          "amount": "50.00",
          "description": "Travel expenses"
        }
      ]
    },
    {
      "payroll": "pay_1234567890abcdef",
      "employee": "emp_1234567890abcdeg",
      "earnings": [
        {
          "type": "salary",
          "workplace": "wrk_0987654321fedcba",
          "amount": "1500.00"
        }
      ]
    }
  ]'

5d. Create a contractor for payroll item

If you need to pay a contractor, you can create one here.

curl -X POST \
  'https://sandbox.checkhq.com/payrolls/contractors' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>'
  -d '{
    "id": "ctr_l4uXhJTcQvPiWorVAtca",
    "type": "individual",
    "company": "com_Y6FUq2d9pYOtqfae1aP2",
    "workplaces": [
        "wrk_gXfqxWUV12fE7xP6AVXQ"
    ],
    "primary_workplace": "wrk_gXfqxWUV12fE7xP6AVXQ",
    "first_name": "Steve",
    "middle_name": null,
    "last_name": "Rogers",
    "business_name": null,
    "dob": "1970-05-29",
    "start_date": "2019-03-01",
    "termination_date": null,
    "email": null,
    "bank_accounts": [],
    "ssn_last_four": null,
    "ssn_validation_status": null,
    "payment_method_preference": null,
    "default_net_pay_split": null,
    "onboard": {
        "status": "blocking",
        "blocking_steps": [
            "address"
        ],
        "remaining_steps": [
            "ssn",
            "address",
            "payment_method"
        ],
        "ssn": [
            "ssn_submitted",
            "ssn_validated"
        ],
        "payment_method": [
            "payment_method_preference_set",
            "bank_account_exists",
            "bank_account_verified"
        ],
        "address": [
            "address_submitted"
        ]
    },
    "ein": null,
    "address": {
        "line1": null,
        "line2": null,
        "city": null,
        "state": null,
        "postal_code": null,
        "country": "US"
    },
    "metadata": {},
    "1099_nec_electronic_consent_provided": false
}

5e. Add contractors to payroll items

Contractor payments represent payments made to contractors. Now that a contractor has been created, you can add the contractor payment item to an existing {{payrollId}}.

Example Request to Create Contractor Payments:

curl -X POST \
  'https://sandbox.checkhq.com/payrolls/contractor_payments' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>'
  -d '{
      "payroll": "pay_1234567890abcdef",
      "contractor": "ctr_XyZ1234567890abc",
      "payment_method": "manual",
      "amount": "500.00",
      "reimbursement_amount": "75.00"
    }
  ]'

6. Preview payroll

You can preview payrolls first and then show the tax calculations to the company for approval. For payrolls paid via direct deposit, Check ensures that the payday is far enough in the future to allow for all fund movement to complete. For this example, you should set the payday to a date returned by the /paydays endpoint. See the endpoint documentation for more details on what constitutes a valid direct deposit payday.

The preview will calculate net amounts and withholdings for all pay using the gross pay and laws applicable on payday. This calculation takes some time and is ephemeral.

By default, previewing a payroll is a synchronous operation. Synchronous previews are limited to payrolls with 500 or fewer payroll items and contractor payments. If you wish to see the calculated payroll items and contractor payments as part of the response to the preview request, you can do so by setting the include_items and include_contractor_payments flags to true.

Example Synchronous Preview Payroll Request:

curl -X GET \
  'https://sandbox.checkhq.com/payrolls/<PAYROLL_ID>/preview?include_items=true?include_contractor_payments=true' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>'

If you have more than 500 payroll items and contractor payments, you will need to preview your payroll asynchronously. This behavior is controlled using the async=true flag. When set, this flag will direct Check to process the preview request in the background, and then update the payroll object once the calculation is completed. You will see this when the payroll's preview.status is set to  succeeded.

Example Asynchronous Preview Payroll Request:

curl -X GET \
  'https://sandbox.checkhq.com/payrolls/<PAYROLL_ID>/preview?async=true' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>'
  -d '{
    "id": "pay_bQbbxLQeghmGG7W5HxeY",
    "company": "com_dFmjg0e9SqJZb9WYEyag",
    "period_start": "2019-06-16",
    "period_end": "2025-11-14",
    "approval_deadline": "2025-11-29T01:00:00Z",
    "reopen_deadline": null,
    "approved_at": null,
    "payday": "2025-11-28",
    "status": "draft",
    "managed": true,
    "type": "regular",
    "pay_frequency": "biweekly",
    "pay_schedule": null,
    "funding_payment_method": "ach",
    "processing_period": "three_day",
    "off_cycle_options": null,
    "is_void": false,
    "totals": null,
    "metadata": {},
    "warnings": [],
    "bank_account": "bnk_fpwKprUwnYj9lAbG5KNh",
    "simulation_mode": "automatic",
    "preview": {
        "messages": null,
        "status": "calculating",
        "started_at": "2025-11-18T02:41:08.194789Z"
    }
}

For more information on asynchronous payroll processing, refer to the guide here: Check API Payroll Preview and Approval.

7. Approve payroll

Once a company has previewed its payroll, it can approve the payroll. No further updates to payroll items are allowed after payroll has been approved.

curl -X POST \
  'https://sandbox.checkhq.com/payrolls/<PAYROLL_ID>/approve' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <API_KEY>'

8. Simulate payment processing

In sandbox, there are two options for testing payments flows:

  • Automatic simulation
  • Manual simulation

To switch between these two modes, set the simulation_mode property on the Payroll object to automatic or manual. By default, payrolls will automatically transition to the next phase of payroll processing (i.e., from pending to processing, and from processing to paid) every 5 minutes. To start the process, you just need to create and approve a payroll.

If thesimulation_mode is changed to manual, you can test payments processing with a set of endpoints on the Payroll API. These endpoints allow you to manually trigger the completion or failure of the payroll debit, and the completion of employee direct deposit disbursements.

For more detail, visit the guide here: Check API Testing Payments in Sandbox.

9. Generate paystubs

Check also generates paystubs for employees both as a rendered PDF and as a JSON object. Because state regulations generally require that all information in the paystub JSON response be rendered and the paystub be printable, Check recommends directly rendering a singular paystub to PDF to satisfy this requirement.

For more information, see Generating Paystubs in the Check Guides.

To return a Check-designed paystub as a PDF, make a GET call to the /paystubs endpoint with the HTTP header Accept: application/pdf. Check will return a fully rendered paystub for the employee:

GET /employees/<employee_id>/paystubs/<payroll_id>

What's Next

If you've made it this far you are well on your way to incorporating payroll into your product. As a next step we suggest browsing our API Reference. Still have questions? Feel free to shoot us an email.