openapi: 3.0.0 info: title: 'Events API — Islamic Network' description: 'What happened / what is observed on the days of the Islamic calendar — consumed by pray.islamic.network (day pages), aladhan.com (holy-day features) and third parties. Every response is wrapped in the `{code, status, data}` envelope shared across Islamic Network APIs; list endpoints add a `meta` sibling. Language keys are BCP 47 tags (`ar`, `en`, `ur`, …, and `ar-Latn` for transliteration); empty values are omitted entirely. Lists summarize, item endpoints expand.' contact: url: 'https://islamic.network' email: hello@islamic.network version: 1.0.0 servers: - url: 'https://events.api.islamic.network/v1' description: Production paths: '/calendar/{month}': get: tags: - calendar summary: 'Events observed in a Hijri month' operationId: getMonth parameters: - $ref: '#/components/parameters/month' responses: '200': description: 'The month and its events, each with its date.' content: application/json: schema: allOf: - { $ref: '#/components/schemas/Envelope' } - { properties: { data: { $ref: '#/components/schemas/CalendarMonth' } }, type: object } '404': $ref: '#/components/responses/Error' '/calendar/{month}/{day}': get: tags: - calendar summary: 'Events observed on a Hijri day' description: "The integration endpoint pray and AlAdhan call. links.day points at the pray API's record for this day when it has one." operationId: getDay parameters: - $ref: '#/components/parameters/month' - $ref: '#/components/parameters/day' responses: '200': description: "The day's events (possibly none)." content: application/json: schema: allOf: - { $ref: '#/components/schemas/Envelope' } - { properties: { data: { $ref: '#/components/schemas/CalendarDay' } }, type: object } '404': $ref: '#/components/responses/Error' /calendar/today: get: tags: - calendar summary: "Resolve a Gregorian date to its Hijri day's events" description: 'Gregorian date → Hijri date (AlAdhan, HJCoSA calendar method) → the events observed that day. Defaults to the server date (UTC).' operationId: getToday parameters: - name: date in: query description: 'Gregorian date as DD-MM-YYYY; defaults to today.' schema: type: string pattern: '^\d{2}-\d{2}-\d{4}$' example: 25-06-2026 responses: '200': description: 'The resolved date, its month, its events and the next upcoming event.' content: application/json: schema: allOf: - { $ref: '#/components/schemas/Envelope' } - { properties: { data: { $ref: '#/components/schemas/Today' } }, type: object } '400': $ref: '#/components/responses/Error' '/documentation/openapi/{format}': get: tags: - documentation summary: 'This specification, as OpenAPI 3' operationId: getOpenApiSpec parameters: - name: format in: path required: true schema: type: string enum: - yaml - json responses: '200': description: 'The OpenAPI document.' /events: get: tags: - events summary: 'All events (summaries) in calendar order' description: 'Events without `year` are timeless anniversaries; full records live at /events/{slug}.' operationId: listEvents parameters: - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/limit' responses: '200': description: 'Paginated event summaries.' content: application/json: schema: allOf: - { $ref: '#/components/schemas/Envelope' } - { properties: { meta: { $ref: '#/components/schemas/Meta' }, data: { type: array, items: { $ref: '#/components/schemas/EventSummary' } } }, type: object } '/events/{slug}': get: tags: - events summary: 'Full event' description: 'Title, observed date, historical year, description, the people involved (shared registry slugs) and cross-links into sibling APIs.' operationId: getEvent parameters: - $ref: '#/components/parameters/slug' responses: '200': description: 'The event, expanded.' content: application/json: schema: allOf: - { $ref: '#/components/schemas/Envelope' } - { properties: { data: { $ref: '#/components/schemas/EventDetail' } }, type: object } '404': $ref: '#/components/responses/Error' /people: get: tags: - people summary: 'People referenced by events' description: 'Person slugs are the ecosystem-wide identifiers owned by the People API; `registry` points at the canonical record there.' operationId: listPeople parameters: - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/limit' responses: '200': description: 'Paginated referenced-person summaries, slug order.' content: application/json: schema: allOf: - { $ref: '#/components/schemas/Envelope' } - { properties: { meta: { $ref: '#/components/schemas/Meta' }, data: { type: array, items: { $ref: '#/components/schemas/PersonSummary' } } }, type: object } '/people/{slug}/events': get: tags: - people summary: 'Events involving a person' operationId: getPersonEvents parameters: - $ref: '#/components/parameters/slug' - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/limit' responses: '200': description: 'The person and their events, calendar order.' content: application/json: schema: allOf: - { $ref: '#/components/schemas/Envelope' } - { properties: { meta: { $ref: '#/components/schemas/Meta' }, data: { properties: { person: { $ref: '#/components/schemas/PersonHeader' }, events: { type: array, items: { $ref: '#/components/schemas/EventSummary' } } }, type: object } }, type: object } '404': $ref: '#/components/responses/Error' /search: get: tags: - search summary: 'Diacritic-folded search across events' description: 'Matching is diacritic-folded (Ṣ→s, ā→a, ʿ/ʾ dropped, Arabic tashkīl stripped) across every language key of titles, descriptions and sources — `karbala`, `Karbalāʾ` and `كَرْبَلَاء` all match. Multiple query words AND together.' operationId: search parameters: - name: q in: query description: 'The query; at least 2 characters.' required: true schema: type: string example: karbala minLength: 2 - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/limit' responses: '200': description: 'Matching events as summaries with the field paths that matched.' content: application/json: schema: allOf: - { $ref: '#/components/schemas/Envelope' } - { properties: { meta: { $ref: '#/components/schemas/Meta' }, data: { properties: { query: { type: string }, total: { type: integer }, results: { type: array, items: { $ref: '#/components/schemas/SearchResult' } } }, type: object } }, type: object } '400': $ref: '#/components/responses/Error' components: schemas: Name: description: 'Language-keyed text. Keys are BCP 47 tags; `ar-Latn` is the transliteration. Only non-empty languages appear.' type: object example: ar: 'مَوْلِدُ النَّبِيِّ ﷺ' ar-Latn: 'Mawlid al-Nabī ﷺ' en: 'The birth of the Prophet Muhammad ﷺ' additionalProperties: type: string Prose: description: 'Language-keyed prose. `raw` is the authored Markdown; `html` is rendered from it (Arabic-script runs wrapped in ``).' type: object additionalProperties: required: - raw - html properties: raw: description: "OpenAPI document root and shared components. Endpoint annotations live on\nthe v1 controllers; the assembled spec is served by\nGET /v1/documentation/openapi/{yaml|json}." type: string html: type: string type: object EventDate: description: 'The Hijri anniversary an event is observed on — the calendar key. Day-of-month anniversaries, not specific dates.' required: - month - day properties: month: type: integer maximum: 12 minimum: 1 day: type: integer maximum: 30 minimum: 1 type: object Year: description: 'When the event actually happened. Present only for historical events; either calendar may be absent (pre-Hijra events have only `gregorian`).' properties: hijri: type: integer example: 61 gregorian: type: integer example: 680 type: object MonthRef: description: 'A Hijri month reference on calendar responses.' required: - number - name properties: number: type: integer maximum: 12 minimum: 1 name: $ref: '#/components/schemas/Name' type: object PersonRef: description: 'A person involved in an event. The slug is the ecosystem-wide identifier owned by the People API; `url` points into that registry.' required: - slug - name - url properties: slug: type: string example: husayn-ibn-ali name: $ref: '#/components/schemas/Name' url: type: string type: object Links: description: 'Cross-links into sibling APIs, present only when there is somewhere to point.' properties: day: description: "The pray API's day record for the observed date." type: string example: 'https://pray.api.islamic.network/v1/calendar/1/10' type: object Meta: description: 'Pagination block, sibling of `data` on list endpoints.' required: - total - page - limit - pages properties: total: type: integer page: type: integer limit: type: integer pages: type: integer type: object Envelope: required: - code - status properties: code: type: integer example: 200 status: type: string example: OK type: object EventSummary: required: - slug - title - date - url properties: slug: type: string example: martyrdom-of-husayn title: $ref: '#/components/schemas/Name' date: $ref: '#/components/schemas/EventDate' year: $ref: '#/components/schemas/Year' url: type: string type: object EventDetail: required: - id - slug - url - title - date properties: id: type: string slug: type: string url: type: string title: $ref: '#/components/schemas/Name' date: $ref: '#/components/schemas/EventDate' year: $ref: '#/components/schemas/Year' description: $ref: '#/components/schemas/Prose' people: type: array items: $ref: '#/components/schemas/PersonRef' source: type: string example: 'Fazilet Calendar' links: $ref: '#/components/schemas/Links' type: object CalendarEvent: description: 'An event as listed on the calendar endpoints: year/people when present. The day view omits `date` (it is the path); the month view carries it.' required: - slug - title - url properties: slug: type: string title: $ref: '#/components/schemas/Name' date: $ref: '#/components/schemas/EventDate' year: $ref: '#/components/schemas/Year' people: type: array items: $ref: '#/components/schemas/PersonRef' url: type: string type: object CalendarMonth: required: - month - events properties: month: $ref: '#/components/schemas/MonthRef' events: type: array items: $ref: '#/components/schemas/CalendarEvent' type: object CalendarDay: required: - date - month - events properties: date: $ref: '#/components/schemas/EventDate' month: $ref: '#/components/schemas/MonthRef' events: type: array items: $ref: '#/components/schemas/CalendarEvent' links: $ref: '#/components/schemas/Links' type: object Today: required: - date - month - events - next properties: date: properties: gregorian: type: string format: date example: '2026-06-25' hijri: properties: year: type: integer example: 1448 month: type: integer example: 1 day: type: integer example: 10 type: object type: object month: oneOf: - $ref: '#/components/schemas/MonthRef' nullable: true events: type: array items: $ref: '#/components/schemas/CalendarEvent' links: $ref: '#/components/schemas/Links' next: oneOf: - $ref: '#/components/schemas/EventSummary' nullable: true description: 'The next upcoming event, wrapping across the year.' type: object PersonSummary: required: - slug - name - events - url - registry properties: slug: type: string name: $ref: '#/components/schemas/Name' events: description: 'How many events involve this person.' type: integer url: description: "This API's event list for the person." type: string registry: description: 'The canonical person record on the People API.' type: string type: object PersonHeader: required: - slug - name - registry properties: slug: type: string name: $ref: '#/components/schemas/Name' registry: type: string type: object SearchResult: required: - type - matched_in - id - slug - title - date - url properties: type: type: string enum: - event matched_in: description: 'Language-keyed field paths that matched, e.g. `title.ar-Latn`.' type: array items: type: string id: type: string slug: type: string title: $ref: '#/components/schemas/Name' date: $ref: '#/components/schemas/EventDate' year: $ref: '#/components/schemas/Year' url: type: string type: object responses: Error: description: 'Error — the envelope with a message string as `data`.' content: application/json: schema: required: - code - status - data properties: code: type: integer example: 404 status: type: string example: 'NOT FOUND' data: type: string example: 'Event not found.' type: object parameters: page: name: page in: query description: 'Page number (default 1).' schema: type: integer default: 1 minimum: 1 limit: name: limit in: query description: 'Records per page (default 50, max 200).' schema: type: integer default: 50 maximum: 200 minimum: 1 month: name: month in: path description: 'Hijri month number.' required: true schema: type: integer maximum: 12 minimum: 1 day: name: day in: path description: 'Hijri day of month.' required: true schema: type: integer maximum: 30 minimum: 1 slug: name: slug in: path description: "The record's canonical URL key." required: true schema: type: string tags: - name: events description: 'The events themselves' - name: calendar description: 'Events by Hijri date' - name: people description: 'People referenced by events (shared registry slugs)' - name: search description: 'Diacritic-folded search' - name: documentation description: 'This specification'