REST API — Overview
Aurabase raw HTTP surface. Compatible with all languages. Base URL, authentication, response format, error codes — then details by endpoint in /docs/api/.
An origin, the project on the way
There is no domain per project. All traffic goes through a single origin — that of the gateway — and the project is identified by its UUID in the path. The gateway exposes two plans: the data plan (SDK and applications, :8080 locally) and the management plan (Studio and administration, :8090). The given plane surfaces are prefixed /v1/db, /v1/auth, /v1/storage, /v1/realtime, /v1/functions, /v1/notifications, /v1/ai.
Two exceptions to the /v1/<service>/{project_id} pattern: the streaming routes /v1/realtime/ws and /v1/realtime/sse do not have project_id in the path — it is inferred from the query parameter ?project_id= or the prefix of ?channel={project_id}:{topic}. A URL without an identifiable project is rejected as 400 (“project_id (UUID) not found in URL to validate API key”).
Two keys, one JWT
anon_key— publishable. Serves as the API key for any request. Headerapikey,X-API-Key, or parameter?apikey=— the latter is only accepted on real-time streams (/ws,/sse,/chat/stream); elsewhere it is explicitly refused.service_role_key— secret, RLS bypass. Reserved for the backend.user_jwt— issued byPOST /v1/auth/{project_id}/loginafter authentication. HeaderAuthorization: Bearer.
Standards applied
Content-Type: application/json— required on POST/PATCH/PUT (except upload storage, inmultipart/form-data)Prefer: return=representation— returns the lines created/modified;return=minimalfor a response without a body (204).Prefer: count=exactis read on aura-db mutations (headersContent-Range+Preference-Applied); To rely on a reading, use the?count=exactparameterRange: 0-49— only on a Postgres project served by PostgREST, which interprets it itself. The aura-db path (MongoDB project, or Postgres with PostgREST disabled) ignores this header: it only readslimitandoffset. Preferlimit/offset, which work on both enginesIdempotency-Key— is NOT read on Database (POST /v1/db/…) writes: two identical POSTs create two lines. It is only honored byPOST /v1/notifications/{project_id}/send(and/send/batch), and by the creation of the management plan API key (POST /v1/db/{project_id}/api-keys, 24-hour window)
Limit + offset
Without limit, a read returns at most 1000 lines — this is both the default and the hard ceiling. The actually applied limit is returned in meta.per_page, never guessed.
The total is not read in the same place depending on the engine: on the aura-db path, the response carries the header Content-Range: items 100-149/1247 (the total is worth * if no count was requested); on the PostgREST path, the gateway does not relay this header and places the total in meta.total of the JSON envelope. Counting is never done by default: request it with the parameter ?count=exact (portable form, translated into Prefer by the gateway on the PostgREST path) or ?count=estimated.
Uniform format
error is always an object, never a string. Two variants, depending on the issuer - the fields code and message are common to both, and it is on code (never on message, free text) that we discriminate.
PostgREST/PostgreSQL codes (PGRST116, 23505…) are never returned as is: the gateway translates them into Aurabase codes (RECORD_NOT_FOUND, NOT_SINGULAR, COLUMN_NOT_FOUND, NO_RELATIONSHIP, SCHEMA_NOT_FOUND, DUPLICATE_KEY, FOREIGN_KEY_VIOLATION, TABLE_NOT_FOUND, INSUFFICIENT_PRIVILEGE, otherwise POSTGREST_ERROR). This variant bears neither type nor request_id; there is no hint nor trace_idfield.
CodeNameDescription
400Invalid Bad RequestPayload or malformed query. error.code = BAD_REQUEST.
401Unauthorizedapikey missing/revoked or invalid JWT. error.code = UNAUTHORIZED (or REFRESH_TOKEN_REJECTED on /refresh).
403ForbiddenRLS or authorization service refuses the operation. error.code = FORBIDDEN, QUOTA_EXCEEDED, or INSUFFICIENT_PRIVILEGE (PostgREST path).
404Not FoundResource nonexistent or invisible by RLS. error.code = NOT_FOUND, RECORD_NOT_FOUND or TABLE_NOT_FOUND.
406Not Acceptable Single line expected, multiple returned. error.code = NOT_SINGULAR.
409ConflictSingle constraint violation or FK. error.code = CONFLICT, DUPLICATE_KEY, FOREIGN_KEY_VIOLATION. Use on_conflict for upsert.
413Payload Too LargeRequest > MAX_BODY_SIZE (default 50 MB on the gateway side). Use multipart storage upload.
429Too Many RequestsRate limit reached. X-RateLimit-Limit / X-RateLimit-Remaining headers; Retry-After on gateway refusals.
500Internal ErrorServer error. error.request_id to provide to support.
503Service UnavailableCircuit breaker open, instance missing, or hibernated project (Retry-After: 5 in the latter case). Recovery breaker after 30 s.
504Gateway TimeoutTimeout upstream. error.code = TIMEOUT.
By IP at the gateway, plus limits per route
- Gateway, all routes: per IP,
100req/s with a burst of1000(adjustable viaRATE_LIMIT_RPS/RATE_LIMIT_BURST). There is no separate tier per role. - Auth sensitive (
login,register,forgot-password,magic-link,email-otp/send,sms/send,refresh,mfa/verify-login): 5 req/min per IP, burst 3. In addition, a quota per project: 30 connection attempts/hour per IP by default, adjustable in the project settings. - Raw SQL (
/raw): 30 req/min, burst 10. IA: 10 req/min, burst 5.
Overflow → 429 Too Many Requests with the headers X-RateLimit-Limit and X-RateLimit-Remaining (present on any response from the gateway), plus X-RateLimit-Reset and Retry-After on the refusal.
Complete tree per service
Each endpoint has its dedicated page with parameters, response codes, examples in 5 languages and live rail code.