Johannes Homeier
Back

API reference

This site exposes exactly one endpoint: a way to send a message without driving the browser form. It is unauthenticated and free to use. The machine-readable description lives at /openapi.json (OpenAPI 3.1); everything below restates it for humans.

Send a note

POST /api/contact
POST /api/v1/contact
Content-Type: application/json

{
  "note": "your message",            // required, 1-5000 characters
  "email": "you@example.com"         // optional reply-to address
}

A success returns 200 with { "ok": true }.

No API key is needed. When the site is running with Friendly Captcha enabled, a third field frcCaptchaResponse is also required, carrying a token from the widget on the home page; a call without one answers 400 with captcha_required. That token can only be produced by a browser, so an automated caller that hits it should fall back to email.

Versioning and deprecation

The endpoint is available unversioned at /api/contact and version-pinned at /api/v1/contact. Both serve the same handler today. Pin to /api/v1/ if you are integrating: breaking changes will ship under a new path (/api/v2/) rather than altering v1 in place.

If a version is ever retired it will first return a Deprecation header and a Sunset header (RFC 8594) giving the retirement date, and will keep working for at least six months after that header first appears. The unversioned path always follows the newest version and can change without that notice.

Rate limits

Ten requests per hour. Every response to POST /api/contact carries RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset and RateLimit-Policy; a 429 adds Retry-After. The limit is enforced per serving instance rather than globally, so treat it as a floor, not a guarantee — back off when the headers say to.

Errors

Every error is JSON, never an HTML page, and carries a stable code you can branch on plus a resolution describing what to do next:

{
  "error": "Note is too long.",
  "code": "note_too_long",
  "resolution": "Keep `note` to 5000 characters or fewer.",
  "status": 400
}
StatusCodes
400invalid_body, note_empty, note_too_long, email_invalid, captcha_required, captcha_failed
404endpoint_not_found
405method_not_allowed
429rate_limited
500not_configured
502delivery_failed — retryable

CORS

The endpoint and every machine-readable file are served with Access-Control-Allow-Origin: *, and the endpoint answers preflight, so a browser-based agent can call it from another origin.

Reading the site itself

There is no read API — the content is published as files instead: /llms.txt (index and when-to-use guidance), /llms-full.txt (the home page plus operator and legal details, in one fetch), /index.md (the home page as Markdown), and /sitemap.xml. Requesting / with Accept: text/markdown returns the Markdown representation.

© 2026 · Regensburg
Imprint Privacy
GitHubXLinkedIn