API documentation

Base URL https://bankday.jacklehoff4866.workers.dev/v1. Every endpoint is a GET returning JSON. Dates are YYYY-MM-DD.

Quickstart

  1. Get a free API key (instant, 1,000 requests/month).
  2. Call an endpoint:
export BANKDAY_KEY=bd_live_...
curl "https://bankday.jacklehoff4866.workers.dev/v1/today?calendar=us-fed" -H "Authorization: Bearer $BANKDAY_KEY"

Authentication

Send your key in the Authorization: Bearer header (preferred) or X-API-Key header. ?api_key= also works for quick tests, but keeps keys in logs, so avoid it in production. Keys can be rotated from the dashboard. CORS is open, but don't ship your key in public front-end code; call Bankday from your server.

Calendars

A calendar is a set of weekend days plus a list of closures. Three kinds:

Which one should I use? For US bank transfers, ACH and wires use us-fed, not us: the Fed's schedule differs from federal-government closures. For euro payments use eu-target2. For UK Direct Debits use uk-bacs. For trade settlement use the exchange.

Each calendar has a coverage range (most 2000–2040). Requests outside it return 422 date_out_of_range rather than a wrong answer.

Joint calendars

Pass several ids separated by commas. A day is a business day only if it is a business day on every calendar, and responses list which calendar closed it. Typical uses: cross-border payouts (us-fed,eu-target2), US equities settled in USD (xnys,us-fed), multi-country payroll.

Is a date a business day?

GET/v1/business-day

Returns whether date is a business day on the calendar, why not (weekend or the holiday name, per calendar), and the next and previous business days. Alias: /v1/is-business-day.

ParameterDescription
calendar requiredCalendar id, or up to 10 comma-separated ids for a joint calendar (e.g. us-fed,eu-target2). Aliases such as nyse, ach, sepa, bacs are accepted.
date requiredYYYY-MM-DD

curl "https://bankday.jacklehoff4866.workers.dev/v1/business-day?calendar=us-fed&date=2026-10-12" \
  -H "Authorization: Bearer $BANKDAY_KEY"
{
  "calendar": "us-fed",
  "date": "2026-10-12",
  "weekday": "Monday",
  "business_day": false,
  "closures": [{ "calendar": "us-fed", "reason": "holiday", "name": "Columbus Day" }],
  "next_business_day": "2026-10-13",
  "previous_business_day": "2026-10-09"
}

Today's status in the calendar's time zone

GET/v1/today

Same as business-day for the current date in the calendar's local time zone (e.g. America/New_York for us-fed), plus the next five holidays within 120 days.

ParameterDescription
calendar requiredCalendar id, or up to 10 comma-separated ids for a joint calendar (e.g. us-fed,eu-target2). Aliases such as nyse, ach, sepa, bacs are accepted.
timezoneOptional IANA time zone overriding the calendar's own (default UTC for country calendars).

curl "https://bankday.jacklehoff4866.workers.dev/v1/today?calendar=xnys" \
  -H "Authorization: Bearer $BANKDAY_KEY"

Add or subtract business days

GET/v1/business-days/add

Moves days business days from date. The start date itself is not counted, so adding 1 business day to a Friday gives the following Monday (if it is open). Negative values go backwards.

ParameterDescription
calendar requiredCalendar id, or up to 10 comma-separated ids for a joint calendar (e.g. us-fed,eu-target2). Aliases such as nyse, ach, sepa, bacs are accepted.
date requiredYYYY-MM-DD
days requiredInteger between -2600 and 2600

curl "https://bankday.jacklehoff4866.workers.dev/v1/business-days/add?calendar=us-fed&date=2026-11-25&days=2" \
  -H "Authorization: Bearer $BANKDAY_KEY"
{
  "calendar": "us-fed",
  "date": "2026-11-25",
  "days": 2,
  "result": "2026-11-30",
  "result_status": { "date": "2026-11-30", "weekday": "Monday", "business_day": true, "closures": [] }
}

Count business days between two dates

GET/v1/business-days/count

Counts business days d with start < d ≤ end (the usual "how many business days until"). Pass include_start=true to count start ≤ d ≤ end. Returns a negative number when end is before start.

ParameterDescription
calendar requiredCalendar id, or up to 10 comma-separated ids for a joint calendar (e.g. us-fed,eu-target2). Aliases such as nyse, ach, sepa, bacs are accepted.
start requiredYYYY-MM-DD
end requiredYYYY-MM-DD
include_starttrue | false (default false)

curl "https://bankday.jacklehoff4866.workers.dev/v1/business-days/count?calendar=gb&start=2026-12-18&end=2027-01-08" \
  -H "Authorization: Bearer $BANKDAY_KEY"

Next (or previous) business day

GET/v1/business-days/next

The first business day strictly after date (default: today in the calendar's time zone). Use inclusive=true to return the date itself when it is a business day. /v1/business-days/previous works the same way backwards.

ParameterDescription
calendar requiredCalendar id, or up to 10 comma-separated ids for a joint calendar (e.g. us-fed,eu-target2). Aliases such as nyse, ach, sepa, bacs are accepted.
dateYYYY-MM-DD (default today)
inclusivetrue | false (default false)

curl "https://bankday.jacklehoff4866.workers.dev/v1/business-days/next?calendar=eu-target2&date=2026-12-24" \
  -H "Authorization: Bearer $BANKDAY_KEY"

Adjust a date with a business-day convention

GET/v1/business-days/roll

Rolls a non-business date using ISDA-style conventions: following, preceding, modified_following (following, unless that crosses into the next month), modified_preceding. Business days are returned unchanged.

ParameterDescription
calendar requiredCalendar id, or up to 10 comma-separated ids for a joint calendar (e.g. us-fed,eu-target2). Aliases such as nyse, ach, sepa, bacs are accepted.
date requiredYYYY-MM-DD
conventionfollowing (default) | preceding | modified_following | modified_preceding

curl "https://bankday.jacklehoff4866.workers.dev/v1/business-days/roll?calendar=us-fed&date=2026-05-31&convention=modified_following" \
  -H "Authorization: Bearer $BANKDAY_KEY"

List business days in a range

GET/v1/business-days

All business days between start and end inclusive (max 2 years).

ParameterDescription
calendar requiredCalendar id, or up to 10 comma-separated ids for a joint calendar (e.g. us-fed,eu-target2). Aliases such as nyse, ach, sepa, bacs are accepted.
start requiredYYYY-MM-DD
end requiredYYYY-MM-DD

curl "https://bankday.jacklehoff4866.workers.dev/v1/business-days?calendar=jp&start=2026-12-25&end=2027-01-10" \
  -H "Authorization: Bearer $BANKDAY_KEY"

List holidays

GET/v1/holidays

Holidays for a year (default: current year) or a date range up to 10 years. For joint calendars every calendar's holidays are listed with a calendar field.

ParameterDescription
calendar requiredCalendar id, or up to 10 comma-separated ids for a joint calendar (e.g. us-fed,eu-target2). Aliases such as nyse, ach, sepa, bacs are accepted.
yeare.g. 2027
start / endYYYY-MM-DD range instead of year

curl "https://bankday.jacklehoff4866.workers.dev/v1/holidays?calendar=uk-bacs&year=2027" \
  -H "Authorization: Bearer $BANKDAY_KEY"

FX spot value date

GET/v1/fx/spot

Spot date for a currency pair traded on trade_date. T+2 by default, T+1 for USD/CAD, USD/TRY, USD/RUB, USD/PHP and USD/KZT. The intermediate day only needs to be a business day for the non-USD currency; the spot date must be a business day for both currencies and, for crosses such as EURGBP, also a USD business day. Currencies map to settlement calendars (USD → us-fed, EUR → eu-target2, GBP → uk-bacs, others → country).

ParameterDescription
pair requirede.g. EURUSD, EUR/USD
trade_date requiredYYYY-MM-DD

curl "https://bankday.jacklehoff4866.workers.dev/v1/fx/spot?pair=EURUSD&trade_date=2026-11-25" \
  -H "Authorization: Bearer $BANKDAY_KEY"
{
  "pair": "EURUSD",
  "trade_date": "2026-11-25",
  "spot_lag": 2,
  "spot_date": "2026-11-27",
  "calendars": { "EUR": "eu-target2", "USD": "us-fed" },
  "convention": "T+2 spot: ..."
}

US ACH settlement estimate

GET/v1/ach/settlement

Estimates when an ACH entry settles at the Federal Reserve, given when you submit it. Same Day ACH uses the three FedACH windows (submission deadlines 10:30 a.m., 2:45 p.m. and 4:45 p.m. ET; settlement 1:00, 5:00 and 6:00 p.m. ET) and the $1,000,000 per-payment limit. Standard ACH settles the next settlement day at 8:30 a.m. ET. Your bank's (ODFI's) cut-offs are earlier than the Fed's.

ParameterDescription
submitted_atISO 8601 timestamp with offset (default: now)
typestandard (default) | same_day
amountOptional, in USD; same-day entries over $1M fall back to standard

curl "https://bankday.jacklehoff4866.workers.dev/v1/ach/settlement?type=same_day&submitted_at=2026-10-09T17:10:00-04:00" \
  -H "Authorization: Bearer $BANKDAY_KEY"

List calendars

GET/v1/calendars

All calendars with metadata (type, weekend days, time zone, coverage years, source). Filter with type and q. GET /v1/calendars/{id} returns one calendar plus this year's holidays.

ParameterDescription
typerail | exchange | country
qSearch text

curl "https://bankday.jacklehoff4866.workers.dev/v1/calendars?type=rail" \
  -H "Authorization: Bearer $BANKDAY_KEY"

Your plan and usage

GET/v1/account

Plan, usage for the current month and usage history. Not counted toward your quota.

curl "https://bankday.jacklehoff4866.workers.dev/v1/account" \
  -H "Authorization: Bearer $BANKDAY_KEY"

Errors

Errors use standard HTTP status codes and a JSON body:

{ "error": { "code": "date_out_of_range", "message": "...", "supported_years": [2000, 2040] } }
StatusCodes
400missing_parameter, invalid_date, invalid_parameter, invalid_range
401missing_api_key, invalid_api_key
404unknown_calendar, not_found
422date_out_of_range, unsupported_currency
429quota_exceeded (Free plan only)

Quotas & response headers

Each response includes x-quota-limit, x-quota-used, x-quota-remaining, x-plan and x-request-id. Free accounts are blocked at the monthly limit; paid plans continue with overage billing. Responses are deterministic for past dates, so cache them freely.

MCP server for AI agents

Bankday exposes a remote Model Context Protocol server at https://bankday.jacklehoff4866.workers.dev/mcp (streamable HTTP). Tools: is_business_day, add_business_days, count_business_days, list_holidays, today_status, fx_spot_date, ach_settlement_date, search_calendars. Each tool call counts as one request.

{
  "mcpServers": {
    "bankday": {
      "type": "http",
      "url": "https://bankday.jacklehoff4866.workers.dev/mcp",
      "headers": { "Authorization": "Bearer bd_live_..." }
    }
  }
}

Claude Code: claude mcp add --transport http bankday https://bankday.jacklehoff4866.workers.dev/mcp --header "Authorization: Bearer bd_live_..."

Code samples

JavaScript / TypeScript

async function bankday(path, params) {
  const url = new URL("https://bankday.jacklehoff4866.workers.dev/v1/" + path);
  Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
  const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.BANKDAY_KEY}` } });
  if (!res.ok) throw new Error((await res.json()).error.message);
  return res.json();
}

const { result } = await bankday("business-days/add", { calendar: "us-fed", date: "2026-12-23", days: 3 });

Python

import os, requests

def bankday(path, **params):
    r = requests.get(f"https://bankday.jacklehoff4866.workers.dev/v1/{path}", params=params,
                     headers={"Authorization": f"Bearer {os.environ['BANKDAY_KEY']}"}, timeout=10)
    r.raise_for_status()
    return r.json()

print(bankday("business-day", calendar="xnys", date="2026-11-26")["business_day"])  # False

Go

req, _ := http.NewRequest("GET", "https://bankday.jacklehoff4866.workers.dev/v1/fx/spot?pair=EURUSD&trade_date=2026-11-25", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("BANKDAY_KEY"))
resp, err := http.DefaultClient.Do(req)

Google Sheets / Excel

=IMPORTDATA("https://bankday.jacklehoff4866.workers.dev/v1/business-days/add?calendar=us-fed&date=2026-12-23&days=3&api_key=YOUR_KEY")