Skip to main content
This guide will demonstrate the required interactions with the Nmbr API in order for employees to get paid reliably and on time.

Company Configuration

Create a company

The first action is to create a company, the overarching container that represents a single customer. Authentication Note You will use your partner_secret to create the top-level company. Once a company is created, future API calls should use the returned access_token to ensure interactions are always scoped to an individual company account. Company-level access_tokens are short-lived and will need to be refreshed before they expire. Read more about Authentication in API Reference. Request
  curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/companies \
     --header 'Authorization: Bearer <partner_secret>' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
         "name": "Bouchard Burger Inc."
     }'
Response
{
  "id": "01hhcy3fc40cp6yyv500re1041",
  "object": "company",
  "data": {
    "name": "Bouchard Burger Inc.",
    "pay_day_movement_setting": "inherit",
    "created_at": "2023-12-11T17:16:55.000000Z",
    "updated_at": "2023-12-11T17:16:55.000000Z",
    "token": {
      "access_token": "4nWkuMVylVeJMkOiFaPMzbQwdUklsP08sIqkBifve92a05c2",
      "expires_in": 59,
      "expires_at": "2023-12-11T18:16:55.000000Z"
    }
  },
  "links": {
    "self": "https://sandbox.nmbr.co/services/payroll/companies/01hhcy3fc40cp6yyv500re1041"
  }
}
You should store both the returned company ID as well as the token object for future interactions with the Nmbr API.
"token": {
    "access_token": "4nWkuMVylVeJMkOiFaPMzbQwdUklsP08sIqkBifve92a05c2",
    "expires_in": 59,
    "expires_at": "2023-12-11T18:16:55.000000Z"
}

Create a business entity

The next action is to create a business entity, the employer that is paying employees. Each business entity is a separate tax entity to tax agencies and has one Canadian payroll account and business number (BN). Use the customer scoped access_token for all requests related to this customer going forward. Request
curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/business_entities \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
        "business_number": "36774676RP0001",
        "name": "Bobs Burgers (#67667)",
        "legal_name": "8877362 Inc"
    }'
Response
{
    "id": "01hhcy3fpqkez7wjqzeaqetwfs",
    "object": "business_entity",
    "data": {
        "business_number": "36774676RP0001",
        "name": "Bobs Burgers (#67667)",
        "legal_name": "8877362 Inc",
        "address_line_1": "13 Fake Street",
        "address_line_2": null,
        "city": "Toronto",
        "province_code": "ON",
        "country_code": "CA",
        "postal_code": "M1M1M1",
        "contact_name": "kevin",
        "contact_area_code": "905",
        "contact_phone_number": "1112233",
        "contact_extension": null,
        "pay_day_movement_setting": "inherit",
        "onboarding_status": "incomplete",
        },
        "created_at": "2023-12-11T17:16:55.000000Z",
        "updated_at": "2023-12-11T17:16:55.000000Z"
    },
    "links": {
        "self": "https://sandbox.nmbr.co/services/payroll/business_entities/01hhcy3fpqkez7wjqzeaqetwfs"
    }
}
You should store at least the returned business entity ID for future interactions with the Nmbr API. Read more about Company Setup in Payroll Fundamentals.

Create a pay schedule

A payroll schedule determines the length of your pay period and how often you pay your employees. The most common payroll schedules are weekly, biweekly, semimonthly, and monthly. Request
curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/pay_schedules \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
         "title": "Salary Schedule",
         "pay_frequency": "semi-monthly",
         "anchor_pay_date": "2023-01-15T00:00:00.000000Z",
         "anchor_end_of_pay_period": "2023-01-15T00:00:00.000000Z",
         "day_1": 15,
         "day_2": -1,
         "business_entity_id": "{business_entity_id}"
     }'
Response
{
  "id": "01hhcy3ftxe4wrcsyzf7a3a46q",
  "object": "pay_schedule",
  "data": {
    "name": "Salary Schedule",
    "pay_frequency": "semi-monthly",
    "anchor_pay_date": "2023-01-15T00:00:00.000000Z",
    "anchor_end_of_pay_period": "2023-01-15T00:00:00.000000Z",
    "day_1": 15,
    "day_2": -1,
    "pay_day_movement_setting": "inherit",
    "created_at": "2023-12-11T17:16:56.000000Z",
    "updated_at": "2023-12-11T17:16:56.000000Z"
  },
  "links": {
    "self": "https://sandbox.nmbr.co/services/payroll/pay_schedules/01hhcy3ftxe4wrcsyzf7a3a46q"
  }
}
You should store at least the returned pay schedule ID for future interactions with the Nmbr API. Read more about Managing Pay Schedules in Payroll Fundamentals.

Employee Configuration

Create an employee

Creating an employee is very similar to creating a business entity. You will make an API request to create an employee entity in the payroll system. Request
curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/employees \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
        "employee_number": "69878",
        "first_name": "Kendall",
        "last_name": "Hintz",
        "middle_initial": null,
        "address_line_1": "Spencer Meadows",
        "address_line_2": null,
        "city": "Toronto",
        "province_code": "on",
        "country_code": "CA",
        "postal_code": "M1M1M1",
        "sin": 366371964
    }'
Response
{
  "id": "01hhcy3hg60x3dq8hfj31hgyea",
  "object": "employee",
  "data": {
    "employee_number": "69878",
    "first_name": "Kendall",
    "last_name": "Hintz",
    "middle_initial": null,
    "address_line_1": "Spencer Meadows",
    "address_line_2": null,
    "city": "Toronto",
    "province_code": "ON",
    "country_code": "CA",
    "postal_code": "M1M1M1",
    "sin": 366371964,
    "is_archived": false,
    "created_at": "2023-12-11T17:16:57.000000Z",
    "updated_at": "2023-12-11T17:16:57.000000Z"
  },
  "links": {
    "self": "https://sandbox.nmbr.co/services/payroll/employees/01hhcy3hg60x3dq8hfj31hgyea"
  }
}
You should store at least the returned employee ID for future interactions with the Nmbr API. Read more about Adding Employees in Payroll Fundamentals.

Create Work Assignment

You will be required to tie an employee and pay schedules together to ensure accurate payroll statutory withholdings. A Work Assignment can be created by providing the appropriate IDs to the Work Assignments endpoint. Request
curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/work_assignments \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
        "employee_id": "{employee_id}",
        "pay_schedule_id": "{pay_schedule_id}"
    }'
Response
{
  "id": "01hhcy3hmeajydc6cpa1k5s5kr",
  "object": "work_assignment",
  "data": {
    "created_at": "2023-12-11T17:16:58.000000Z",
    "updated_at": "2023-12-11T17:16:58.000000Z"
  },
  "links": {
    "self": "https://sandbox.nmbr.co/services/payroll/work_assignments/01hhcy3hmeajydc6cpa1k5s5kr"
  }
}
Creating a work assignment linked to a pay schedule will generate the upcoming pay stubs for each pay period in the system. Read more about Work Assignments in Payroll Fundamentals.

Setup pay rates

Paying out earnings to employees is one of the primary functions of payroll software. Depending on the province or territory of employment, different labour laws apply relating to minimum wage and vacation earnings. You can create a Pay Rate for an employee using the pay_rate endpoint: Request
curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/pay_rates \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
        "work_assignment_id": "{work_assignment_id}",
        "title": "Location Manager",
        "type": "salary",
        "rate": "60000",
        "expected_hours_per_week": "38",
        "effective_from": "2023-11-01T00:00:00.000000Z"
    }'
Response
{
  "id": "01hhcy3j61408834dmfe8bzg24",
  "object": "pay_rate",
  "data": {
    "title": "Location Manager",
    "type": "salary",
    "rate": "60000",
    "expected_hours_per_week": "38.00",
    "effective_from": "2023-11-01T00:00:00.000000Z",
    "effective_to": null,
    "created_at": "2023-12-11T17:16:58.000000Z",
    "updated_at": "2023-12-11T17:16:58.000000Z"
  },
  "links": {
    "self": "https://sandbox.nmbr.co/services/payroll/pay_rates/01hhcy3j61408834dmfe8bzg24"
  }
}
Read more about Setup Pay Rates in Payroll Fundamentals.

Payroll Configuration

Retrieve payroll information

When a payroll is first created, it will be in the draft status. You can retrieve draft payrolls and display totals for the end user. First, retrieve a list of all payrolls, then retrieve the individual payroll that you would like to review, change, or approve. Request
curl --request GET \
     --url 'https://sandbox.nmbr.co/services/payroll/payrolls?business_entity_id={business_entity_id}' \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json'

curl --request GET \
     --url https://sandbox.nmbr.co/services/payroll/payrolls/{payroll_id} \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json'
Response
{
  "id": "01hfvzcp9c5phwfjkcra40rsg4",
  "object": "payroll",
  "data": {
    "type": "regular",
    "period_start": "2023-01-01T00:00:00.000000Z",
    "period_end": "2023-01-15T00:00:00.000000Z",
    "pay_date": "2023-01-13T00:00:00.000000Z",
    "employee_summary": {
      "gross": "1161.54",
      "deductions": null,
      "reimbursements": null,
      "net": "712.31"
    },
    "contractor_summary": {
      "gross": "100.00",
      "reimbursements": "15.00",
      "net": "115.00"
    },
    "company_summary": {
      "taxes_and_contributions": "73.56",
      "benefits": "50.00",
      "total": "123.56"
    },
    "liability": "1150.10",
    "cash_requirement": "1150.10",
    "status": "draft",
    "approved_at": null,
    "created_at": "2023-11-22T16:56:38.000000Z",
    "updated_at": "2023-11-22T16:56:38.000000Z"
  },
  "links": {
    "self": "https://sandbox.nmbr.co/services/payroll/payrolls/01hfvzcp9c5phwfjkcra40rsg4"
  }
}
Read more about Payroll Lifecycle in Payroll Fundamentals.

Retrieve an employee’s earnings & deductions

In order to make adjustments to individual employee’s earnings and deductions, you will need to retrieve the corresponding pay stub. Payments to employees can be added and removed, earnings and hours worked can be modified on individual payroll items, etc. You can retrieve a payroll and include all corresponding pay stubs using the ?expands=[] functionality. Read more about working with related resources in the API Reference. Request
curl --request GET \
     --url 'https://sandbox.nmbr.co/services/payroll/payrolls/{payroll_id}?expand[]=pay_stubs' \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json'

curl --request GET \
     --url 'https://sandbox.nmbr.co/services/payroll/pay_stubs/{pay_stub_id}?expand[]=earning_line_items' \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json'
Response
{
  "id": "01hfwg2784vc1408yhmjp4x81q",
  "object": "pay_stub",
  "data": {
    "has_taxes_calculated": true,
    "employee_summary": {
      "gross": "2520",
      "deductions": "714.91",
      "reimbursements": "10",
      "net": "1815.09"
    },
    "contractor_summary": {
      "gross": null,
      "reimbursements": null,
      "net": null
    },
    "company_summary": {
      "taxes_and_contributions": "500",
      "benefits": "50",
      "total": "550"
    },
    "earning_line_items": {
      "object": "list",
      "data": [
        {
          "id": "01hfwg27gtha4m82def3y3spz4",
          "object": "earning_line_item",
          "data": {
            "amount": 2500,
            "line_item_type": "earning",
            "earning": {
              "earning_type": "salary",
              "hours": null,
              "accrued_vacation_pay": null
            },
            "created_at": "2023-11-22T21:48:01.000000Z",
            "updated_at": "2023-11-22T21:48:01.000000Z"
          }
        }
      ]
    },
    "statutory_withholding_line_items": {
      "object": "list",
      "data": [
        {
          "id": "01hfye1vw8wqg7a4x4nwrfmt17",
          "object": "statutory_withholding_line_item",
          "data": {
            "line_item_type": "statutory_withholding",
            "amount": 134.6,
            "statutory_withholding": {
              "statutory_withholding_type": "provincial_income_tax",
              "hours": null
            },
            "created_at": "2023-11-23T15:51:21.000000Z",
            "updated_at": "2023-11-23T15:51:21.000000Z"
          }
        }
      ]
    },
    "allowance_line_items": {
      "object": "list",
      "data": [
        {
          "id": "01hfycrt5cr7vajwaej1yre9q5",
          "object": "allowance_line_item",
          "data": {
            "line_item_type": "allowance",
            "amount": 10,
            "allowance": {
              "allowance_type": "automobile_and_motor_vehicle",
              "recurring_allowance": null
            },
            "created_at": "2023-11-23T15:28:56.000000Z",
            "updated_at": "2023-11-23T15:28:56.000000Z"
          }
        }
      ]
    },
    "reimbursement_line_items": {
      "object": "list",
      "data": [
        {
          "id": "01hfycs5ze4hs2c5erjb6jx4kn",
          "object": "reimbursement_line_item",
          "data": {
            "line_item_type": "reimbursement",
            "amount": 10,
            "reimbursement": {
              "reimbursement_type": "non_taxable_reimbursement",
              "recurring_reimbursement": null
            },
            "created_at": "2023-11-23T15:29:08.000000Z",
            "updated_at": "2023-11-23T15:29:08.000000Z"
          }
        }
      ]
    },
    "benefit_line_items": {
      "object": "list",
      "data": [
        {
          "id": "01hfycn0yy7gs7s5ek2k6j854w",
          "object": "benefit_line_item",
          "data": {
            "line_item_type": "benefit",
            "amount": 30,
            "benefit": {
              "employee_benefit": null,
              "benefit_type": "dental",
              "company_contribution_amount": 10,
              "employee_contribution_amount": 30
            },
            "created_at": "2023-11-23T15:26:52.000000Z",
            "updated_at": "2023-11-23T15:26:52.000000Z"
          }
        }
      ]
    },
    "deduction_line_items": {
      "object": "list",
      "data": [
        {
          "id": "01hfycw58xh8pp8j9agw63esgv",
          "object": "deduction_line_item",
          "data": {
            "line_item_type": "deduction",
            "amount": 10,
            "deduction": {
              "deduction_type": "income_tax",
              "recurrence": null
            },
            "created_at": "2023-11-23T15:30:46.000000Z",
            "updated_at": "2023-11-23T15:30:46.000000Z"
          }
        }
      ]
    },
    "created_at": "2023-11-22T21:48:01.000000Z",
    "updated_at": "2023-11-23T15:51:21.000000Z"
  },
  "links": {
    "self": "https://sandbox.nmbr.co/services/payroll/pay_stubs/01hfwg2784vc1408yhmjp4x81q"
  }
}
You can update an individual payroll line item using the API. The example below could be used to enter 10 hours for the given pay rate. Request
curl --request PUT \
     --url https://sandbox.nmbr.co/services/payroll/earnings/{earning_id} \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
                "hours": 10,
            }'
Read more about Additional Line Items in Payroll Fundamentals. You will notice changes to earnings automatically update related statutory withholdings and tax calculations. You can leverage webhooks to show payroll calculation changes to your users. Read more about Webhooks in the API Reference.

Approve payroll

When a payroll is approved (via the /payrolls/<payroll_id>/ approve endpoint), its status changes to approved. Once approved, the payroll can no longer be modified. This is because the taxes, net pay, and benefits have been calculated and saved for the payroll. Request
curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/payrolls/{payroll_id}/approve \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json'
At the end of each business day at 5pm PT, our system collects all pending payrolls that have an approval deadline on that day and begins the multi-step process of moving money through the banking system to pay them out. Read more about the Payroll Life Cycle in Payroll Fundamentals.

Generate pay stubs

Nmbr also provides the ability to generate pay stubs for employees both as a rendered PDF and as a JSON object. Because CRA regulations generally require that all information in the pay stub JSON response be rendered and the pay stub be printable, Nmbr recommends directly rendering a singular pay stub to PDF to satisfy this requirement. To return a pay stub as a JSON response, make a GET call to the /pay_stubs endpoint:
curl --request GET \
     --url https://sandbox.nmbr.co/services/payroll/pay_stubs/{pay_stub_id} \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/json'
To return a pay stub as a PDF response, make a GET call to the /pay_stubs/{pay_stub_id}/render endpoint:
curl --request GET \
     --url https://sandbox.nmbr.co/services/payroll/pay_stubs/{pay_stub_id}/render \
     --header 'Authorization: Bearer <access_token>' \
     --header 'accept: application/pdf'
Draft pay stub PDFs will be rendered with a “DRAFT” watermark.

What’s Next

As a next step we suggest browsing our API Reference.