Tannur

API Reference

The Tannur REST API lets you emit events, query state, manage deployments, and control databases programmatically.

Base URL

https://api.tannur.xyz

Authentication

All API requests require an API key. Pass it in the x-api-key header.

curl -X POST https://api.tannur.xyz/emit \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"stream":"orders","type":"order.created","data":{"id":"123"}}'

You can generate and rotate API keys from the Tannur Dashboard under Settings → API Keys, or via the CLI:

tannur rotate-key

Event Sourcing API

Tannur's core is an event-sourcing engine. You emit events into named streams, and Tannur materialises the current state by replaying them in order.

POST
/emit

Emit a new event into a stream

GET
/state

Get the materialised state of a stream

GET
/events

List all raw events in a stream

GET
/events-fetch

Fetch events with filtering & pagination

POST /emit

Append a new event to a stream. Tannur automatically resolves the tenant from your API key.

Request Body

{
  "stream": "orders",
  "type": "order.created",
  "data": {
    "orderId": "abc-123",
    "amount": 49.99,
    "currency": "NGN"
  }
}

Response 200

{
  "ok": true,
  "eventId": "evt_7xk29m",
  "stream": "orders",
  "sequence": 42,
  "timestamp": "2026-06-30T12:00:00Z"
}

GET /state

Returns the current materialised state of a stream — computed by replaying every event in order.

Query Parameters

GET /state?stream=orders

Response 200

{
  "stream": "orders",
  "state": {
    "totalOrders": 42,
    "totalRevenue": 2099.58,
    "lastOrderAt": "2026-06-30T12:00:00Z"
  },
  "version": 42
}

GET /events

Retrieve the raw event log for a stream.

Query Parameters

GET /events?stream=orders
    &limit=50
    &offset=0

Response 200

{
  "events": [
    {
      "id": "evt_7xk29m",
      "type": "order.created",
      "data": { "orderId": "abc-123" },
      "sequence": 42,
      "timestamp": "2026-06-30T12:00:00Z"
    }
  ],
  "total": 42
}

CLI Authentication Flow

The CLI authenticates via a browser-based OAuth handshake. These three endpoints power that flow.

POST
/auth-cli-start

Start a CLI auth session — returns a one-time code and browser URL

GET
/auth-cli-poll

Poll until the user approves the session in the browser

POST
/auth-cli-complete

Exchange the approved code for a long-lived API key

# Typical flow (the CLI does this for you):
1. POST /auth-cli-start  →  { code: "ABCD-1234", url: "https://tannur.xyz/auth?code=ABCD-1234" }
2. User opens URL in browser and approves
3. GET  /auth-cli-poll?code=ABCD-1234  →  { status: "approved", token: "tk_..." }
4. CLI stores the token locally for future requests

Deployment API

Push builds to Tannur's edge network and check system health.

POST
/deploy

Deploy a new build from your connected repository

GET
/health

Health-check — returns { status: 'ok' }

Database API

Provision and manage databases (PostgreSQL, MySQL, MongoDB, Redis, ClickHouse) directly through the API.

POST
/api/database/create

Provision a new managed database

GET
/api/database/list

List all databases for your tenant

GET
/api/database/:id

Get database connection details and status

GET
/api/database/:id/stats

CPU, memory, storage, QPS metrics

GET
/api/database/:id/tables

List tables with row counts and sizes

POST
/api/database/:id/start

Start a stopped database

POST
/api/database/:id/stop

Stop a running database

POST
/api/database/:id/restart

Restart a database

DELETE
/api/database/:id

Permanently delete a database

Create a Database

Request Body

POST /api/database/create

{
  "name": "my-app-db",
  "type": "postgres",
  "region": "us-east-1",
  "memory_limit": 1024,
  "storage_limit": 10240
}

Response 201

{
  "database": {
    "id": "db_8fk29x",
    "name": "my-app-db",
    "type": "postgres",
    "status": "provisioning",
    "host": "db-8fk29x.tannur.xyz",
    "port": 5432,
    "connection_string": "postgresql://..."
  }
}

Supported Engines

EngineType ValueTypical Use
PostgreSQLpostgresRelational workloads
MySQLmysqlLaravel, WordPress
MongoDBmongodbDocument storage
RedisredisCaching, queues
ClickHouseclickhouseColumnar analytics

Feature Access & Tiers

Tannur enforces tier-based feature gating. Use these endpoints to check what your current plan allows.

GET
/features-access

Check if a specific feature is available on your plan

GET
/features-matrix

Get the full feature matrix for all tiers

Tier Hierarchy

Seed

Free — basic API access, 1 project

Sprout

Starter — advanced analytics

Pro

Custom domains, teams, AI generation

Growth

SSO, custom branding, dedicated support

Error Handling

All errors follow a consistent JSON shape:

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing API key",
    "status": 401
  }
}
StatusCodeMeaning
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENYour tier doesn't allow this feature
404NOT_FOUNDStream or resource not found
429RATE_LIMITEDToo many requests — slow down
500INTERNALServer error — retry with backoff
Ctrl+I