JENRIKS API and agent access

Everything on JENRIKS that a program can read is public, read-only and free: a small REST API, an MCP server for agent hosts, and the feeds, markdown pages and discovery documents listed below. There are no API keys, no accounts and no write operations. The photographs stay copyrighted; the last section says how to credit them.

REST API, version 1

Base URL https://jenriks.com/api/v1. Responses are JSON (UTF-8) with CORS open to any origin. The archive gains one photo every day at 00:00 Europe/Berlin. The machine-readable contract is /openapi.json (OpenAPI 3.1, every response typed).

GET /api/v1
Index of endpoints with links to this page, the OpenAPI document and the MCP server.
GET /api/v1/photos
Search, newest first. Query parameters: q (free text over title, place, categories, tags, photographer), photographer (Erik or Jens), category, year, location, limit (1 to 50, default 10), offset.
GET /api/v1/photos/latest
Today's photo.
GET /api/v1/photos/random
A random photo; optional photographer, category, year.
GET /api/v1/photos/{YYYY-MM-DD}
The photo published on that date. One post exists for every day since 2006-01-01.
GET /api/v1/overview
Totals, photographers, categories with counts, posts per year, section URLs, URL pattern and license terms.
GET /api/v1/health
Health of the API and the MCP server, including the number of indexed photos.

Quickstart

curl "https://jenriks.com/api/v1/photos?q=fog&photographer=Jens&limit=2"

Every photo object carries the same fields:

{
  "title": "Huangshan Views",
  "photographer": "Jens",
  "date": "2026-05-22",
  "url": "https://jenriks.com/2026/05/22/huangshan-views/",
  "location": "Huangshan, China",
  "categories": ["Landscapes"],
  "tags": ["mountains", "mist"],
  "image": {
    "full": "https://pub-1e42b425212d40d4b2d89a957f723c24.r2.dev/photos/JH3689_huangshan-views.jpg",
    "thumbnail": "https://pub-1e42b425212d40d4b2d89a957f723c24.r2.dev/thumbs/JH3689_huangshan-views.jpg"
  },
  "credit": "© Jens Herrmann, JENRIKS, https://jenriks.com/2026/05/22/huangshan-views/"
}

Search results wrap photos in total_matches, offset, returned, photos and, when more exist, next_offset.

MCP server

Endpoint https://jenriks.com/mcp, Model Context Protocol over Streamable HTTP with JSON responses. It is stateless: no sessions, no server-initiated event stream, no authentication. Protocol versions 2025-06-18, 2025-03-26 and 2024-11-05 are accepted.

Tools: search_photos, get_photo (by date or URL), get_latest_photo, random_photo, get_site_overview. Each declares an input and an output schema and returns structuredContent. Resources: /llms.txt, /llms-full.txt, /feed.xml, /index.md.

Client configuration for hosts that take a JSON server list:

{
  "mcpServers": {
    "jenriks": { "type": "http", "url": "https://jenriks.com/mcp" }
  }
}

Discovery: server card /.well-known/mcp/server-card.json (also /mcp/server-card as application/mcp-server-card+json), MCP Registry manifest /server.json, health /mcp/health.

Errors

Every error from /api, /mcp and the discovery documents is an RFC 9457 problem document with Content-Type: application/problem+json. Page URLs answer the same way when a client accepts only JSON. Fields: type (a link into this section), title, status, detail, instance (the request URL), code (stable, listed below), resolution (what to do instead) and documentation_url.

not_found (404)
No page or document exists at the URL.
api_route_not_found (404)
No API route at that path; the index at /api/v1 lists the routes.
photo_not_found (404)
No post on the requested date.
method_not_allowed (405)
The API is read-only; the Allow header lists the accepted methods.
invalid_parameter (400)
A query or path parameter failed validation; detail names it.
not_acceptable (406)
The URL has no representation matching the Accept header.
unsupported_media_type (415)
MCP messages need Content-Type: application/json.
payload_too_large (413)
MCP request bodies are limited to 64 KB.
rate_limit_exceeded (429)
Quota exhausted; wait for Retry-After.
service_unavailable (503)
The photo index could not be loaded; retry after a minute.

JSON-RPC level errors inside the MCP server (unknown method, unknown tool, invalid params) use the JSON-RPC error object as the protocol requires.

Rate limits

/api and /mcp allow 120 requests per client IP in each 60-second window. Every response advertises the policy and the remaining quota through the IETF RateLimit-Policy and RateLimit structured fields, plus RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset for older clients. A 429 carries Retry-After. Feeds, sitemap and pages are served from Cloudflare's edge and are not counted.

Versioning and deprecation

Stable REST operations carry a major version in the path, beginning with /api/v1. Backward-compatible fields may be added within v1; breaking request or response changes get a new major path. Before a version is removed, JENRIKS publishes a migration note in this section and signals it with RFC 9745 Deprecation and Link headers; a dated Sunset header is announced at least 90 days before removal. No sunset is scheduled. The MCP server follows the protocol's own version negotiation and keeps at least the two most recent protocol versions.

Feeds, markdown and discovery documents

Credit and licensing

All photographs are © Jens Herrmann or © Erik Hehrmann, all rights reserved. When you show or cite a photo: name the photographer and link the permanent page URL; the credit field is ready to paste. Do not redistribute, modify or train on the images without written permission. Prints and licensing go through the contact page. The API documents, schemas and this page may be copied freely.

Contact

Questions, corrections and integration notes: [email protected] or the contact page.