What date does this legal deadline fall on?
Agents should not guess due dates. One call returns the deadline under an explicitly chosen computation regime, with every skipped weekend and holiday named.
By Matthias Begot ·
An agent that files a response, serves a notice or schedules a termination has
to commit to a date. Adding days to a date looks like the easiest thing in
the request — it is the part most likely to be silently wrong, because the
answer depends on a counting rule the agent was never told, a national holiday
calendar it does not carry, and a rollover rule that may or may not apply. One
paid call — GET /legal/deadline — returns the due
date under a computation regime you choose explicitly, together with every
weekend and public holiday it skipped, named and dated, and the calculation
written out step by step.
Three independent things can be wrong about a due date
“Five days from 6 May” is not a computation. It is a question with at least three unstated parameters:
- What counts as a day. Calendar days, working days (Monday to Friday), business days (Monday to Saturday), or jours francs — clear days, where neither the day of the act nor the day of expiry counts.
- Which calendar. Public holidays are national, and sometimes regional. The same term, the same start date and the same regime produce different dates in Paris and in Strasbourg.
- Whether the date rolls over. A term expiring on a Saturday may be postponed to the next working day — under some regimes, in some jurisdictions.
Get any one of the three wrong and the output is still a plausible-looking ISO date. There is no runtime error to catch. That is exactly the failure profile an autonomous agent should not absorb into its own reasoning.
The counting rules are written law, not convention
These are not house conventions to be inferred from context; they are codified, and they differ by legal order.
| Legal order | Instrument | Day of the act | Weekend / holiday expiry | Months |
|---|---|---|---|---|
| France (civil procedure) | Articles 641 and 642 of the Code de procédure civile | Does not count | Term extended to the next working day (art. 642) | Expires on the day bearing the same day-of-month |
| European Union | Regulation (EEC, Euratom) No 1182/71 | Does not count (art. 3) | Period ends at the last hour of the following working day (art. 3) | If the day does not exist in the last month, the period ends on the last day of that month |
Two independently drafted regimes, converging on the same three primitives —
which is precisely why a generic date + N is wrong so often, and why the
endpoint returns which rule it applied rather than only the result. Whether
Regulation 1182/71 is still the version in force is itself a question you can
put to GET /legal/eu-act.
The regime is the caller’s decision, and it is never inferred
The endpoint dates a term. It does not advise which term applies to your
matter, nor which regime governs it. Ask for a deadline without a regime and
you get a 400 that lists the seven admissible values instead of a plausible
default:
{ "code": "INVALID_INPUT",
"error": "query parameter `regime` is required; choose one of calendar_days, calendar_days_with_rollover, business_days, working_days, clear_days, months, years — the regime is never inferred from the legal matter" }
regime | Counts | Rollover |
|---|---|---|
calendar_days | Every day; no calendar is consulted at all | No |
calendar_days_with_rollover | Every day | Yes |
business_days | Monday to Saturday, public holidays excluded | Yes |
working_days | Monday to Friday, public holidays excluded | No |
clear_days (jours francs) | Neither the day of the act nor the day of expiry counts | Yes |
months | Same day-of-month, then the end-of-month rule | Yes |
years | The same rules, in years | Yes |
Refusing to guess is the whole point. A date computed under the wrong regime is indistinguishable, in the response, from a date computed under the right one — so the choice is pushed back to the caller, where the legal knowledge actually lives.
The call
A start date, a length, a regime, and the country whose holiday calendar
applies. Every regime except calendar_days consults a calendar and therefore
requires country.
GET /legal/deadline?start=2026-05-06&duration=5®ime=working_days&country=FR
Five working days from 6 May 2026 in France is 15 May, not 11 May — four days were skipped, and the response names all four:
{
"data": {
"due_date": "2026-05-15",
"regime": "working_days",
"unit": "days",
"start_date": "2026-05-06",
"start_date_effective": "2026-05-07",
"days_counted": 5,
"skipped_days": [
{ "date": "2026-05-08", "kind": "public_holiday", "name": "Victory in Europe Day", "name_local": "8 mai" },
{ "date": "2026-05-09", "kind": "weekend", "name": "Sat" },
{ "date": "2026-05-10", "kind": "weekend", "name": "Sun" },
{ "date": "2026-05-14", "kind": "public_holiday", "name": "Ascension Day", "name_local": "Ascension" }
],
"rollover_applied": false,
"steps": [
"day of the act 2026-05-06 is not counted (art. 641 CPC): counting starts on the next day",
"5 working days (Monday to Friday, public holidays excluded) counted: 2026-05-07 to 2026-05-15, 4 day(s) skipped",
"regime `working_days` applies no rollover: due date stands at 2026-05-15"
],
"calendar": { "country": "FR", "authority": "official", "as_of": "2026-07-29" }
},
"provenance": {
"source": "official-holiday-calendars",
"freshness": { "kind": "snapshot", "as_of": "2026-07-29T00:00:00Z" }
}
}
due_date is the answer. Everything beside it exists so the answer can be
checked without trusting the service: an agent can log skipped_days and
steps into its audit trail, and a human reviewing the file later can redo the
count by hand in under a minute.
Two rules can stack on one term
A term in months from the 31st is where the end-of-month rule and the rollover rule meet. One month from 31 January 2026: day 31 does not exist in February, so the term lands on the 28th — a Saturday — and article 642 pushes it to the following Monday.
{
"due_date": "2026-03-02",
"rollover_applied": true,
"rollover_reason": "due date 2026-02-28 falls on a Sat",
"steps": [
"term of 1 months: the deadline expires on the day bearing the same day-of-month as 2026-01-31 (art. 641 CPC)",
"day 31 does not exist in the target month: end-of-month rule applies, due date is 2026-02-28",
"2026-02-28 is not a working day (Sat): deadline extended (art. 642 CPC)",
"2026-03-01 is not a working day (Sun): deadline extended (art. 642 CPC)",
"rolled over to the next working day: 2026-03-02"
]
}
Both rules are named in steps, in the order they were applied. Note also what
is absent: days_counted is not served for months and years, because a
term in months counts no days and the service does not manufacture a number to
fill a field.
Whose calendar, and on whose authority
Ten countries are covered. France comes from the holiday calendar published
by the French State (the Etalab calendrier.api.gouv.fr dataset); BE, DE,
ES, IE, IT, LU, NL, PL and PT come from an open community reference dataset
(Nager.Date) that has no official standing. Every answer carries which one
backed it, in data.calendar.authority — official or community_dataset. A
community dataset never silently becomes published law inside an integration.
Regional calendars matter more than they look. The same request, run twice,
differing only by subdivision:
| Request | Skipped | due_date |
|---|---|---|
start=2026-04-01&duration=3®ime=working_days&country=FR | Sat, Sun, Easter Monday | 2026-04-07 |
… &subdivision=FR-ALSACE-MOSELLE | Good Friday, Sat, Sun, Easter Monday | 2026-04-08 |
Good Friday is a public holiday under the local law of Alsace-Moselle (article
L3134-13 of the Code du travail) and not elsewhere in France. That single day
moves the deadline, and data.calendar.subdivision is echoed on the response so
the answer always says which of the two calendars it used.
Holiday calendars are also not constants. In July 2025 the French government
proposed removing two public holidays as part of the 2026 budget; the proposal
was subsequently dropped. Either outcome is a reason not to freeze a holiday
table into agent code: provenance.freshness.as_of tells you the date of the
calendar dump that backed the answer, and it has its own refresh cycle,
independent of the LEGI and EUR-Lex dumps behind
GET /legal/article.
Out of coverage is a refusal, not a guess
Per the x402 golden rule, the agent pays for the answer to its question. A well-formed request on a covered calendar returns its due date — a 200. What the service cannot answer leaves the 200 range and is not billed, because a deadline computed on a guessed calendar is worse than no deadline:
{ "code": "COUNTRY_NOT_COVERED",
"error": "no holiday calendar for country `US`; covered countries: BE, DE, ES, FR, IE, IT, LU, NL, PL, PT" }
{ "code": "OUT_OF_COVERAGE_WINDOW",
"error": "date 2033-01-05 is outside the loaded holiday calendar for `FR` (2015-01-01 to 2029-12-31 inclusive)" }
The coverage window is derived from the days actually present in the loaded
calendar rather than declared, and both bounds are inclusive. A start date or a
due date beyond it is a 404: days whose holiday status is unknown are never
counted as ordinary days. Every refusal names what is covered, so the second
call can succeed.
What it will not do
Three sentences travel in data.limits on every answer. They are the
contract, not small print:
- It does not choose the term or the regime. It dates a term; it does not advise which term applies or which regime governs it.
- It counts civil days, not hours. Hourly time limits, court closing hours, judicial vacations and non-working days set by contract or collective agreement are out of scope.
- It does not upgrade a community dataset into published law.
officialandcommunity_datasetride on every answer precisely so that distinction cannot be lost downstream.
It also does not search for the deadline applicable to a situation, interpret a contract, or reason about time zones and filing hours.
Where it sits in the x402 loop
The call follows the same pattern as every Invoket endpoint — discover, receive
the 402, sign the chosen rail, replay:
- Discover the endpoint on the catalog
and call it; receive the
402. - Pay — sign and replay the request.
- Read
due_date, and keepstepsplusskipped_daysin the audit trail. - Branch — schedule against
due_date; if the response carriesauthority: "community_dataset", decide whether that is good enough for the decision at hand.
The Quickstart walks the whole discover → 402 → pay →
replay cycle with runnable snippets. Price and accepted rails are deliberately
not pinned in this article: the catalog is
the single source of truth for both, and it also states which endpoints
currently carry a free trial call.
Two endpoints pair naturally with this one on either side of a due date:
GET /legal/articleandGET /legal/eu-act— the text that sets the term, and whether it is still in force.POST /invoice/late-payment— once a due date has passed, what the unpaid claim actually owes under Directive 2011/7/EU./legal/deadlineproduces the date;/invoice/late-paymentprices the breach of it.
Used for what it is — a deterministic, auditable date under a regime the caller
chose — GET /legal/deadline removes date
arithmetic from the list of things an agent has to be trusted with. For the full
field reference, the seven regimes and the error codes, see the
endpoint documentation; for how agents discover and
call Invoket endpoints, see For agents.
Sources and attribution
- Regulation (EEC, Euratom) No 1182/71 determining the rules applicable to periods, dates and time limits — EUR-Lex, Publications Office of the European Union.
- Article 642 du Code de procédure civile and Chapitre Ier : La computation des délais (art. 640 à 647-1) — Légifrance, DILA.
- Article L3134-13 du Code du travail — local law of Alsace-Moselle.
- API Jours fériés — Etalab / data.gouv.fr, and the
etalab/calendrier.api.gouv.frrepository. - Nager.Date — open community holiday dataset, no official standing.
- Suppression de deux jours fériés dans le budget 2026 — franceinfo, on the July 2025 proposal later abandoned.
The French public-holiday calendar is derived from the open dataset published by the French State under the Licence Ouverte / Etalab. The nine other national calendars come from the Nager.Date open reference dataset. Articles 641 and 642 of the Code de procédure civile are cited from the LEGI dataset made available by DILA on Légifrance.