API reference
Base URL https://dierum.io. Every endpoint returns JSON over HTTPS. Examples in curl, Python, JavaScript, and C#. The language tabs stay in sync as you read.
Authentication
Pass your key in the X-Api-Key header. A key takes one signup with
an email address (free tier included) and is shown
once, at creation. Lost keys are replaced, not recovered: POST /v1/rotate
with your email revokes the old key and mails a new one.
curl "https://dierum.io/v1/check?region=US&date=2027-11-25" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/check",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'date': '2027-11-25'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/check?region=US&date=2027-11-25", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/check?region=US&date=2027-11-25");
Console.WriteLine(json);Where headers are awkward, as with calendar feeds and spreadsheet imports,
?api_key= works as a query parameter. Treat URLs containing it as
secrets: they end up in logs.
Agents: a machine-readable spec lives at /openapi.json and a compact plain-text surface at /llms.txt. Signup, keys, and every endpoint are fully self-serve; no human steps anywhere in the flow.
Keys come in two kinds. Your secret key (ck_...)
belongs on servers and never in a browser. For client-side code and widgets,
mint a publishable key: origin-locked, read-only, and
safe to ship. CORS is open on the whole API; the key is the gate.
Limits
| Plan | Requests / day | Price |
|---|---|---|
| Free | 100 | $0 |
| Developer | 1,000 | $8 / month |
| Starter | 10,000 | $20 / month |
| Pro | 100,000 | $48 / month |
| Business | 500,000 | $150 / month |
| Enterprise | negotiated | from $500 / month |
Every response carries X-RateLimit-Limit and
X-RateLimit-Used. Limits reset at midnight UTC. Requests over the
limit return 429 and are not counted against you. Batch operations
meter per inner operation.
Errors
Errors are { "error": { "code", "message" } } with a matching
HTTP status. The codes worth handling:
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_date · bad_terms · bad_rule | Malformed input. Dates are yyyy-MM-dd. |
| 401 | missing_key · invalid_key | No key, or a revoked one. |
| 404 | unknown_region | Not in /v1/regions. |
| 422 | out_of_range | The result would leave 2020–2035. We refuse rather than guess. |
| 429 | quota_exceeded | Daily limit reached. |
GET /v1/check
Classify one date: business day, weekend, or holiday, with the next business day included.
| Parameter | Notes |
|---|---|
region | ISO 3166 code, subdivision, or market · see /v1/regions |
date | yyyy-MM-dd |
curl "https://dierum.io/v1/check?region=US&date=2027-11-25" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/check",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'date': '2027-11-25'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/check?region=US&date=2027-11-25", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/check?region=US&date=2027-11-25");
Console.WriteLine(json);Response
{ "region": "US", "date": "2027-11-25", "business_day": false,
"weekend": false, "holiday": true, "holiday_name": "Thanksgiving",
"next_business_day": "2027-11-26" }
GET /v1/add
Add or subtract business days. days may be negative; zero returns the start date unchanged. The primitive under settlement dates and simple deadlines.
| Parameter | Notes |
|---|---|
region | calendar to use · XNYS here, so Good Friday counts as closed |
start | yyyy-MM-dd |
days | -5000 to 5000 |
curl "https://dierum.io/v1/add?region=XNYS&start=2027-03-25&days=2" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/add",
headers={"X-Api-Key": KEY},
params={'region': 'XNYS', 'start': '2027-03-25', 'days': '2'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/add?region=XNYS&start=2027-03-25&days=2", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/add?region=XNYS&start=2027-03-25&days=2");
Console.WriteLine(json);Response
{ "region": "XNYS", "start": "2027-03-25", "days": 2, "result": "2027-03-30" }
GET /v1/count
Business days between two dates, inclusive of both ends. Negative when to precedes from, so count(a,b) = -count(b,a) always holds.
| Parameter | Notes |
|---|---|
region | subdivisions carry their own holidays · Bavaria observes Epiphany; Berlin does not |
from, to | yyyy-MM-dd |
curl "https://dierum.io/v1/count?region=DE-BY&from=2027-01-01&to=2027-01-31" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/count",
headers={"X-Api-Key": KEY},
params={'region': 'DE-BY', 'from': '2027-01-01', 'to': '2027-01-31'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/count?region=DE-BY&from=2027-01-01&to=2027-01-31", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/count?region=DE-BY&from=2027-01-01&to=2027-01-31");
Console.WriteLine(json);Response
{ "region": "DE-BY", "from": "2027-01-01", "to": "2027-01-31", "business_days": 19 }
GET /v1/due-date
Invoice date plus payment terms, rolled forward to a real working day when the nominal date lands on a weekend or holiday. Terms grammar: net30 (calendar days), net10b (business days), eom, eom+15.
| Parameter | Notes |
|---|---|
invoice_date | yyyy-MM-dd |
terms | net<n>, net<n>b, eom, eom+<n> |
curl "https://dierum.io/v1/due-date?region=US&invoice_date=2027-01-15&terms=net30" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/due-date",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'invoice_date': '2027-01-15', 'terms': 'net30'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/due-date?region=US&invoice_date=2027-01-15&terms=net30", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/due-date?region=US&invoice_date=2027-01-15&terms=net30");
Console.WriteLine(json);Response
{ "invoice_date": "2027-01-15", "terms": "net30",
"nominal_due": "2027-02-14", "due_date": "2027-02-16", "rolled": true }
GET /v1/paydays
A year of pay dates from a rule. Dates landing on weekends or holidays roll backward: payroll pays early, never late. December 2027 in the US is the canonical trap: the 31st is New Year's Day observed.
| Parameter | Notes |
|---|---|
year | 2020–2035 |
rule | last-business-day · nth:<1-28> · semi:<day>,<day|last> |
curl "https://dierum.io/v1/paydays?region=US&year=2027&rule=semi:15,last" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/paydays",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'year': '2027', 'rule': 'semi:15,last'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/paydays?region=US&year=2027&rule=semi:15,last", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/paydays?region=US&year=2027&rule=semi:15,last");
Console.WriteLine(json);Response
{ "region": "US", "year": 2027, "rule": "semi:15,last",
"paydays": ["2027-01-15", "2027-01-29", "...", "2027-12-15", "2027-12-30"] }
GET /v1/common-days
Days that are business days in every region listed. The question behind cross-border settlement, international support coverage, and shipping cutoffs. A memorable case: a US–Saudi pair shares only Monday to Thursday even in a quiet week.
| Parameter | Notes |
|---|---|
regions | 2–5 comma-separated codes |
from, to | at most 92 days apart |
curl "https://dierum.io/v1/common-days?regions=US,DE&from=2027-05-28&to=2027-06-01" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/common-days",
headers={"X-Api-Key": KEY},
params={'regions': 'US,DE', 'from': '2027-05-28', 'to': '2027-06-01'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/common-days?regions=US,DE&from=2027-05-28&to=2027-06-01", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/common-days?regions=US,DE&from=2027-05-28&to=2027-06-01");
Console.WriteLine(json);Response
{ "regions": ["US", "DE"], "from": "2027-05-28", "to": "2027-06-01",
"common_business_days": ["2027-05-28", "2027-06-01"] }
GET /v1/year
A year at a glance: total business days, per-month counts, and the full holiday list. Capacity planning and forecasting input.
| Parameter | Notes |
|---|---|
year | 2020–2035 |
curl "https://dierum.io/v1/year?region=GB&year=2027" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/year",
headers={"X-Api-Key": KEY},
params={'region': 'GB', 'year': '2027'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/year?region=GB&year=2027", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/year?region=GB&year=2027");
Console.WriteLine(json);Response
{ "region": "GB", "year": 2027, "business_days_total": 253,
"business_days_per_month": [20, 20, 23, ...], "holidays_count": 10,
"holidays": [{ "date": "2027-01-01", "name": "New Year's Day" }, ...] }
GET /v1/bridge-days
Windows where a little leave buys a long break, ranked by days off per day spent. Germany's best 2027 window: one day of leave around Easter yields five consecutive days off.
| Parameter | Notes |
|---|---|
year | 2020–2035 |
pto | leave budget, 1–5 days |
curl "https://dierum.io/v1/bridge-days?region=DE&year=2027&pto=1" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/bridge-days",
headers={"X-Api-Key": KEY},
params={'region': 'DE', 'year': '2027', 'pto': '1'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/bridge-days?region=DE&year=2027&pto=1", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/bridge-days?region=DE&year=2027&pto=1");
Console.WriteLine(json);Response
{ "region": "DE", "year": 2027, "pto_budget": 1, "windows": [
{ "from": "2027-03-25", "to": "2027-03-29", "pto_days": 1,
"total_days_off": 5, "pto_dates": ["2027-03-25"], "efficiency": 5.0 }, ...] }
GET /v1/next-holiday
Upcoming holidays with a countdown. Ops dashboards, deploy-freeze checks, or a desk widget.
| Parameter | Notes |
|---|---|
count | 1–10, default 1 |
curl "https://dierum.io/v1/next-holiday?region=US&count=2" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/next-holiday",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'count': '2'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/next-holiday?region=US&count=2", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/next-holiday?region=US&count=2");
Console.WriteLine(json);Response
{ "region": "US", "as_of": "2026-08-31", "holidays": [
{ "date": "2026-09-07", "name": "Labor Day", "days_until": 7 }, ...] }
GET /v1/holidays
The raw holiday calendar for a region and range (up to three years), when you want the list itself.
| Parameter | Notes |
|---|---|
from, to | range up to 3 years |
curl "https://dierum.io/v1/holidays?region=GB&from=2027-12-01&to=2027-12-31" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/holidays",
headers={"X-Api-Key": KEY},
params={'region': 'GB', 'from': '2027-12-01', 'to': '2027-12-31'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/holidays?region=GB&from=2027-12-01&to=2027-12-31", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/holidays?region=GB&from=2027-12-01&to=2027-12-31");
Console.WriteLine(json);Response
{ "region": "GB", "holidays": [
{ "date": "2027-12-25", "name": "Christmas Day" },
{ "date": "2027-12-27", "name": "Christmas Day (observed)" }, ...] }
GET /v1/holidays.ics
The same calendar as an iCal feed. Subscribe from Google Calendar, Apple Calendar, or Outlook and holidays appear alongside your events. No key required: calendar apps can't send headers, and the data is open-licensed. Rate-limited per IP.
| Parameter | Notes |
|---|---|
year | defaults to the current year |
curl "https://dierum.io/v1/holidays.ics?region=US&year=2027" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/holidays.ics",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'year': '2027'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/holidays.ics?region=US&year=2027", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/holidays.ics?region=US&year=2027");
Console.WriteLine(json);Response
BEGIN:VCALENDAR
VERSION:2.0
X-WR-CALNAME:Holidays US 2027
BEGIN:VEVENT
DTSTART;VALUE=DATE:20270101
SUMMARY:New Year's Day
...
POST /v1/batch
Up to 100 operations in one request (1,000 on Pro and above): add, count, check, or due-date. Each operation is metered as one request; results come back in order, with per-item errors instead of all-or-nothing failure.
| Parameter | Notes |
|---|---|
operations[].op | add · count · check · due-date |
operations[].region | any region code |
operations[]. … | parameters matching the single-call endpoint |
curl -X POST "https://dierum.io/v1/batch" \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"operations": [{"op": "add", "region": "XNYS", "start": "2027-03-25", "days": 2}, {"op": "due-date", "region": "US", "start": "2027-01-15", "terms": "net30"}]}'import requests
r = requests.post("https://dierum.io/v1/batch",
headers={"X-Api-Key": KEY},
json={"operations": [{"op": "add", "region": "XNYS", "start": "2027-03-25", "days": 2}, {"op": "due-date", "region": "US", "start": "2027-01-15", "terms": "net30"}]})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/batch", {
method: "POST",
headers: { "X-Api-Key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({"operations": [{"op": "add", "region": "XNYS", "start": "2027-03-25", "days": 2}, {"op": "due-date", "region": "US", "start": "2027-01-15", "terms": "net30"}]}),
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var body = JsonContent.Create({"operations": [{"op": "add", "region": "XNYS", "start": "2027-03-25", "days": 2}, {"op": "due-date", "region": "US", "start": "2027-01-15", "terms": "net30"}]});
var res = await http.PostAsync("https://dierum.io/v1/batch", body);
res.EnsureSuccessStatusCode();
Console.WriteLine(await res.Content.ReadAsStringAsync());Response
{ "count": 2, "results": [
{ "result": "2027-03-30" },
{ "due_date": "2027-02-16", "rolled": true } ] }
GET /v1/regions
Every supported region: countries, subdivisions, and financial markets. Each carries its own weekend definition, applied to calculations automatically. Mind the UK: bare GB is aliased to England & Wales holidays (the common industry default when no UK nation is specified). Scotland and Northern Ireland observe different dates for some bank holidays; use GB-SCT or GB-NIR for those. Mind Australia: bare AU is aliased to New South Wales, which includes the weekend-to-weekday substitute dates every state observes for Christmas, Boxing Day, New Year's, and Australia Day (e.g. Sat 25 Dec 2027 shifts the day off to Mon 27 Dec); use another AU-* code for a different state's own extra holidays.
curl "https://dierum.io/v1/regions" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/regions",
headers={"X-Api-Key": KEY})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/regions", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/regions");
Console.WriteLine(json);Response
{ "count": 1801, "regions": [
{ "code": "US", "country": "US", "subdiv": null, "kind": "country" },
{ "code": "US-CA", "country": "US", "subdiv": "CA", "kind": "subdivision" },
{ "code": "XNYS", "country": "XNYS", "subdiv": null, "kind": "financial" }, ...] }
GET /v1/diff
Day-type census for a range: how many business days, weekend days, and holidays between two dates. Capacity planning and prorating.
| Parameter | Notes |
|---|---|
from, to | up to 3 years apart |
curl "https://dierum.io/v1/diff?region=DE-BY&from=2027-01-01&to=2027-03-31" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/diff",
headers={"X-Api-Key": KEY},
params={'region': 'DE-BY', 'from': '2027-01-01', 'to': '2027-03-31'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/diff?region=DE-BY&from=2027-01-01&to=2027-03-31", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/diff?region=DE-BY&from=2027-01-01&to=2027-03-31");
Console.WriteLine(json);Response
{ "region": "DE-BY", "from": "2027-01-01", "to": "2027-03-31",
"total_days": 90, "business_days": 60, "weekend_days": 26, "holiday_days": 4 }
GET /v1/window
The next N business days from a date, as a list. The feed behind date pickers, slot schedulers, and delivery choosers.
| Parameter | Notes |
|---|---|
count | 1-100, default 10 |
start | included when it is a business day |
curl "https://dierum.io/v1/window?region=US&start=2027-11-24&count=5" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/window",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'start': '2027-11-24', 'count': '5'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/window?region=US&start=2027-11-24&count=5", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/window?region=US&start=2027-11-24&count=5");
Console.WriteLine(json);Response
{ "region": "US", "start": "2027-11-24", "count": 5,
"business_days": ["2027-11-24", "2027-11-26", "2027-11-29", "2027-11-30", "2027-12-01"] }
GET /v1/holidays.csv
The holiday calendar as CSV for spreadsheets and data pipelines. Pairs well with the query-parameter key form.
| Parameter | Notes |
|---|---|
year | defaults to the current year |
curl "https://dierum.io/v1/holidays.csv?region=GB&year=2027" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/holidays.csv",
headers={"X-Api-Key": KEY},
params={'region': 'GB', 'year': '2027'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/holidays.csv?region=GB&year=2027", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/holidays.csv?region=GB&year=2027");
Console.WriteLine(json);Response
date,name
2027-01-01,"New Year's Day"
2027-03-26,"Good Friday"
...
GET /v1/nth
The nth business day of each month, from either end. The schedule behind "invoice on the 3rd business day" and "settle 3 days before month end" rules.
| Parameter | Notes |
|---|---|
n | 1-23 |
from_end | true counts backward from month end |
curl "https://dierum.io/v1/nth?region=US&year=2027&n=3&from_end=false" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/nth",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'year': '2027', 'n': '3', 'from_end': 'false'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/nth?region=US&year=2027&n=3&from_end=false", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/nth?region=US&year=2027&n=3&from_end=false");
Console.WriteLine(json);Response
{ "region": "US", "year": 2027, "n": 3, "from_end": false,
"dates": ["2027-01-06", "2027-02-03", "..."] }
POST /v1/public-keys
Mints a publishable key (pk_...) for browser code and widgets: locked to the origins you list, accepted only on read-only endpoints, metered against your account, and revoked when you rotate your secret key. Requires your secret key; keep that one server-side.
| Parameter | Notes |
|---|---|
origins | 1-10; https only, except http on localhost |
curl -X POST "https://dierum.io/v1/public-keys" \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"origins": ["https://your-site.com", "http://localhost:4200"]}'import requests
r = requests.post("https://dierum.io/v1/public-keys",
headers={"X-Api-Key": KEY},
json={"origins": ["https://your-site.com", "http://localhost:4200"]})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/public-keys", {
method: "POST",
headers: { "X-Api-Key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({"origins": ["https://your-site.com", "http://localhost:4200"]}),
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var body = JsonContent.Create({"origins": ["https://your-site.com", "http://localhost:4200"]});
var res = await http.PostAsync("https://dierum.io/v1/public-keys", body);
res.EnsureSuccessStatusCode();
Console.WriteLine(await res.Content.ReadAsStringAsync());Response
{ "public_key": "pk_4c9...",
"origins": ["https://your-site.com", "http://localhost:4200"] }
GET /v1/pay-periods
Pay periods with paydays rolled back off non-working days. The anchored biweekly rule is the one fixed-date systems cannot express and most US payrolls run on: pass any known payday as the anchor and the phase is preserved forever.
| Parameter | Notes |
|---|---|
rule | weekly | biweekly | semi-monthly | monthly |
anchor | a known payday; required for weekly/biweekly |
from, count | first period on/after from; up to 60 |
curl "https://dierum.io/v1/pay-periods?region=US&rule=biweekly&anchor=2027-01-08&from=2027-02-01&count=3" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/pay-periods",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'rule': 'biweekly', 'anchor': '2027-01-08', 'from': '2027-02-01', 'count': '3'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/pay-periods?region=US&rule=biweekly&anchor=2027-01-08&from=2027-02-01&count=3", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/pay-periods?region=US&rule=biweekly&anchor=2027-01-08&from=2027-02-01&count=3");
Console.WriteLine(json);Response
{ "rule": "biweekly", "periods": [
{ "period_start": "2027-01-23", "period_end": "2027-02-05", "payday": "2027-02-05" },
{ "period_start": "2027-02-06", "period_end": "2027-02-19", "payday": "2027-02-19" }, ...] }
GET /v1/add-hours
Business-hours arithmetic inside a working window: "respond within 8 business hours" resolved to an exact date and time. Hours spill across holidays and weekends; a start outside the window clips to the next opening. Times are local wall-clock; time zones stay the caller's affair.
| Parameter | Notes |
|---|---|
time | HH:mm start |
hours | 0-2000, fractions allowed |
window | HH:mm-HH:mm, default 09:00-17:00 |
curl "https://dierum.io/v1/add-hours?region=DE&start=2027-03-25&time=16:00&hours=2&window=09:00-17:00" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/add-hours",
headers={"X-Api-Key": KEY},
params={'region': 'DE', 'start': '2027-03-25', 'time': '16:00', 'hours': '2', 'window': '09:00-17:00'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/add-hours?region=DE&start=2027-03-25&time=16:00&hours=2&window=09:00-17:00", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/add-hours?region=DE&start=2027-03-25&time=16:00&hours=2&window=09:00-17:00");
Console.WriteLine(json);Response
{ "start": "2027-03-25", "time": "16:00", "hours": 2,
"result_date": "2027-03-30", "result_time": "10:00" }
GET /v1/recurrence
Recurring schedules that respect the calendar: every N weeks on a weekday, the nth weekday monthly, or the last weekday monthly, with your choice of roll policy when a date lands closed.
| Parameter | Notes |
|---|---|
rule | weekly:<1-12>:<dow> | nth:<1-5>:<dow> | last:<dow> |
roll | forward | backward | skip | none |
curl "https://dierum.io/v1/recurrence?region=US&rule=nth:3:thu&start=2027-01-01&count=3&roll=forward" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/recurrence",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'rule': 'nth:3:thu', 'start': '2027-01-01', 'count': '3', 'roll': 'forward'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/recurrence?region=US&rule=nth:3:thu&start=2027-01-01&count=3&roll=forward", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/recurrence?region=US&rule=nth:3:thu&start=2027-01-01&count=3&roll=forward");
Console.WriteLine(json);Response
{ "rule": "nth:3:thu", "dates": ["2027-01-21", "2027-02-18", "2027-03-18"] }
GET /v1/quarter
The fiscal quarter containing a date, with business-day totals, elapsed, and remaining. Custom fiscal-year starts for the July and February crowd.
| Parameter | Notes |
|---|---|
fiscal_start | month 1-12, default 1 |
date | defaults to today |
curl "https://dierum.io/v1/quarter?region=US&date=2027-02-15&fiscal_start=7" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/quarter",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'date': '2027-02-15', 'fiscal_start': '7'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/quarter?region=US&date=2027-02-15&fiscal_start=7", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/quarter?region=US&date=2027-02-15&fiscal_start=7");
Console.WriteLine(json);Response
{ "quarter": "Q3", "quarter_start": "2027-01-01", "quarter_end": "2027-03-31",
"business_days_total": 61, "business_days_elapsed": 32, "business_days_remaining": 29 }
GET /v1/tenor
Add a financial tenor (2W, 3M, 1Y) the way settlement systems do: land on the nominal date, then apply a roll convention. Modified-following rolls forward unless that crosses a month boundary, in which case it rolls back; the end-of-month rule keeps month-end starts on month-ends. This is the arithmetic behind deposit maturities, swap schedules, and net-90 terms that must stay in the right month.
| Parameter | Notes |
|---|---|
tenor | <n>D | <n>W | <n>M | <n>Y, n up to 999 |
convention | following | modified-following | preceding | modified-preceding | unadjusted; default modified-following |
eom | end-of-month rule, default true; a month-end start plus months lands on the target month-end |
curl "https://dierum.io/v1/tenor?region=GB&start=2027-02-26&tenor=1M&convention=modified-following" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/tenor",
headers={"X-Api-Key": KEY},
params={'region': 'GB', 'start': '2027-02-26', 'tenor': '1M', 'convention': 'modified-following'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/tenor?region=GB&start=2027-02-26&tenor=1M&convention=modified-following", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/tenor?region=GB&start=2027-02-26&tenor=1M&convention=modified-following");
Console.WriteLine(json);Response
{ "start": "2027-02-26", "tenor": "1M", "convention": "modified-following",
"eom": true, "result": "2027-03-31" }
GET /v1/day-count
The day count and year fraction between two dates under the five conventions interest math actually uses. 30/360 US and 30E/360 apply their month-end adjustments; ACT/ACT ISDA splits the range at year boundaries so leap years weight correctly.
| Parameter | Notes |
|---|---|
basis | ACT/360 (default) | ACT/365F | 30/360 | 30E/360 | ACT/ACT |
curl "https://dierum.io/v1/day-count?from=2027-01-31&to=2027-07-31&basis=30/360" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/day-count",
headers={"X-Api-Key": KEY},
params={'from': '2027-01-31', 'to': '2027-07-31', 'basis': '30/360'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/day-count?from=2027-01-31&to=2027-07-31&basis=30/360", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/day-count?from=2027-01-31&to=2027-07-31&basis=30/360");
Console.WriteLine(json);Response
{ "from": "2027-01-31", "to": "2027-07-31", "basis": "30/360",
"days": 180, "fraction": 0.5 }
GET /v1/installments
An amount split into installments that sum back to the total exactly, in cents, with every due date rolled off weekends and holidays. The remainder cents go to the earliest payments, so three payments of $100.00 come out 33.34 + 33.33 + 33.33, never 99.99 or 100.02.
| Parameter | Notes |
|---|---|
amount_cents | total in minor units, 1-100,000,000 |
count | 2-60 payments |
first | first due date |
cadence | monthly (default) | biweekly | weekly |
roll | forward (default) | backward |
curl "https://dierum.io/v1/installments?region=US&amount_cents=10000&count=3&first=2027-05-31&cadence=monthly" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/installments",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'amount_cents': '10000', 'count': '3', 'first': '2027-05-31', 'cadence': 'monthly'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/installments?region=US&amount_cents=10000&count=3&first=2027-05-31&cadence=monthly", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/installments?region=US&amount_cents=10000&count=3&first=2027-05-31&cadence=monthly");
Console.WriteLine(json);Response
{ "amount_cents": 10000, "count": 3, "total_check": 10000, "installments": [
{ "date": "2027-06-01", "amount_cents": 3334 },
{ "date": "2027-06-30", "amount_cents": 3333 },
{ "date": "2027-08-02", "amount_cents": 3333 } ] }
GET /v1/elapsed
Business days since a date, not counting the start day itself. "Opened 12 business days ago" for ticket queues, invoice aging buckets, and SLA clocks that should not tick on Sundays.
| Parameter | Notes |
|---|---|
since | yyyy-MM-dd |
until | defaults to today, UTC |
curl "https://dierum.io/v1/elapsed?region=US&since=2027-11-19" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/elapsed",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'since': '2027-11-19'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/elapsed?region=US&since=2027-11-19", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/elapsed?region=US&since=2027-11-19");
Console.WriteLine(json);Response
{ "region": "US", "since": "2027-11-19", "until": "2027-11-29",
"business_days_elapsed": 5 }
GET /v1/long-weekends
Every stretch of three or more consecutive days off in a year, with the holidays that make it happen. Travel demand planning, staffing forecasts, and "book one day, get five" content.
| Parameter | Notes |
|---|---|
year | 2020-2035, defaults to the current year |
curl "https://dierum.io/v1/long-weekends?region=DE&year=2027" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/long-weekends",
headers={"X-Api-Key": KEY},
params={'region': 'DE', 'year': '2027'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/long-weekends?region=DE&year=2027", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/long-weekends?region=DE&year=2027");
Console.WriteLine(json);Response
{ "region": "DE", "year": 2027, "long_weekends": [
{ "start": "2027-03-26", "end": "2027-03-29", "days": 4,
"holidays": ["Karfreitag", "Ostermontag"] }, ...] }
Invoice due dates that survive the calendar
Accounts receivable at volume: one batch call turns an invoice run into correct, holiday-aware due dates.
curl -X POST "https://dierum.io/v1/batch" \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"operations": [{"op": "due-date", "region": "US", "start": "2027-01-15", "terms": "net30"}, {"op": "due-date", "region": "DE", "start": "2027-01-15", "terms": "net45"}, {"op": "due-date", "region": "GB", "start": "2027-01-15", "terms": "eom+15"}]}'import requests
r = requests.post("https://dierum.io/v1/batch",
headers={"X-Api-Key": KEY},
json={"operations": [{"op": "due-date", "region": "US", "start": "2027-01-15", "terms": "net30"}, {"op": "due-date", "region": "DE", "start": "2027-01-15", "terms": "net45"}, {"op": "due-date", "region": "GB", "start": "2027-01-15", "terms": "eom+15"}]})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/batch", {
method: "POST",
headers: { "X-Api-Key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({"operations": [{"op": "due-date", "region": "US", "start": "2027-01-15", "terms": "net30"}, {"op": "due-date", "region": "DE", "start": "2027-01-15", "terms": "net45"}, {"op": "due-date", "region": "GB", "start": "2027-01-15", "terms": "eom+15"}]}),
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var body = JsonContent.Create({"operations": [{"op": "due-date", "region": "US", "start": "2027-01-15", "terms": "net30"}, {"op": "due-date", "region": "DE", "start": "2027-01-15", "terms": "net45"}, {"op": "due-date", "region": "GB", "start": "2027-01-15", "terms": "eom+15"}]});
var res = await http.PostAsync("https://dierum.io/v1/batch", body);
res.EnsureSuccessStatusCode();
Console.WriteLine(await res.Content.ReadAsStringAsync());Response
{ "count": 3, "results": [
{ "due_date": "2027-02-16", "rolled": true },
{ "due_date": "2027-03-01", "rolled": false },
{ "due_date": "2027-02-16", "rolled": true } ] }
An SLA deadline that holds up in a dispute
Ticket opened in Munich on the Wednesday before Easter, five business days to respond. Good Friday and Easter Monday are statutory holidays in Germany; the deadline is a week later than a weekend-only calculation claims.
curl "https://dierum.io/v1/add?region=DE&start=2027-03-24&days=5" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/add",
headers={"X-Api-Key": KEY},
params={'region': 'DE', 'start': '2027-03-24', 'days': '5'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/add?region=DE&start=2027-03-24&days=5", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/add?region=DE&start=2027-03-24&days=5");
Console.WriteLine(json);Response
{ "region": "DE", "start": "2027-03-24", "days": 5, "result": "2027-04-01" }
Publishing next year's payroll calendar
One call per pay group. Semi-monthly staff paid on the 15th and month-end, rolled back from weekends and holidays:
curl "https://dierum.io/v1/paydays?region=US&year=2027&rule=semi:15,last" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/paydays",
headers={"X-Api-Key": KEY},
params={'region': 'US', 'year': '2027', 'rule': 'semi:15,last'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/paydays?region=US&year=2027&rule=semi:15,last", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/paydays?region=US&year=2027&rule=semi:15,last");
Console.WriteLine(json);Response
{ "paydays": ["2027-01-15", "2027-01-29", "2027-02-12", "2027-02-26",
"...", "2027-12-15", "2027-12-30"] }
Checking a cross-border settlement window
A EUR/USD trade needs both TARGET2 and US markets open. Ask for the days both calendars agree on:
curl "https://dierum.io/v1/common-days?regions=ECB,XNYS&from=2027-05-01&to=2027-05-31" -H "X-Api-Key: $KEY"import requests
r = requests.get("https://dierum.io/v1/common-days",
headers={"X-Api-Key": KEY},
params={'regions': 'ECB,XNYS', 'from': '2027-05-01', 'to': '2027-05-31'})
r.raise_for_status()
print(r.json())const r = await fetch("https://dierum.io/v1/common-days?regions=ECB,XNYS&from=2027-05-01&to=2027-05-31", {
headers: { "X-Api-Key": KEY },
});
if (!r.ok) throw new Error(`dierum: ${r.status}`);
console.log(await r.json());using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", key);
var json = await http.GetStringAsync(
"https://dierum.io/v1/common-days?regions=ECB,XNYS&from=2027-05-01&to=2027-05-31");
Console.WriteLine(json);Response
{ "regions": ["ECB", "XNYS"],
"common_business_days": ["2027-05-03", "2027-05-04", "..."] }
Data provenance
Holiday data derives from the MIT-licensed python-holidays project, one of the most actively maintained calendar datasets anywhere. It is regenerated and cross-verified against independent sources on every refresh. Weekend rules are curated separately: Friday–Saturday across much of the Middle East, Saturday alone in Nepal, Friday and Sunday in Brunei. The dataset version and generation timestamp are public at /health.
Found an error in a calendar? Tell us. Corrections ship in the next daily refresh, and we credit reporters who want it.