Integration guide · Patent Pending

Custom Calendars

Your world probably does not run on Gregorian months. A ten-month year, a six-day week, a Founding-era epoch, an irregular leap cycle — the Spiral encoder treats all of these as a pure labelling layer over the same multi-scale coordinate. Pick a built-in projection, or define your own in-world calendar once and reference it on every /v1/spiral call. The phase math never changes; only the human-readable label does.

The calendar query param

Every /v1/spiral response is labelled by a calendar projection. Omit the field and you get gregorian, a pure pass-through. Pass ?calendar=<id> on the REST endpoint (or the calendar argument in an SDK) to relabel the same coordinate in another system. The projection only changes the meta.calendar label — your physics step and rung phases are byte-for-byte identical across calendars.

The shipped projections:

  • gregorianDefault. Pure label pass-through, no shape change.
  • holoceneHuman Era — re-numbers the year (HE = Gregorian + 10,000).
  • cosmologicalBig-Bang-anchored deep time; accepts gyr / yrBP shorthand.
  • stardateContinuous fractional stardate count.
  • julianJulian Day Number (continuous day count).
  • unix-dayFractional days since the Unix epoch.
  • mjdModified Julian Day (JDN − 2,400,000.5).
  • ut1Earth-rotation time (UT1).
  • gmstGreenwich Mean Sidereal Time.
  • lmstLocal Mean Sidereal Time.
  • j2000Julian centuries since the J2000.0 epoch.

The astronomical projections (ut1, gmst, lmst, j2000) and the deep-time cosmological shorthand are Standard or higher. The registry lives at lib/temporalspiral/src/calendars/; adding a projection there ships it everywhere the encoder runs.

Define your own world calendar

When none of the built-ins match your world, register a custom calendar as data. A definition is a small JSON document scoped to your API key (Standard or higher), created with POST /v1/calendars. Once stored, reference it as calendar=custom:<id> on any spiral call.

# Define a 10-month, 300-day world calendar with a leap cycle.
# Standard+ tier. The definition is scoped to this API key.

curl -s -X POST "https://api.temporalblock.com/v1/calendars" \
  -H "X-API-Key: tblk_live_yourkeyhere" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "eldoria",
    "yearDays": 300,
    "monthCount": 10,
    "monthNames": [
      "Frostwane","Seedfall","Greentide","Highsun","Embermonth",
      "Goldharvest","Mistreach","Duskfall","Longnight","Yearturn"
    ],
    "weekDays": 6,
    "weekNames": ["Sunday","Moonday","Forgeday","Tideday","Vineday","Restday"],
    "eraNames": ["Before Founding","After Founding"],
    "epochUtcMs": 0,
    "leapCycleDays": 1501
  }'

CRUD lives under /v1/calendars: POST to create or replace, GET to list ({ count, items }) or read one by id, and DELETE /v1/calendars/:id to remove it. Posting the same id again replaces the definition in place.

Definition fields

FieldRequiredMeaning
idyesSlug you reference as calendar=custom:<id>. Matches /^[a-z0-9][a-z0-9_-]{0,63}$/i.
yearDaysyesWhole days in a standard (non-leap) year. 1–10,000,000.
monthCountyesNumber of months the year is divided into. 1–1000. Days are split as evenly as possible; the first (yearLength mod monthCount) months get one extra day.
monthNamesnoOptional month names; length must equal monthCount. Falls back to “Month <n>”.
weekDaysyesLength of the weekday cycle. The epoch day is weekday index 0; the cycle runs continuously from there.
weekNamesnoOptional weekday names; length must equal weekDays. Falls back to “Day <n>”.
eraNamesnoOptional eras. [0] labels years before the epoch; the last entry labels years on/after it (a single entry applies to both). 1–8 entries.
epochUtcMsnoUTC epoch-ms of this calendar's day 0 (year 1, month 1, day 1). Default 0 = the Unix epoch.
leapCycleDaysnoTotal days in one repeating leap cycle (e.g. Earth's Julian cycle = 4×365 + 1 = 1461). The surplus over whole years is distributed as one leap day onto the last years of the cycle. Must be ≥ yearDays.

The label math is fully deterministic and documented in lib/temporalspiral/src/calendars/customCalendar.ts: the same instant always projects to the same year / era / month / day / weekday, so replays and lock-step multiplayer stay reproducible.

Use it on a spiral call

Pass calendar=custom:<id> and the response meta.calendar block comes back in your system — including display, year, era, monthName, dayOfMonth, dayOfYear, and weekdayName. Drive your in-world clock, season banner, and date UI directly from those fields.

# Relabel any spiral coordinate in your world calendar.
# The spiral PHASE math is unchanged — only the calendar label is
# reinterpreted into your year / era / month / day / weekday.

curl -s "https://api.temporalblock.com/v1/spiral?calendar=custom:eldoria&atUtcMs=1750000000000" \
  -H "X-API-Key: tblk_live_yourkeyhere"

# meta.calendar carries the in-world label, e.g.
#   { "display": "Highsun 12, Year 56 After Founding",
#     "year": 56, "era": "After Founding",
#     "month": 4, "monthName": "Highsun",
#     "dayOfMonth": 12, "dayOfYear": 102,
#     "weekday": 3, "weekdayName": "Tideday" }
Need an API key?

Custom calendars require a Standard or higher key. The default gregorian, holocene, and stardate projections are available on every tier. Get a key at temporalblock.com.

Related

Temporal Spiral is patent pending — U.S. Provisional Application No. 64/065,213 (filed 2026-05-14).