Developers

Address API

A small HTTP API for the same actions as the site: check a name, claim an address after payment, and cancel it.

Mock documentation. This describes the API we intend to ship. No endpoint on this draft accepts requests. The availability checker on the buy page is the working mock of GET /v1/availability.

Base URL

https://api.teton.id/v1

Send and accept application/json. Authenticated routes expect Authorization: Bearer and a token created in the account dashboard. This draft does not issue tokens. Do not send a real secret to this static site.

Errors

Errors use a single shape and an HTTP status. Rate limit is 60 requests per minute per token. A 429 response includes a Retry-After header, in seconds.

{
  "error": {
    "code": "address_taken",
    "message": "That address is not available."
  }
}
Error codes
CodeStatusWhen
invalid_local400The local-part fails the name rules.
address_reserved409The name is held for operations or impersonation risk.
address_taken409Another address already uses the name.
unauthorized401Missing or rejected token.
cycle_unknown400Billing cycle is not monthly or annual.
rate_limited429Too many requests.
GET /v1/availability

Check whether a local-part is free on teton.id. This route is public so the buy page can call it before an account exists. It does not reserve the name.

Query

NameRequiredNotes
localYes2–32 characters. Letters, numbers, and single dots or hyphens.

Example request

curl "https://api.teton.id/v1/availability?local=mesa"

Example response · 200

{
  "local": "mesa",
  "address": "mesa@teton.id",
  "available": true
}
POST /v1/addresses

Claim an address after payment is confirmed. Send an Idempotency-Key header so a retry does not claim two names. The response is 202 while status is provisioning. The price is $30 a month or $300 a year. Mail for the address is a separate service.

Example request

curl -X POST "https://api.teton.id/v1/addresses" \
  -H "Authorization: Bearer $TETON_TOKEN" \
  -H "Idempotency-Key: 8f1c0b4e" \
  -H "Content-Type: application/json" \
  -d '{
    "local": "mesa",
    "cycle": "annual"
  }'

Example response · 202

{
  "id": "adr_01J0DEMO",
  "address": "mesa@teton.id",
  "status": "provisioning",
  "cycle": "annual",
  "amount": 300
}

Status values: provisioning, active, suspended, cancelled.

GET /v1/addresses/{id}

Read one address on the account. Use this to poll until status is active.

Example response · 200

{
  "id": "adr_01J0DEMO",
  "address": "mesa@teton.id",
  "status": "active",
  "cycle": "annual",
  "renews_at": "2027-10-23"
}
POST /v1/addresses/{id}/cancel

Cancel at the end of the paid term. The address stays assigned until that date. Response 200.

Example response · 200

{
  "id": "adr_01J0DEMO",
  "address": "mesa@teton.id",
  "status": "active",
  "cancel_at_period_end": true
}

Name rules

Local-parts are stored in lowercase. They must be 2–32 characters, start and end with a letter or number, and may contain dots, hyphens, or underscores if those marks are not repeated. Role names such as postmaster and abuse, and names used to impersonate banks or well-known services, are rejected with address_reserved.