Name Days & Calendar API

Finnish name days, holidays, flag days and notable days via an authenticated, Typesense-compatible API

Overview

The Name Days API provides a secure proxy to Typesense search functionality, allowing authenticated applications to search through a comprehensive database of Finnish, Swedish, Sámi, Orthodox, and even pet name days. All requests are authenticated using API tokens, logged for analytics, and rate-limited per organization.

Base URL: https://nimipaivarajapinta.fi/api/typesense/collections/namedays/documents/search

Authentication

All API requests require authentication using an organization-specific API token.

API Token Authentication

API tokens are unique identifiers that start with ndt_ and are tied to specific organizations. Include your API token in the Authorization header:

Authorization: Bearer ndt_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0...
Important:
  • API tokens must be active (not inactive or expired)
  • The associated organization must be active
  • Expired tokens will return a 401 error
  • Keep your API tokens secure and never expose them in client-side code
Getting an API Token: Contact your system administrator to obtain an API token for your organization. Tokens can be configured with optional expiration dates for enhanced security.

Today's Name Days Endpoint

Get all name days for the current date without needing to specify any parameters. This endpoint automatically fetches today's names and groups them by type.

GET Auth Required
/api/namedays/today

Request

No parameters required - the endpoint automatically uses the current date.

Example Request

curl -X GET https://nimipaivarajapinta.fi/api/namedays/today \
  -H "Authorization: Bearer ndt_your_api_token_here"

Response Format

{
  "success": true,
  "date": {
    "day": 10,
    "month": 9,
    "year": 2025,
    "formatted": "10.9.2025"
  },
  "total_count": 7,
  "name_days": [
    {
      "id": "123",
      "name": "Sinikka",
      "type": "suomi",
      "gender": "nainen",
      "day": 10,
      "month": 9
    },
    {
      "id": "124",
      "name": "Sini",
      "type": "suomi",
      "gender": "nainen",
      "day": 10,
      "month": 9
    },
    {
      "id": "125",
      "name": "Erik",
      "type": "ruotsi",
      "gender": "mies",
      "day": 10,
      "month": 9
    }
  ],
  "name_days_by_type": {
    "suomi": [
      {"id": "123", "name": "Sinikka", "type": "suomi", "gender": "nainen", "day": 10, "month": 9},
      {"id": "124", "name": "Sini", "type": "suomi", "gender": "nainen", "day": 10, "month": 9}
    ],
    "ruotsi": [
      {"id": "125", "name": "Erik", "type": "ruotsi", "gender": "mies", "day": 10, "month": 9}
    ]
  },
  "response_time_ms": 32,
  "_meta": {
    "authenticated_user": null,
    "organization_id": 5,
    "organization_name": "Example Org",
    "auth_type": "api_token",
    "timestamp": "2025-09-10T18:30:00Z"
  }
}
Use Case: Perfect for daily widgets, calendar applications, or any service that needs to display today's name days without complex date calculations.

Search Parameters

Request Parameters

Parameter Type Required Description Example
q string No Search query. Use * for all records "Maria"
query_by string No Field to search in "name"
filter_by string No Filter expressions "type:=suomi && gender:=nainen"
facet_by string No Fields to generate facets for "type,gender,month"
sort_by string No Sort order "month:asc,day:asc"
page integer No Page number (default: 1) 1
per_page integer No Results per page (max: 100) 50

Available Filter Fields

Field Type Possible Values
type string suomi, ruotsi, saame, ortod, koira, kissa, hevonen, historiallinen
gender string mies, nainen, ei_maaritelty
day integer 1-31
month integer 1-12

Examples

Get today's name days

curl -X GET https://nimipaivarajapinta.fi/api/namedays/today \
  -H "Authorization: Bearer ndt_your_api_token_here"

Search for all Finnish female names

curl -X POST https://nimipaivarajapinta.fi/api/typesense/collections/namedays/documents/search \
  -H "Authorization: Bearer ndt_your_api_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "filter_by": "type:=suomi && gender:=nainen",
    "per_page": 20,
    "sort_by": "month:asc,day:asc"
  }'

Search for names on Christmas Eve

curl -X POST https://nimipaivarajapinta.fi/api/typesense/collections/namedays/documents/search \
  -H "Authorization: Bearer ndt_your_api_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "filter_by": "day:=24 && month:=12",
    "sort_by": "name:asc"
  }'

Search for a specific name

curl -X GET "https://nimipaivarajapinta.fi/api/typesense/collections/namedays/documents/search?q=Maria&query_by=name" \
  -H "Authorization: Bearer ndt_your_api_token_here"

Get today's name days

const API_TOKEN = 'ndt_your_api_token_here';

async function getTodaysNameDays() {
  const response = await fetch('https://nimipaivarajapinta.fi/api/namedays/today', {
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`
    }
  });

  if (!response.ok) {
    throw new Error(`API Error: ${response.status}`);
  }

  return await response.json();
}

// Example usage
getTodaysNameDays()
  .then(data => {
    console.log(`Today is ${data.date.formatted}`);
    console.log(`${data.total_count} names celebrate today:`);
    
    // Display by type
    for (const [type, names] of Object.entries(data.name_days_by_type)) {
      console.log(`\n${type}:`);
      names.forEach(n => console.log(`  - ${n.name} (${n.gender})`));
    }
  })
  .catch(error => console.error('Failed to fetch today\'s names:', error));

Search with Fetch API

const API_TOKEN = 'ndt_your_api_token_here';
const API_URL = 'https://nimipaivarajapinta.fi/api/typesense/collections/namedays/documents/search';

async function searchNameDays(query, filters) {
  const response = await fetch(API_URL, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      q: query || '*',
      filter_by: filters,
      per_page: 50,
      sort_by: 'name:asc',
      facet_by: 'type,gender,month'
    })
  });

  if (!response.ok) {
    throw new Error(`API Error: ${response.status}`);
  }

  return await response.json();
}

// Example: Find all Swedish male names
searchNameDays('*', 'type:=ruotsi && gender:=mies')
  .then(results => {
    console.log(`Found ${results.found} Swedish male names`);
    results.hits.forEach(hit => {
      const doc = hit.document;
      console.log(`${doc.name} - ${doc.day}.${doc.month}`);
    });
  })
  .catch(error => console.error('Search failed:', error));

Get today's name days

import requests
from datetime import datetime

API_TOKEN = 'ndt_your_api_token_here'

def get_todays_name_days():
    headers = {
        'Authorization': f'Bearer {API_TOKEN}'
    }
    
    response = requests.get(
        'https://nimipaivarajapinta.fi/api/namedays/today',
        headers=headers
    )
    response.raise_for_status()
    return response.json()

# Example usage
today_data = get_todays_name_days()
print(f"Today is {today_data['date']['formatted']}")
print(f"Total names celebrating: {today_data['total_count']}")

# Display names by type
for name_type, names in today_data['name_days_by_type'].items():
    print(f"\n{name_type.capitalize()} names:")
    for name_info in names:
        print(f"  - {name_info['name']} ({name_info['gender']})")

Search with Python requests

import requests
import json

API_TOKEN = 'ndt_your_api_token_here'
API_URL = 'https://nimipaivarajapinta.fi/api/typesense/collections/namedays/documents/search'

def search_name_days(query='*', filters=None, page=1, per_page=50):
    headers = {
        'Authorization': f'Bearer {API_TOKEN}',
        'Content-Type': 'application/json'
    }
    
    payload = {
        'q': query,
        'query_by': 'name',
        'page': page,
        'per_page': per_page,
        'sort_by': 'name:asc',
        'facet_by': 'type,gender,month'
    }
    
    if filters:
        payload['filter_by'] = filters
    
    response = requests.post(API_URL, json=payload, headers=headers)
    response.raise_for_status()
    return response.json()

# Example 1: Find all Orthodox names
orthodox_names = search_name_days('*', 'type:=ortod')
print(f"Found {orthodox_names['found']} Orthodox names")

# Example 2: Find names for a specific date
july_names = search_name_days('*', 'day:=15 && month:=7')
for hit in july_names['hits']:
    doc = hit['document']
    print(f"{doc['name']} ({doc['type']}, {doc['gender']})")

# Example 3: Search with pagination
page = 1
while True:
    results = search_name_days('*', 'type:=koira', page=page, per_page=100)
    print(f"Page {page}: {len(results['hits'])} dog names")
    
    if page >= results.get('out_of', 1):
        break
    page += 1

Response Structure

Successful Response

{
  "found": 2847,
  "hits": [
    {
      "document": {
        "id": "123",
        "name": "Maria",
        "type": "suomi",
        "gender": "nainen",
        "day": 15,
        "month": 8,
        "created_at": "2024-01-15T10:30:00Z",
        "updated_at": "2024-01-15T10:30:00Z"
      },
      "highlight": {
        "name": {
          "snippet": "Maria"
        }
      }
    }
  ],
  "facet_counts": [
    {
      "field_name": "type",
      "counts": [
        {"value": "suomi", "count": 1250},
        {"value": "ruotsi", "count": 980}
      ]
    }
  ],
  "page": 1,
  "out_of": 285,
  "search_time_ms": 12,
  "_meta": {
    "response_time_ms": 45,
    "authenticated_user": null,
    "organization_id": 5,
    "organization_name": "Example Org",
    "auth_type": "api_token",
    "timestamp": "2024-01-15T12:30:00Z"
  }
}

Response Fields

Field Type Description
found integer Total number of matching documents
hits array Array of matching documents with highlights
facet_counts array Aggregated counts for faceted fields
page integer Current page number
out_of integer Total number of pages
search_time_ms integer Typesense search time in milliseconds
_meta object Additional metadata including auth info and timing

Error Handling

Common Error Responses

401 Unauthorized - Missing Token

{
  "statusCode": 401,
  "statusMessage": "Authentication required - provide JWT or API token"
}

Cause: No API token provided in the Authorization header

401 Unauthorized - Invalid Token

{
  "statusCode": 401,
  "statusMessage": "Invalid API token"
}

Cause: The provided API token does not exist in the system

401 Unauthorized - Token Expired

{
  "statusCode": 401,
  "statusMessage": "API token has expired"
}

Cause: The API token has passed its expiration date

401 Unauthorized - Token Inactive

{
  "statusCode": 401,
  "statusMessage": "API token is inactive"
}

Cause: The API token has been deactivated

401 Unauthorized - Organization Inactive

{
  "statusCode": 401,
  "statusMessage": "Organization is inactive"
}

Cause: The organization associated with the token is inactive

400 Bad Request

{
  "statusCode": 400,
  "statusMessage": "Invalid search parameters"
}

Cause: Malformed request body or invalid parameter values

500 Internal Server Error

{
  "statusCode": 500,
  "statusMessage": "Search proxy failed"
}

Cause: Server error or Typesense service unavailable

Best Practice: Always implement proper error handling and retry logic with exponential backoff for production applications. Monitor your API token expiration dates and renew them before they expire.

Calendar API

Beyond name days, the API also exposes Finnish calendar metadata: holidays, flag days and notable days. Each is stored in its own Typesense collection alongside the existing namedays collection. Authentication, analytics and per-organization usage tracking work identically to the name day endpoints.

Collections

Collection Contents Distinguishing fields
holidays Public holidays and church-calendar Sundays (juhla- ja pyhäpäivät) in_short_list (bool) — true for the curated short list, false for verbose liturgical entries
flag_days Finnish official and established flag days (liputuspäivät) flags (string[]) — codes for which flags fly, e.g. ["fi"] or ["fi","ax"]
notable_days Almanac notable / themed days (merkkipäivät) such as Ystävänpäivä, Aleksis Kivi None — date + bilingual name only

Common document fields

Every calendar document carries a full ISO date plus pre-derived helpers so you can filter by year, month or week without parsing the date string client-side:

Field Type Description
datestringYYYY-MM-DD
yearint32e.g. 2026
monthint32112
dayint32131
weekdayint320=Sunday, 6=Saturday
iso_weekint32ISO 8601 week number
name_fistringFinnish name
name_svstringSwedish name
Two surfaces, one auth model: Use the merged /api/calendar/search when you want one query that returns all three categories per date with locale-formatted display strings. Use the per-collection Typesense proxies when you want to use the official typesense-js / typesense-python / InstantSearch clients with full Typesense response shape.

Calendar Collection Endpoints

Three thin Typesense passthrough endpoints, one per collection. They mirror the existing /api/typesense/collections/namedays/documents/search proxy: same auth model, same per-organization analytics, and they preserve the standard Typesense response shape so the official client libraries work transparently.

POST Auth Required
/api/typesense/collections/holidays/documents/search
POST Auth Required
/api/typesense/collections/flag_days/documents/search
POST Auth Required
/api/typesense/collections/notable_days/documents/search

Request Body

Pass any standard Typesense SearchParameters as JSON. Typical fields:

Parameter Type Description
qstringFree-text query, or * for match-all
query_bystringComma-separated list of fields. Typically name_fi,name_sv
filter_bystringTypesense filter expression, e.g. year:=2026 && in_short_list:=true
sort_bystringdate:asc is supported (date is marked sortable)
per_pageintegerUp to 250

Example Request — short-list holidays in 2026

curl -X POST https://nimipaivarajapinta.fi/api/typesense/collections/holidays/documents/search \
  -H "Authorization: Bearer ndt_your_api_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "query_by": "name_fi,name_sv",
    "filter_by": "year:=2026 && in_short_list:=true",
    "sort_by": "date:asc",
    "per_page": 50
  }'

Example with typesense-js

import Typesense from 'typesense'

const client = new Typesense.Client({
  nodes: [{
    host: 'nimipaivarajapinta.fi',
    port: 443,
    protocol: 'https',
    path: '/api'
  }],
  apiKey: 'ndt_your_api_token_here',
  connectionTimeoutSeconds: 5
})

const result = await client
  .collections('holidays')
  .documents()
  .search({
    q: '*',
    query_by: 'name_fi,name_sv',
    filter_by: 'year:=2026 && in_short_list:=true',
    sort_by: 'date:asc',
    per_page: 50
  })

Filter Examples

Use case filter_by
February 2026, all entriesyear:=2026 && month:=2
Single datedate:=2026-02-14
ISO week 5 of 2026year:=2026 && iso_week:=5
Sundays only (weekday 0)weekday:=0
Days that fly the Åland flagflags:=ax (only valid for flag_days)
Short list onlyin_short_list:=true (only valid for holidays)

Response Shape

Identical to a Typesense search response. The proxy adds a _meta object alongside hits, found, page etc.:

{
  "hits": [
    {
      "document": {
        "id": "1714817349-abc123",
        "date": "2026-02-05",
        "year": 2026, "month": 2, "day": 5,
        "weekday": 4, "iso_week": 6,
        "name_fi": "J.L. Runebergin päivä",
        "name_sv": "Runebergsdagen",
        "flags": ["fi"],
        "created_at": "2026-04-30T12:00:00Z",
        "updated_at": "2026-04-30T12:00:00Z"
      },
      "highlight": {},
      "highlights": []
    }
  ],
  "found": 22,
  "out_of": 22,
  "page": 1,
  "request_params": { ... },
  "search_time_ms": 1,
  "_meta": {
    "response_time_ms": 12,
    "authenticated_user": null,
    "organization_id": 5,
    "organization_name": "Example Org",
    "auth_type": "api_token",
    "timestamp": "2026-05-04T09:00:00Z"
  }
}

Interactive API Documentation

Use the Swagger UI below to explore and test the API endpoints interactively. Enter your API token to authenticate requests.

Try it out: Enter your API token below, then use the "Try it out" button in the Swagger UI to make real API calls.