Ash Template
Docs About Contact

Developer documentation

Ash Template has a small public surface: documentation you can read without an account, a health check, and one account API for the person who signed in.

Start without an account

Public documentation and the health check need no API key or wallet. Read this page, the agent guide or the OpenAPI JSON specification.

curl --fail 'https://template.regents.sh/healthz'
curl --fail -H 'Accept: text/markdown' 'https://template.regents.sh/docs'
curl --fail 'https://template.regents.sh/openapi.json'

The health response is the plain text ok. It confirms the web service is responding, not that every outside service is available.

The homepage, this documentation, About, Contact, Privacy and Terms answer Accept: text/markdown at their ordinary addresses. Browsers receive HTML by default. Unknown page addresses return 404 rather than an empty document.

Read and update your profile

GET /api/v1/profile returns the profile of the person whose credentials are presented. PATCH /api/v1/profile updates its display_name or wallet_address. POST /api/v1/profile/sync creates the profile on first use and refreshes it from your sign-in evidence afterwards.

Every request carries both a Privy access token in Authorization: Bearer … and a Privy identity token in Privy-Id-Token. These are your own sign-in credentials, not an API key. Keep them private; never paste tokens, private keys or recovery phrases into a chat, report or public issue.

The following command assumes the two token variables were supplied through your own secure credential handling:

curl --fail-with-body 'https://template.regents.sh/api/v1/profile' \
  -H 'Accept: application/json' \
  -H "Authorization: Bearer ${PRIVY_ACCESS_TOKEN}" \
  -H "Privy-Id-Token: ${PRIVY_IDENTITY_TOKEN}"

Create the profile on first use, then change the name shown on it:

curl --fail-with-body -X POST 'https://template.regents.sh/api/v1/profile/sync' \
  -H 'Accept: application/json' \
  -H "Authorization: Bearer ${PRIVY_ACCESS_TOKEN}" \
  -H "Privy-Id-Token: ${PRIVY_IDENTITY_TOKEN}"

curl --fail-with-body -X PATCH 'https://template.regents.sh/api/v1/profile' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ${PRIVY_ACCESS_TOKEN}" \
  -H "Privy-Id-Token: ${PRIVY_IDENTITY_TOKEN}" \
  -d '{"display_name": "Ada"}'

A successful response contains a profile object with the profile id, display name, the linked wallets and the selected wallet. Missing or invalid credentials return 401. A profile that has not been created yet returns 404; call POST /api/v1/profile/sync first. An invalid update returns 422. A service that is not configured for sign-in returns 503. Profile responses are never cached.

Errors

Every JSON error has one shape:

{"error": {"code": "not_found", "message": "Not Found", "hint": "See https://template.regents.sh/docs and https://template.regents.sh/openapi.json for supported requests."}}

code is stable and meant for programs, message says what went wrong and hint says what to do next. Profile answers carry the code alone, for example authentication_required, profile_not_created or invalid_profile_update. Branch on the status and the code, never on the wording of message.

An unknown address under /api answers JSON 404 whatever the Accept header says. An unknown page address answers 404 as HTML, or as Markdown when you ask for text/markdown. The OpenAPI JSON specification lists every status each operation can return.

Rate limits

Each client address has 120 requests per 60 seconds, shared by /healthz and /api/v1. Every answer says where you stand:

RateLimit-Policy: "default";q=120;w=60
RateLimit: "default";r=119;t=42

q is the number of requests allowed in a window of w seconds, r is how many remain and t is the number of seconds until the window resets. Past the limit the answer is 429 with the code too_many_requests and a Retry-After header in seconds; wait that long, then send the request again.

Versioning and deprecation

  • The API version is in the path (/api/v1) and in info.version of the OpenAPI JSON specification. New endpoints, response fields and optional inputs can appear at any time, so ignore fields you do not recognise.
  • A breaking change, such as removing or renaming a field, endpoint or error code, changing a type or making an input required, ships in place under the same path. It is listed below on the day it ships and info.version moves to a new major number. There is no notice period and no Deprecation or Sunset header, so check info.version before relying on a field.

Breaking changes

None yet.

Browser tools

Every page offers a browser's own agent these tools through WebMCP (document.modelContext). Each reads one of the public documents as Markdown, needs no sign-in and changes nothing. The tool manifest describes them as JSON.

Tool Reads Needs What it does
about GET /about Nothing Read the About page as Markdown: what Ash Template is, what a person can do here and who runs it. Reads only; needs no sign-in; changes nothing.
docs GET /docs Nothing Read the developer documentation as Markdown: the public reads, the profile API, errors, rate limits and the versioning policy. Use it before calling the HTTP API. Reads only; needs no sign-in; changes nothing.

Contracts

The OpenAPI JSON specification describes the health check and the profile API above, including their authentication requirements. The YAML contract is the full served contract, including the browser session endpoints the site itself uses. The API catalog (RFC 9727) points to the OpenAPI specification and this page, and security.txt names where to report a vulnerability.

Public documentation does not authorize a payment, signature, credential change or other change to your account.

Need help? Read About, Contact, Privacy and Terms.

For agents