Public API Overview
Base URL: https://<host>/api/v1
All endpoints require a Bearer API key.
Authorization: Bearer sok_live_... # or sok_test_...
Content type: application/json.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /api/v1/emails |
Send one email |
| POST | /api/v1/emails/batch |
Send up to 100 emails |
| GET | /api/v1/emails |
List emails (cursor pagination) |
| GET | /api/v1/emails/{id} |
Retrieve one email |
| POST | /api/v1/sms |
Send one SMS |
| POST | /api/v1/sms/batch |
Send up to 100 SMS |
| GET | /api/v1/sms |
List SMS |
| GET | /api/v1/sms/{id} |
Retrieve one SMS |
Cross-cutting behavior
Every request passes through withApiAuth (src/lib/api/middleware.ts):
- Auth — validates Bearer token against
api_keystable (sha256 hash). - Rate limit — Upstash sliding window: 100 req / 60s per
orgId. Skipped if Upstash env vars absent. - Context — handler receives
{ orgId, apiKeyId, environment }.
POST send endpoints additionally:
- Idempotency —
Idempotency-Keyheader replays the stored response for 24h. - Usage limit — free-tier caps enforced in live env; Pro allows overage; test env bypasses.
Response envelopes
Single resource:
{ "id": "msg_...", "channel": "email", "status": "sent", "created_at": "..." }
List:
{ "data": [...], "has_more": true, "next_cursor": "msg_..." }
Batch:
{ "data": [{"id":"msg_...","status":"sent"}, ...], "total": 2, "successful": 2, "failed": 0 }
Error: see errors.md.
See also: authentication.md, emails.md, sms.md, rate-limits.md, idempotency.md.