Key-value data
Store strings and structured collections with TTLs and atomic counters.
Use tenant-scoped data, scheduling, workflow, and messaging services from your application. Administration and platform operations are intentionally excluded from this reference.
Choose the service that fits the work your application needs to perform.
Store strings and structured collections with TTLs and atomic counters.
Deliver public HTTP webhooks now, later, or on a recurring schedule.
Track idempotent steps, sleeps, and external signals.
Publish messages to webhooks, SSE consumers, and WebSocket subscribers.
X-API-Key: <key> or
Authorization: Bearer <key> on every
/v1/* request. Browser console sessions use an
HttpOnly cookie and are not a substitute for an integration API
key.
Successful responses wrap their payload in result.
Paginated list responses include total,
page, limit, and pages
alongside the endpoint's list field. Errors use
{"detail":"..."}.
All routes are relative to your Thodari host, for example
https://your-host/v1/…. Request and response bodies use
JSON unless an endpoint specifies otherwise.
Verify an integration key and discover its tenant context with
GET /v1/admin/me. Key issuance, reset, revocation, and
audit records are administrator operations available in the Console.
Store application state, cache entries, counters, and compact collections.
| Field | Purpose |
|---|---|
key |
Key to store. |
value |
Value to store. |
ex / px |
Optional expiration in seconds or milliseconds. |
nx / xx |
Optional create-only or update-only condition. |
POST /v1/kv/set {"key":"cart:42","value":"open","ex":3600}
Returns the tenant-scoped value or null when it is
absent or expired.
POST /v1/kv/incr {"key":"orders:processed","delta":1}
POST /v1/kv/del {"keys":["cart:42","cart:43"]}
POST /v1/kv/mget {"keys":["cart:42","cart:43"]}
POST /v1/kv/mset {"items":{"cart:42":"open"},"ex":3600}
/scan supports cursor-based paging. TTL returns
-1 for persistent keys and -2 for
missing keys.
POST /v1/kv/hash/hset {"key":"profile:42","field":"name","value":"Ada"}
GET /v1/kv/hash/hget/{key}/{field} · /hash/hgetall/{key}
POST /v1/kv/hash/hdel {"key":"profile:42","fields":["name"]}
POST /v1/kv/list/push {"key":"jobs","values":["a"],"direction":"left"}
POST /v1/kv/list/pop {"key":"jobs","direction":"left"}
GET /v1/kv/list/range/{key}?start=0&stop=-1
POST /v1/kv/sets/sadd {"key":"roles","members":["editor"]}
POST /v1/kv/sets/srem {"key":"roles","members":["editor"]}
GET /v1/kv/sets/smembers/{key}
POST /v1/kv/zset/zadd {"key":"scores","score":10,"member":"ada"}
POST /v1/kv/zset/zrem {"key":"scores","member":"ada"}
GET /v1/kv/zset/zrange/{key}?start=0&stop=-1&withscores=true
GET /v1/kv/zset/zscore/{key}/{member}
Schedule outbound delivery to public HTTP(S) URLs. Deliveries retry with backoff and appear in your dead-letter queue if they cannot be delivered.
| Field | Purpose |
|---|---|
url |
Public HTTP(S) destination. |
delay |
Optional delay in seconds. |
scheduled_at |
Optional ISO 8601 date and time. |
cron |
Optional five-field cron expression. |
timezone |
IANA time zone for cron or scheduled dates. |
body |
Optional request body. |
POST /v1/publish {"url":"https://example.com/hooks/order","delay":300,"retries":3}
Use optional page and limit parameters
for paged results. Send
PUT /v1/schedules/{job_id} to update a job.
These actions apply only to jobs owned by your tenant.
Cancellation permanently removes the scheduled job.
Use resend after correcting a destination or temporary downstream issue.
Create long-running executions and record idempotent progress as your application completes work.
POST /v1/workflows/submit {"name":"fulfil-order","url":"https://example.com/workflows/fulfil","initial_data":{"order_id":"ORD-123"}}
An execution response includes its current state and recorded steps.
Step names are idempotent within an execution: resubmitting the same step returns its recorded outcome.
Wait steps can specify signal_timeout_seconds. If a
signal does not arrive before the deadline, the execution fails.
Use cancellation to halt work; deletion removes the durable execution record.
Publish tenant-scoped topic events to webhook subscribers and real-time consumers.
POST /v1/topics/orders/publish {"payload":{"order_id":"ORD-123","status":"ready"}}
Use GET /v1/topics to list topics,
DELETE /v1/topics/{topic} to remove one, and
GET /v1/topics/{topic}/history for message history.
Topic names may be reused by other tenants without sharing data.
Add or list subscriptions for a topic. Remove one with
DELETE /v1/topics/subscriptions/{sub_id}.
The stream contains events visible to your tenant.
Authenticate with an Authorization: Bearer <api-key>
header (server clients) or a console session cookie (same-origin browser).
Browser clients without a session must first create a one-time
POST /v1/ws-ticket ticket and use ?ticket=....
{"action":"subscribe","topic":"orders"}
{"action":"unsubscribe","topic":"orders"}
List with optional status (pending,
running, retry, delivered,
or dlq), page, and limit.
Replay requeues a delivery using its stable ID.
These unauthenticated operational endpoints are for reverse proxies and monitoring.
/livez confirms that the process is running. Use
/readyz for traffic admission: it verifies database access,
the event bus, and required background health. It returns 503
when the instance should not receive traffic.
Use conventional HTTP status handling and retry only when a response tells you to wait.
For 429, wait for the number of seconds in the
Retry-After response header before retrying. A
413 response indicates that the request body exceeds
the service limit.