Integrations

Time & Attendance

Submit time punches and sync time data between Netchex and a third-party scheduling or T&A system.

This guide covers syncing time-and-attendance data in both directions: retrieving punches already recorded in Netchex, and submitting new punches and earnings.

A punch in this API is a single clock event, not an in/out pair. Each punch has one time and one type (In, Out, InLunch, OutLunch, InBreak, OutBreak, InPaidBreak, OutPaidBreak, InUnpaidBreak, OutUnpaidBreak). A shift is represented as several punches, not one record with both times on it.

Overview

Five endpoints power the T&A sync workflow:

  • GET /time-punches: retrieve punches within a date range (v3)
  • POST /api/TimePunches/byEmpCodeAndComboDept: submit a batch of punches by employee code, per-record error reporting (v1)
  • POST /api/TimePunches: submit a batch of punches by employee ID, all-or-nothing per company (v1)
  • POST /api/Timecard/earning: submit earnings for a timecard entry (v1)
  • GET /direct-entry-earnings: retrieve earnings already recorded (v3)

Step 1: Retrieve time punches

Request
GET https://external-api.netchexonline.net/time-punches?start-date=2024-01-01&end-date=2024-01-31&company-ids=101&page-size=250&api-version=3.0
Authorization: ApiKey YOUR_API_KEY

Key parameters:

ParameterTypeDescription
start-datedateRequired. Start of the punch date range
end-datedateRequired. End of the punch date range
organization-ids, company-ids, or employee-idsarrayExactly one of these three is required. Providing more than one, or none, returns 400
data-sourcestringOptional, filter by data source
project-ids, client-idsarrayOptional, further filter results
page-sizeintegerMax rows per page (1 to 250, default 50)
page-numberinteger1-based page number
Response (200)
{
  "pageNumber": 1,
  "pageSize": 250,
  "totalItemsCount": 1842,
  "items": [
    {
      "id": "98001",
      "employeeId": 5001,
      "companyId": 101,
      "time": "2024-01-15T08:02:00Z",
      "type": "In",
      "departmentId": 10,
      "projectId": null,
      "uniqueExternalId": null,
      "dataSource": "Swipe",
      "sequenceNumber": 1
    }
  ]
}

id is a string. Each punch is its own item with one time and one type.

Returns 404 if no records match the filters at all, distinct from an empty page. page-size maxes out at 250. Use pagination for date ranges spanning several weeks.

Step 2: Submit new time punches

If your source system stores employee codes rather than internal IDs, use this endpoint. It reports errors per punch instead of failing the whole batch:

Request
POST https://external-api.netchexonline.net/api/TimePunches/byEmpCodeAndComboDept?api-version=1.0
Authorization: ApiKey YOUR_API_KEY
Content-Type: application/json
Request body
[
  {
    "companyId": 101,
    "employeeCode": "EMP-1234",
    "comboDivBuDeptCode": "DIV-1/BU-1/DEPT-A",
    "time": "2024-01-22T08:00:00Z",
    "timeZoneOffset": -300,
    "type": "In"
  }
]

comboDivBuDeptCode is three codes joined with /: division, then business unit, then department, in that order.

If any punch fails, the response is 422 Unprocessable Entity with an error per failed punch, everything else in the batch is still saved:

Response (422, partial failure)
[
  { "companyId": 101, "employeeCode": "EMP-1234", "error": "Department `DIV-1/BU-1/DEPT-A` does not exist or you do not have access." }
]

Alternative: submit by employee ID

If you already have internal Netchex employee and department IDs, you can submit directly against them. The tradeoff: if any punch in the batch fails, nothing in that batch is saved for the affected company, validate on your side first.

Request
POST https://external-api.netchexonline.net/api/TimePunches?api-version=1.0
Authorization: ApiKey YOUR_API_KEY
Content-Type: application/json
Request body
[
  {
    "companyId": 101,
    "employeeId": 5001,
    "departmentId": 10,
    "time": "2024-01-22T08:00:00Z",
    "timeZoneOffset": -300,
    "type": "In"
  }
]

Step 3: Submit earnings for a timecard

Earnings attached to a timecard (regular hours, overtime, tips, and similar) use their own endpoint and their own set of codes, not IDs:

Request
POST https://external-api.netchexonline.net/api/Timecard/earning?api-version=1.0
Authorization: ApiKey YOUR_API_KEY
Content-Type: application/json

The path is /api/Timecard/earning, with a capital T and no versioned path segment.

Request body
[
  {
    "employeeCode": "EMP-1234",
    "companyId": 101,
    "companyCode": "ACME",
    "divisionCode": "DIV-1",
    "businessUnitCode": "BU-1",
    "departmentCode": "DEPT-A",
    "locationCode": "LOC-1",
    "userCode": "jsmith",
    "payCode": "REG",
    "units": 8.0,
    "date": "2024-01-22",
    "comments": "Regular shift",
    "clientCode": null,
    "projectCode": 0
  }
]

projectCode doesn't accept null, it's a plain integer. Send 0 (or omit the field) when there's no project to associate.

This endpoint identifies everything by code, not by internal ID, unlike the punch endpoints above. employeeCode here is the same code you'd use for byEmpCodeAndComboDept.

Step 4: Retrieve earnings

Request
GET https://external-api.netchexonline.net/direct-entry-earnings?start-date=2024-01-01&end-date=2024-01-31&company-ids=101&api-version=3.0
Authorization: ApiKey YOUR_API_KEY

Same filter rules as GET /time-punches: start-date and end-date are required, and exactly one of organization-ids, company-ids, or employee-ids is required.

Response (200)
{
  "pageNumber": 1,
  "pageSize": 50,
  "totalItemsCount": 1,
  "items": [
    {
      "directEntryEarningId": 55001,
      "employeeId": 5001,
      "companyEarningId": 1,
      "units": 8.0,
      "rate": 22.50,
      "grossAmount": 180.00,
      "date": "2024-01-22",
      "departmentId": 11,
      "projectId": null,
      "comment": "Regular shift",
      "uniqueExternalId": null,
      "dataSource": "Manual"
    }
  ]
}

rate on the response above shows you the rate that was actually applied.

Can an employee be paid a different rate depending on which department they work in? Yes, if department transfer is set up for your company. An employee working across multiple departments can be paid at each department's own rate rather than one fixed rate, departmentId on the earning is what determines which rate applies. Confirm with your Netchex representative whether department transfer is configured for you.

Coming soon: a v3 batch contract

The v1 endpoints above already batch (see "Step 2: Submit new time punches"). This section is about a separate, not-yet-published v3 batch contract — not available on this API today, described here so you know what's planned and can plan around it, or ask for early access.

Netchex's own internal sync pipeline submits punches and direct-entry earnings against a newer v3 batch endpoint, not the v1 ones documented above. We're extending that same v3 batch path to this API. The shape we expect to publish:

Punches — expected batch shape
{
  "items": [
    {
      "employeeId": "5001",
      "time": "2024-01-22T08:00:00Z",
      "departmentId": "10",
      "type": "In",
      "dataSource": "netchex:your-integration-name",
      "comment": "optional",
      "externalUniqueId": "optional, for idempotent retries"
    }
  ]
}
Direct-entry earnings — expected batch shape
{
  "items": [
    {
      "employeeId": "5001",
      "companyEarningId": 3,
      "units": 8.0,
      "date": "2024-01-22",
      "departmentId": "10",
      "dataSource": "netchex:your-integration-name",
      "transferCodeType": "optional",
      "uniqueExternalId": "optional, for idempotent retries"
    }
  ]
}

externalUniqueId/uniqueExternalId is the field we care about most for anything syncing on a schedule: it's what lets a re-run of the same batch (after a timeout, a retry, a redeploy) skip records it already submitted instead of double-posting them. If your integration needs this v3 contract sooner than it's publicly available, reach out to the Netchex Integrations team.

Try it in the playground

Test these endpoints interactively in the API reference:

On this page