Free APIs — liturgical calendar
Every API on this page is free, without a key, without an account, with open CORS: callable from a browser, a server or a mobile app. Responses are CDN-cached for one hour.
credits field: please display the source next to each ordo’s texts.Base URL
https://categpt.chat
The feast of the day — GET /api/v1/feast
Returns the full liturgical day: both forms of the rite, their texts and the biblical reference of every text. Days close to today are generated on the fly when missing.
| Parameter | Type | Required | Description |
|---|---|---|---|
date | string | no | Day as YYYY-MM-DD (default: today, UTC). |
locale | string | no | fr (default), en, de, it, es, pt, pl. |
curl "https://categpt.chat/api/v1/feast?locale=en"
/api/v1/feastAusprobierenThe feast of the day — both ordos, their texts and their biblical references.
curl "https://categpt.chat/api/v1/feast?date=2026-07-29&locale=fr"
At the top level, only date and sameFeast — plus credits (the
sources). Everything else lives in nom and vom, which carry exactly
the same keys:
{
"date": "2026-07-25",
"sameFeast": false,
"nom": {
"name": "St Mary Magdalene",
"rank": "Feast",
"rawRank": "Fête",
"latinName": null,
"color": "blanc",
"line": "Saturday, week 16 in Ordinary Time — Year II",
"commemorations": [],
"commemorationLine": null,
"description": "…Markdown description…",
"excerpt": "…two-sentence summary…",
"permalink": "https://app.categpt.chat/en/saint/july-25-2026-st-mary-magdalene",
"slug": "july-25-2026-st-mary-magdalene",
"questions": ["…", "…", "…"],
"mass": [
{ "key": "first_reading", "label": "First reading", "ref": "Ct 3, 1-4a", "text": "<p>…</p>", "source": { "language": "fr", "label": "Première lecture", "ref": "Ct 3, 1-4a", "text": "<p>…</p>" } },
{ "key": "second_reading", "label": "Second reading", "ref": "1 Co 13, 1-13", "text": "<p>…</p>", "source": { "language": "fr", "label": "Deuxième lecture", "ref": "1 Co 13, 1-13", "text": "<p>…</p>" } },
{ "key": "gospel", "label": "Gospel", "ref": "Jn 20, 1-2.11-18", "text": "<p>…</p>", "source": { "language": "fr", "label": "Évangile", "ref": "Jn 20, 1-2.11-18", "text": "<p>…</p>" } }
],
"offices": {
"lauds": [
{ "key": "hymn", "label": "Hymne", "ref": null, "text": "<p>…</p>", "source": null },
{ "key": "short_reading", "label": "Parole de Dieu", "ref": "Rm 8, 26-27", "text": "<p>…</p>", "source": null }
],
"vespers": [ { "key": "short_reading", "label": "Parole de Dieu", "ref": "…", "text": "<p>…</p>", "source": null } ]
},
"localPropers": [ { "zone": "france", "name": "Sts Martha, Mary and Lazarus" } ],
"localPropersLine": "France: Sts Martha, Mary and Lazarus"
},
"vom": {
"name": "St Christopher, Martyr",
"rank": "3rd class",
"rawRank": "III. classis",
"latinName": "S. Christophori Martyris",
"color": "rouge",
"line": "Saturday after the 8th Sunday after Pentecost",
"commemorations": ["St Christopher, Martyr"],
"commemorationLine": "Commemoration of St Christopher, Martyr",
"description": "…description of the Vetus Ordo feast itself…",
"excerpt": "…two-sentence summary…",
"permalink": "https://app.categpt.chat/en/saint/july-25-2026-st-christopher-martyr",
"slug": "july-25-2026-st-christopher-martyr",
"questions": ["…", "…", "…"],
"mass": [
{ "key": "introit", "label": "Introit", "ref": "Ps 138:17", "text": "<p>…</p>", "source": { "language": "la", "label": "Introitus", "ref": "Ps 138:17", "text": "<p>…</p>" } },
{ "key": "collect", "label": "Collect", "ref": null, "text": "<p>…</p>", "source": { "language": "la", "label": "Oratio", "ref": null, "text": "<p>…</p>" } },
{ "key": "communion", "label": "Communion", "ref": "Ps 33:9", "text": "<p>…</p>", "source": { "language": "la", "label": "Communio", "ref": "Ps 33:9", "text": "<p>…</p>" } }
],
"offices": {
"sext": [
{ "key": "short_reading", "label": "Little Chapter", "ref": "Gal 6:2", "text": "<p>…</p>", "source": { "language": "la", "label": "Capitulum Responsorium Versus", "ref": "Gal 6:2", "text": "<p>…</p>" } },
{ "key": "collect", "label": "Collect", "ref": null, "text": "<p>…</p>", "source": { "language": "la", "label": "Oratio", "ref": null, "text": "<p>…</p>" } }
]
},
"localPropers": [],
"localPropersLine": null
},
"credits": {
"nom": { "source": "AELF", "url": "https://www.aelf.org" },
"vom": { "source": "Divinum Officium", "url": "https://www.divinumofficium.com/" }
}
}
Strict NOM / VOM equality
nom carries the celebration of the current Roman calendar (Novus Ordo,
AELF texts), vom the one of the Vetus Ordo Missae (1962 calendar,
Divinum Officium texts). Both blocks have
the same key set — no field exists on one side only:
| Key | Description |
|---|---|
name | Localized feast name of this ordo. |
rank | Localized rank: AELF degree (“Feast”, “Optional memorial”) on the NOM side, class (“3rd class”) on the VOM side. |
rawRank | The same rank exactly as the source prints it (Mémoire facultative, III. classis). |
latinName | Latin title of the celebration (Divinum Officium). null on the NOM side: AELF publishes none. |
color | Liturgical colour: blanc, rouge, vert, violet, rose, noir. |
line | The day’s position in this calendar: week line (NOM), temporal line (VOM). On the NOM side it also carries the reading cycle AELF publishes, joined the way AELF joins it ("Wednesday, week 17 in Ordinary Time — Year II"). When the celebration is that position — a Sunday, a feria whose title already says it — the position is dropped and the cycle stays alone ("Year A"). null when nothing remains: no position to state and no cycle published — always so on the VOM side, which has no reading cycle. |
commemorations | Commemorations of the day in this calendar, in the order its ordo prints them (["The Holy Maccabees, Martyrs"]). The current Roman calendar publishes none, so the list is always empty on the NOM side — the key exists on both sides, like latinName. |
commemorationLine | The same commemorations as one ready-to-display sentence ("Commemoration of St Christopher, Martyr"). null when the ordo commemorates nothing — so always on the NOM side. |
description / excerpt | Description and summary of this ordo’s feast. |
permalink | Absolute URL of the permanent page of this feast — always present, one per ordo. |
slug | The permalink slug alone. |
questions | Suggested questions about this ordo’s feast. |
mass | Texts of the mass (see below). |
offices | Texts of the offices, per hour (see below). |
localPropers | Local propers: only the zones whose celebration differs from this ordo's universal calendar: [{ "zone": "france", "name": "…" }]. This is the exact counterpart of the VOM commemorations — an indication under the feast, never the feast itself — and the list is empty on the VOM side, whose Calendarium Generale publishes none. |
localPropersLine | The same propers as one ready-to-display sentence, zones grouped by wording: "France, Luxembourg: St Henry and St Cunegonde". null when every place celebrates what the universal calendar already announces. |
sameFeast is true when both calendars celebrate the same feast that
day, false when they differ, null when the day has no VOM data —
vom is then null.
It is information, never a conditional to write: description,
excerpt and questions always belong to their own block's ordo, whatever
its value. A block whose text has not been produced yet carries null — it
never borrows the other ordo's. Two different feasts give two different
permalinks. Returns 404 (not_found) when no data exists for that day.
Liturgical texts and biblical references
mass and each hour of offices are lists of identical objects on
both ordos:
| Field | Description |
|---|---|
key | Stable machine key, identical across days, languages and years. |
label | Readable heading, in the requested language. For the Novus Ordo mass readings it names the part of the mass — “First reading”, “Psalm”, “Gospel” — and not the sentence AELF puts in exergue; that sentence is only the fallback when no rule recognises the reading. |
ref | Biblical reference of the text (Ps 118:89, 1 Co 13, 1-13), or null when the source prints none. |
text | The text, as the HTML fragment published by the source. |
source | The same text in its source language, with its own label and its own reference, when text is a translation of it: `{ "language": "la" |
One vocabulary, in English, for both ordos
Every key is English, and the two ordos share a key whenever they mean the
same thing. That is what makes the two blocks interchangeable: swapping
vom for nom in a path gives the same result, for everything the two
calendars have in common.
Hours — matins, lauds, prime, terce, sext, none,
vespers, compline. Each ordo serves only the ones it has: the Novus
Ordo has no prime, and its office of readings is matins.
Mass — shared: epistle, gospel, sequence, psalm,
canticle, reading. Novus Ordo only: first_reading,
second_reading, third_reading, gospel_acclamation. Vetus Ordo
only: introit, collect, gradual, alleluia, tract,
offertory, secret, communion, postcommunion,
commemoration.
The mass decides what its readings are called: a mass with a single
reading before the gospel — the ordinary weekday — serves it as reading,
"Reading", not as first_reading; first_reading and second_reading
come as a pair, as they do in the missal. And the short form of the
gospel, which AELF publishes on some Sundays alongside the full text, is not
served: the mass holds the full gospel only.
Offices — shared: hymn, antiphon, psalm, short_reading
(AELF's "péricope" and Divinum Officium's "capitulum" are the same object),
responsory, versicle, collect, reading, te_deum. Novus Ordo
only: introduction, patristic_reading, patristic_responsory,
psalm_versicle, intercession, our_father, blessing,
invitatory_antiphon, invitatory_psalm, benedictus,
magnificat, nunc_dimittis and their antiphons. Vetus Ordo only:
lesson_1…lesson_9, the Matins lessons.
Numbered parts keep their number (psalm_2, antiphon_3), and a key
repeated inside the same list is suffixed _2, _3…
Zone codes (france, belgique…) are values published by AELF,
not keys: they are served as-is, so they stay comparable with the source.
Everything is therefore retrieved by key, without knowing anything about the sources’ formats:
const day = await fetch(`https://categpt.chat/api/v1/feast?date=2026-07-25`).then(r => r.json());
// The reference of the little chapter of Sext in the Vetus Ordo → "Gal 6:2"
day.vom.offices.sext.find(t => t.key === 'short_reading').ref;
// The 2nd reading of a Novus Ordo Sunday → "1 Co 13, 1-13"
day.nom.mass.find(t => t.key === 'second_reading').ref;
// The communion antiphon of a Vetus Ordo day → "Ps 33:9"
day.vom.mass.find(t => t.key === 'communion').ref;
Novus Ordo references come from AELF’s own ref field; Vetus Ordo ones are
parsed out of the text itself (Divinum Officium prints them as a rubric,
on their own line or at the end of a reading incipit) using a list of Latin
and vernacular book abbreviations — ref is null when no reference is
recognised.
description, excerpt, name, rank, line, commemorations and the labels
come back in the requested locale (French fallback, then Latin on the VOM
side). Novus Ordo mass texts are translated when locale ≠ fr; Novus
Ordo offices stay in French (official AELF text). credits gives the source
to display next to each ordo’s texts.
The liturgical day — GET /api/liturgical/{date}
The same payload as /api/v1/feast, plus prev / next
navigation — this is the API the site itself consumes for its daily pages.
| Parameter | Type | Required | Description |
|---|---|---|---|
date | string (path) | yes | Day as YYYY-MM-DD. |
locale | string | no | fr (default), en, de, it, es, pt, pl. |
curl "https://categpt.chat/api/liturgical/2026-07-29?locale=en"
/api/liturgical/{date}AusprobierenThe same full day, plus prev / next navigation.
curl "https://categpt.chat/api/liturgical/2026-07-29?locale=fr"
prev and next are null when the adjacent day is not stored yet;
otherwise:
| Key | Description |
|---|---|
date | The adjacent day, YYYY-MM-DD. |
slug | Permalink slug of its permanent page (Novus Ordo). |
vomSlug | Its Vetus Ordo page slug — present only when that day's two ordos celebrate different feasts, null otherwise. |
The calendar — GET /api/liturgical/calendar
One month of entries ready to list — what the liturgical calendar page shows. Read-only: a day missing from the database simply yields one entry fewer.
| Parameter | Type | Required | Description |
|---|---|---|---|
month | string | yes | Month as YYYY-MM. |
locale | string | no | fr (default), en, de, it, es, pt, pl. |
curl "https://categpt.chat/api/liturgical/calendar?month=2026-07&locale=en"
/api/liturgical/calendarAusprobierenOne month of liturgical-calendar entries, ready to list.
curl "https://categpt.chat/api/liturgical/calendar?month=2026-07&locale=fr"
Each entry of entries:
| Key | Description |
|---|---|
date | Day YYYY-MM-DD. |
slug | Permalink slug of the day's page. |
name | Localized feast name (Novus Ordo). |
degreeKey / degree | Degree: a stable key when known (feast, memorial…), the raw AELF label otherwise. |
color | Liturgical colour ("" when AELF publishes none). |
vomName / vomSlug / vomColor | The day's Vetus Ordo feast, its permalink and its colour — as soon as the day has VOM data, a shared saint included (the two calendars title it differently). |
vomClass / vomRank | Class 1–4 when the rank is class-based, the raw Divinum Officium rank otherwise. |
sameFeast | true / false / null — same semantics as on the full day. |
vomCommemoration | The day's Vetus Ordo commemoration, as one sentence. null when the ordo commemorates nothing. |
nomLocalPropers | The local propers that differ from the universal calendar, grouped by wording: [{ "zones": ["france"], "name": "…" }]. null when every place follows the universal calendar. |
The card of the day — GET /api/liturgical/card/{date}
A 1080 × 1080 JPEG of the day (feast name, liturgical colour), freely embeddable — the visual of the project's daily posts. Stored days only.
<img src="https://categpt.chat/api/liturgical/card/2026-07-29" alt="Feast of the day" width="540">
/api/liturgical/card/{date}AusprobierenThe card of the day — a freely embeddable 1080 × 1080 JPEG.
curl "https://categpt.chat/api/liturgical/card/2026-07-29"
The RSS feeds — GET /api/feed/feast-of-the-day
Two RSS 2.0 feeds of the saint of the day (French), one per form of the rite: the last 30 days, each item linking to its permanent page, with the name, link and excerpt of its own ordo.
| Parameter | Type | Required | Description |
|---|---|---|---|
ordo | string | no | nom (Novus Ordo, default) or vom (Vetus Ordo Missae, 1962 calendar). |
https://categpt.chat/api/feed/feast-of-the-day
https://categpt.chat/api/feed/feast-of-the-day?ordo=vom
Both feeds are advertised in the <head> of every public page
(<link rel="alternate" type="application/rss+xml">): an RSS reader pointed
at categpt.chat discovers them by itself.
/api/feed/feast-of-the-dayAusprobierenRSS 2.0 feed of the saint of the day (French, last 30 days) — one feed per ordo.
curl "https://categpt.chat/api/feed/feast-of-the-day?ordo=nom"
Errors
The /api/v1/* endpoints answer { "error": { "code": "…" } }; the
/api/liturgical/* endpoints answer { "error": "…" }:
| HTTP code | Error code | Meaning |
|---|---|---|
| 400 | invalid_date / invalid_month | Malformed parameter. |
| 404 | not_found | No data for that day. |
| 500 | internal_error | Internal error. |
OpenAPI specification
The whole API — free and keyed — is described by an OpenAPI 3.1 specification generated from the same source as this page:
https://categpt.chat/api/openapi
Import it into Postman, Insomnia or a client generator to get typed requests and schemas.