This is the developer portal for edheltzel.codes. It documents the public read surface. There is no hosted product, no account, and no write API.

## API keys

No API keys. Every page is public. Do not send an Authorization header. A missing key is not an error, and there is no key to create, rotate, or revoke. If a client sends a bearer token, ignore it. Nothing on this origin checks one.

## Documentation

Request the canonical URL with `Accept: text/markdown`. The response is Markdown, `Content-Type: text/markdown`, and `Vary: Accept`. The same URL with `Accept: text/html` is the terminal page people see. Unknown page paths return HTTP 404, not the homepage. A Markdown 404 points here, to the sitemap, and to llms.txt.

Machine-readable files:

- `/llms.txt` tells an agent when to use this site and which page to open.
- `/sitemap.xml` lists indexable URLs with lastmod dates.
- `/robots.txt` points at the sitemap.
- `/openapi.json` is the OpenAPI 3.1.0 description of the read API.
- Each HTML page also has a `.md` sibling, advertised with `rel="alternate"`.

The read API is JSON, not negotiated Markdown:

- `GET /api/v1/pages` lists public pages. `cursor` and `limit` page the list. `next_cursor` is present only when `has_more` is true.
- `GET /api/v1/page?path=/now` returns one page, including its Markdown body. `path` must be a value from the list.

## Quickstart

```
curl -sS -D - -H 'Accept: text/markdown' https://edheltzel.codes/
curl -sS -D - -H 'Accept: text/html' https://edheltzel.codes/
curl -sS -D - -H 'Accept: text/markdown' https://edheltzel.codes/some-path-that-does-not-exist
curl -sS -D - https://edheltzel.codes/openapi.json
curl -sS -D - https://edheltzel.codes/api/v1/pages
curl -sS -D - 'https://edheltzel.codes/api/v1/page?path=/now'
curl -sS -D - https://edheltzel.codes/api/v1/orank-probe-test
```

The first response is Markdown with `Vary: Accept`. The second is HTML. The third is HTTP 404 with a Markdown body. The OpenAPI document is JSON. The page list and page read are JSON. The last URL is not a route, so it is HTTP 404 with `Content-Type: application/problem+json`.

From a checkout of the site repo, the CLI does the same page read:

```
bun cli/edheltzel.ts get /now
bun cli/edheltzel.ts ls
```

## Sandbox

The public origin is the sandbox. Reads have no side effects. There is no write API, no stored caller state, and no separate sandbox host. Reset is unnecessary because a GET does not change the site. Do not send personal data, credentials, or private URLs in query strings. Nothing here is stored for you.

<h2 id="errors">Errors</h2>

Page paths that are not under `/api` stay HTML or Markdown, depending on `Accept`. Paths under `/api` always return JSON, including when the client sends no `Accept` header.

An API error is RFC 9457 `application/problem+json`. The body has a stable `code`, a `message` (the same text as `detail`), and a `resolution` that says what to do next. `status` matches the HTTP status. `instance` is the request URL. `documentation_url` points here.

Codes:

- `api_route_not_found` (404): the path is not a read API route. Open `/openapi.json`.
- `page_not_found` (404): `path` is not a public page. List pages and retry with one of those paths.
- `invalid_path` (400): `GET /api/v1/page` was called without `path`.
- `invalid_cursor` (400): `cursor` was not a `next_cursor` from this API. Omit it to start over.
- `invalid_limit` (400): `limit` must be an integer from 1 to 100.
- `method_not_allowed` (405): retry with GET. There is no write operation.
- `rate_limit_exceeded` (429): wait for `Retry-After`. The quota is 120 requests per 60 seconds on that edge isolate, not a global account limit.
- `internal_error` (500): retry once, or read the page with `Accept: text/markdown`.

Successful API responses and API errors include the IETF `RateLimit-Policy` and `RateLimit` headers.

<h2 id="versioning-and-deprecation">Versioning and deprecation</h2>

The current major is `/api/v1`. Breaking changes ship under a new `/api/vN` path. A retired major stays available for at least 180 days. While it is retired, responses send the RFC 9745 `Deprecation` header and the RFC 8594 `Sunset` header. Those headers are absent on the current v1 operations. The policy URL is this section.

## CLI

The official client is `cli/edheltzel.ts` in https://github.com/edheltzel/edheltzelCodes3. It fetches Markdown and lists the sitemap. It is not on npm, PyPI, or Homebrew yet. Publishing needs the maintainer's registry credentials. Until that publish, run it from a checkout with bun. Do not invent an npm package name and treat it as installed.
