API Overview
The Underlay API is a JSON REST API served at /api. All request and response bodies are JSON (except file uploads/downloads). A machine-readable reference is available at /.well-known/ai.txt.
Base URL
https://underlay.org/api Authentication
All GET requests are public — no authentication required to read public data. All write requests (POST, PATCH, PUT, DELETE) require authentication.
There are two authentication methods:
API Keys (recommended for scripts & apps)
Pass your key as a Bearer token:
Authorization: Bearer ul_a1b2c3d4e5... Keys have three scopes:
read— list and download datawrite— push versions, upload filesadmin— delete collections, manage keys
Keys can optionally be scoped to a single collection. Create keys in your organization settings or via POST /api/accounts/keys.
Session Cookies (browser)
The web UI authenticates via signed session cookies set by POST /api/accounts/login. Sessions expire after 30 days.
Invalid Credentials
If a Bearer token is provided but does not match any key, the request is immediately rejected with 401 — it will not fall through to anonymous access.
Rate Limits
All requests are rate-limited. Authenticated requests get a significantly higher allowance:
| Auth status | Limit |
|---|---|
| Unauthenticated (by IP) | 60 requests / minute |
| Authenticated (by account) | 5,000 requests / minute |
Every response includes rate limit headers:
X-RateLimit-Limit— max requests in the current windowX-RateLimit-Remaining— requests remainingX-RateLimit-Reset— seconds until the window resets
When you exceed the limit, you'll receive a 429 Too Many Requests response with a Retry-After header indicating how long to wait.
For any automated or scripted access, always use an API key to get the higher rate limit.
Error Responses
Errors return a JSON body with error and statusCode:
{
"error": "Authentication required",
"statusCode": 401
} Common status codes:
400— Bad request (invalid input)401— Authentication required or invalid credentials403— Insufficient permissions (wrong scope)404— Resource not found409— Version conflict (re-fetch and retry)422— Validation error (e.g. missing files)429— Rate limited (wait and retry)