-
-
Notifications
You must be signed in to change notification settings - Fork 0
Closing Days
Manage company-wide closing days in Teamleader Focus.
The Closing Days resource lets you create and delete dates on which your company is closed. Closing days affect scheduling, user availability calculations, and planning across the account.
update() and info() are not supported β there are no API endpoints for them.
Access via Teamleader::closingDays().
You write
dayand read backdate.closingDays.addtakes adayfield;closingDays.listreturns each record withidanddate. See Response Structure.This resource returns pagination metadata. It is one of the few that does β since v2.2.0 it sends
includes=paginationon every list call, someta.matchesgives you a real total count.Unknown filter keys and sort options throw since v2.2.1. This endpoint has exactly two filters and no sorting at all.
closingDays
| Capability | Supported |
|---|---|
| Pagination | β Supported, with metadata |
| Filtering | β
Supported (date_after, date_before) |
| Sorting | β Not supported |
| Sideloading | β Not supported |
| Creation | β Supported |
| Update | β Not supported |
| Deletion | β Supported |
Note on the API endpoint:
create()posts toclosingDays.addinternally, notclosingDays.create. The SDK handles this transparently.
Returns closing days, optionally filtered by date range. Both filter values are validated as YYYY-MM-DD before the request is sent.
use McoreServices\TeamleaderSDK\Facades\Teamleader;
// All closing days
$closingDays = Teamleader::closingDays()->list();
// Within a date range
$closingDays = Teamleader::closingDays()->list([
'date_after' => '2025-01-01',
'date_before' => '2025-12-31',
]);
// With pagination
$closingDays = Teamleader::closingDays()->list([], [
'page_size' => 50,
'page_number' => 1,
]);Unknown filter keys and sort options throw before the request is sent:
Teamleader::closingDays()->list(['date' => '2025-12-25']);
// InvalidArgumentException: Unsupported filter key for closingDays.list: date.
// Supported: date_before, date_after.
Teamleader::closingDays()->list([], ['sort' => 'date']);
// InvalidArgumentException: closingDays.list does not support sorting.
// Passed: sort. Records come back in the order the API chooses.Pagination metadata is always requested. Before v2.2.0 the SDK sent the parameter as include (singular) and only when an include_pagination option was passed. The API silently ignores the singular form, so the metadata never arrived β the same defect fixed SDK-wide in v1.2.3. It is now sent as includes on every call, unconditionally. The include_pagination option is redundant but harmless.
Adds a closing day. The day field must be a valid date in YYYY-MM-DD format β validated before the request is sent.
Teamleader::closingDays()->create(['day' => '2025-12-25']);Alias for create(['day' => $day]). Accepts the date string directly.
Teamleader::closingDays()->add('2025-12-25');Removes a closing day by UUID. Throws if $id is empty.
Teamleader::closingDays()->delete('closing-day-uuid');Each of these makes its own API call.
Returns closing days for a specific month. Validates the YYYY-MM format.
$closingDays = Teamleader::closingDays()->forMonth('2025-12');
$closingDays = Teamleader::closingDays()->forMonth(date('Y-m'));Returns closing days for a full year. Year must be between 1900 and 2100.
$closingDays = Teamleader::closingDays()->forYear(2025);
$closingDays = Teamleader::closingDays()->forYear(date('Y'));Returns closing days between two dates (inclusive). Both dates are validated; start must not be after end.
$closingDays = Teamleader::closingDays()->forDateRange('2025-12-20', '2025-12-31');Returns closing days from today up to $daysAhead days in the future.
$closingDays = Teamleader::closingDays()->upcoming(); // next 30 days
$closingDays = Teamleader::closingDays()->upcoming(90); // next 90 daysReturns true if the given date is registered as a closing day. Makes one API call, so avoid it in a loop β fetch the year once and check against the result instead.
if (Teamleader::closingDays()->isClosingDay('2025-12-25')) {
// Office is closed
}Adds multiple closing days in a loop. Each date is passed through add(). Failures are caught and returned as error objects in the results array β they do not throw.
$results = Teamleader::closingDays()->bulkAdd([
'2025-01-01',
'2025-04-21',
'2025-12-25',
'2025-12-26',
]);
// Each entry is either a success response or:
// ['error' => true, 'date' => '2025-12-25', 'message' => '...']One API request per date. Adding a year of public holidays costs a dozen or so requests against your rate limit budget.
Returns an array of common holiday dates for a year β no API call. Useful for seeding bulkAdd().
$holidays = Teamleader::closingDays()->getCommonHolidays(2025);
// ['New Year\'s Day' => '2025-01-01', 'Christmas Day' => '2025-12-25',
// 'Boxing Day' => '2025-12-26', 'Easter Monday' => '2025-04-21']Three caveats worth knowing before you rely on this:
- It covers four dates only β New Year's Day, Christmas Day, Boxing Day and Easter Monday. It is a starting point, not a Belgian public holiday calendar. Ascension, Whit Monday, Labour Day, the National Holiday, Assumption, All Saints' Day and Armistice Day are all absent.
-
The
$countryparameter is accepted but ignored. The dates are hard-coded for Belgium regardless of what you pass. -
Easter Monday needs the
calendarPHP extension. It is derived fromeaster_date(), which lives inext-calendarand is not present in every PHP build. Since v2.2.1 the method checks for it and returns the three fixed dates without Easter Monday when it is missing. Before v2.2.1 it raisedError: Call to undefined function easter_date().
Check for it if you depend on the Easter date:
$holidays = Teamleader::closingDays()->getCommonHolidays(2025);
if (! isset($holidays['Easter Monday'])) {
// ext-calendar is not loaded β supply the date yourself
}For anything beyond a rough default, generate the dates yourself and pass them to bulkAdd().
| Filter | Type | Description |
|---|---|---|
date_after |
string | Start of the period (inclusive). Format YYYY-MM-DD
|
date_before |
string | End of the period (inclusive). Format YYYY-MM-DD
|
That is the complete set. Both values are validated as YYYY-MM-DD before the request, and any other key throws.
The API specification's descriptions for these two are swapped β it labels
date_beforeas "start of the period" anddate_afteras "end of the period". The names are the reliable guide:date_afteris the lower bound,date_beforethe upper. The SDK's helpers (forMonth(),forYear(),forDateRange()) use them that way round.Unknown filter keys throw since v2.2.1. They were previously dropped silently β the API ignores keys it does not recognise and returns every closing day with HTTP 200, so a mistyped key produced a plausible but unfiltered result.
[
'data' => [
['id' => 'closing-day-uuid', 'date' => '2025-12-25'],
['id' => 'closing-day-uuid', 'date' => '2025-12-26'],
],
'meta' => [
'page' => ['size' => 20, 'number' => 1],
'matches' => 12,
],
'headers' => ['X-RateLimit-Remaining' => ['199'], /* ... */],
]The field is
dateon read,dayon write. You pass['day' => '2025-12-25']tocreate(), and read back['id' => ..., 'date' => '2025-12-25']. Earlier versions of this page showeddayin the list response, which is not what the API returns.
metais real here. Most resources return no pagination metadata at all; this one does, because the SDK sendsincludes=pagination.meta.matchesis a genuine total count, so you can page deterministically rather than waiting for a short page.
[
'data' => ['type' => 'closingDay', 'id' => 'closing-day-uuid'],
'headers' => [/* ... */],
]$holidays = Teamleader::closingDays()->getCommonHolidays(2025);
Teamleader::closingDays()->bulkAdd(array_values($holidays));For a complete Belgian calendar, supply your own dates:
Teamleader::closingDays()->bulkAdd([
'2025-01-01', // Nieuwjaar
'2025-04-21', // Paasmaandag
'2025-05-01', // Dag van de Arbeid
'2025-05-29', // O.L.H. Hemelvaart
'2025-06-09', // Pinkstermaandag
'2025-07-21', // Nationale feestdag
'2025-08-15', // O.L.V. Hemelvaart
'2025-11-01', // Allerheiligen
'2025-11-11', // Wapenstilstand
'2025-12-25', // Kerstmis
]);$result = Teamleader::closingDays()->forDateRange('2025-12-25', '2025-12-25');
if (! empty($result['data'])) {
Teamleader::closingDays()->delete($result['data'][0]['id']);
}isClosingDay() costs one request each. For more than one date, fetch the year once:
$closingDays = Teamleader::closingDays()->forYear((int) date('Y'));
$closedDates = array_column($closingDays['data'], 'date');
$isClosed = in_array('2025-12-25', $closedDates, true);$closedDates = Cache::remember('tl_closing_days_'.date('Y'), 86400, fn () =>
array_column(
Teamleader::closingDays()->forYear((int) date('Y'))['data'],
'date'
)
);use InvalidArgumentException;
use McoreServices\TeamleaderSDK\Exceptions\TeamleaderException;
// Invalid date format β thrown before the request
try {
Teamleader::closingDays()->add('25-12-2025'); // wrong format
} catch (InvalidArgumentException $e) {
// 'The "day" field must be a valid date in YYYY-MM-DD format'
}
// Invalid filter format
try {
Teamleader::closingDays()->list(['date_after' => '01/01/2025']);
} catch (InvalidArgumentException $e) {
// 'date_after must be in YYYY-MM-DD format'
}
// Unsupported filter key
try {
Teamleader::closingDays()->list(['date' => '2025-12-25']);
} catch (InvalidArgumentException $e) {
// 'Unsupported filter key for closingDays.list: date.
// Supported: date_before, date_after.'
}
// Sorting is not supported
try {
Teamleader::closingDays()->list([], ['sort' => 'date']);
} catch (InvalidArgumentException $e) {
// 'closingDays.list does not support sorting. Passed: sort. Records come
// back in the order the API chooses.'
}
// Invalid month format
try {
Teamleader::closingDays()->forMonth('2025-1');
} catch (InvalidArgumentException $e) {
// 'Month format must be YYYY-MM'
}
// Reversed date range
try {
Teamleader::closingDays()->forDateRange('2025-12-31', '2025-01-01');
} catch (InvalidArgumentException $e) {
// 'Start date must be before or equal to end date'
}
// bulkAdd() catches failures per-entry β check results for errors
$results = Teamleader::closingDays()->bulkAdd(['2025-12-25', 'bad-date']);
foreach ($results as $result) {
if (isset($result['error'])) {
Log::warning('Bulk add failure', ['message' => $result['message']]);
}
}
// API-level errors
try {
Teamleader::closingDays()->delete('closing-day-uuid');
} catch (TeamleaderException $e) {
Log::error('Teamleader error', ['message' => $e->getMessage()]);
}-
Day Off Types β Categories of leave used with
daysOff - Days Off β Import/delete individual user leave entries
-
Users β
listDaysOff()reads user leave records - User Availability β Closing days affect availability calculations
- Filtering β Filter and pagination reference
Last Updated: August 2026 β’ SDK Version: 2.2.2 β’ Made with β€οΈ by MCore Services
- Departments
- Users
- Teams
- Custom Fields
- Work Types
- Document Templates
- Currencies
- Notes
- Email Tracking
- Closing Days
- Day Off Types
- Days Off
- User Schedules
- Invoices
- Credit Notes
- Subscriptions
- Payment Methods
- Payment Terms
- Tax Rates
- Withholding Tax Rates
- Commercial Discounts
Next Gen Projects
Legacy Projects