Business Days Field
The businessDays(path) field is available on both Order and TrackingEvent GraphQL types. It calculates how many business days separate a date field on the parent object from today, using the organization's configured business calendar.
Overview
- Returns:
Int— signed count of business days (positive = date is in the past, negative = date is in the future, zero = today) - Calendar source: The organization's business calendar, including weekly schedule and availability blocks
- Timezone: All calculations are performed in the organization's configured timezone
- Null safety: Returns
nullif the field is not found, cannot be parsed as a date, or the organization has no business calendar configured
Field Signature
Available on both Order and TrackingEvent:
businessDays(path: String!, contactId: Int): Int
Argument
| Argument | Type | Required | Description |
|---|---|---|---|
path | String | Yes | Dot-notation path to a date field on the parent object (e.g., "eta", "customValues.pickupDate") |
contactId | Int | No | Optional contact scope for availability blocks. When provided, only org-wide blocks plus blocks for that contact are used. |
How It Works
- The resolver reads the field value at
pathfrom the parent object using reflection - The value is coerced to a
DateTime— supportsDateTime,DateTimeOffset,DateOnly, or any parseable date string - The organization's business calendar is loaded (cached within the request via DataLoader)
- Availability blocks are optionally filtered by
contactId: org-wide blocks plus blocks matching that contact are used - Business days are counted between the resolved date and today (organization's local date), excluding the start date and including the end date
- The result is signed: positive when the date is in the past, negative when it is in the future
Business Day Definition
A calendar day counts as a business day if, after combining the weekly schedule with availability blocks, at least one time window remains available on that date:
- Weekly schedule: Defines standard business hours per day of week
IsAvailable=trueblocks: Add extra availability windows (e.g., holiday coverage)IsAvailable=falseblocks: Remove windows (e.g., public holidays, closures)
Usage Examples
Business days since an order's ETA
query {
order(organizationId: 1, orderId: 123) {
orderId
eta
businessDaysSinceEta: businessDays(path: "eta")
}
}
Response:
{
"data": {
"order": {
"orderId": 123,
"eta": "2026-04-10T00:00:00Z",
"businessDaysSinceEta": 8
}
}
}
Multiple business day fields in one query
You can request businessDays for several different date fields simultaneously using aliases:
query {
order(organizationId: 1, orderId: 123) {
orderId
bdaysFromCreated: businessDays(path: "created")
bdaysFromEta: businessDays(path: "eta")
bdaysFromPickup: businessDays(path: "customValues.pickupDate")
}
}
Business days on a tracking event
The businessDays field is also available on TrackingEvent, where path is resolved relative to the tracking event — not the order:
query {
order(organizationId: 1, orderId: 123) {
orderId
lastDeliveryAttempt: lastTrackingEvent(eventDefinitionName: "DeliveryAttempt") {
trackingEventId
eventDate
bdaysSinceAttempt: businessDays(path: "eventDate")
}
}
}
Response:
{
"data": {
"order": {
"orderId": 123,
"lastDeliveryAttempt": {
"trackingEventId": 456,
"eventDate": "2026-04-15T09:30:00Z",
"bdaysSinceAttempt": 5
}
}
}
}
Contact-scoped carrier availability
Pass contactId when the business-day count should honor availability exceptions for a carrier, customer, or other contact. This keeps org-wide closures while adding contact-specific blocks.
query {
order(organizationId: 1, orderId: 123) {
eta
carrierBusinessDays: businessDays(path: "eta", contactId: 456)
}
}
For commodity grids, the backend also exposes a scalar helper on Commodity so each row can resolve its carrier from row custom values without a per-row client argument:
query {
commodities(organizationId: 1) {
items {
commodityId
customValues
lastFreeDays: lastTrackingEventBusinessDays(
path: "eventDate"
eventDefinitionName: "Yard Scan"
orderBy: "eventDate"
contactIdPropertyName: "carrierId"
)
}
}
}
contactIdPropertyName names the custom value key on the commodity row (for carrier use cases, usually carrierId).
Null Return Cases
businessDays returns null when:
| Condition | Reason |
|---|---|
path does not exist on the parent object | Field not found |
Field value is null | No date to measure from |
| Field value cannot be parsed as a date | Unsupported format |
| No business calendar is configured for the organization | Calendar lookup returned null |
Performance Note
The business calendar is loaded via a batched DataLoader scoped to the GraphQL request. Requesting businessDays on many orders or tracking events in a single query results in at most one calendar lookup per organization, regardless of result set size. Contact-scoped filtering is in-memory against the already-loaded calendar blocks; it does not add per-row SQL queries.