External API integration
Serveon's external API starts under /api/v1. Tenant identity is resolved from the API key, and every response uses a predictable JSON envelope so integrations can handle success and failure consistently.
GET /api/v1/health. The documented scopes for menu, orders, tables, service requests, and notifications are reserved for upcoming endpoint releases.Base path
/api/v1
Current endpoint
GET /health
Auth modes
live and test keys
Authentication
Send the raw API key on every request. The API accepts either an authorization bearer token or an X-API-Key header.
sk_live_<keyId>_<secret>
sk_test_<keyId>_<secret>Authorization: Bearer sk_test_<keyId>_<secret>
# or
X-API-Key: sk_test_<keyId>_<secret>API key record
Keys are stored in the top-level Firestore apiKeys collection. Raw secrets are shown once and are never stored.
apiKeys/{keyId}
tenantId: string
name: string
secretHash: string
secretPreview: string
scopes: string[]
enabled: boolean
allowedOrigins: string[]
expiresAt: Timestamp | null
createdAt: Timestamp
createdBy: string
revokedAt: Timestamp | nullSecret hashing
New secrets use hmac-sha256: hashes generated with API_KEY_PEPPER. Keep that environment variable stable because existing key hashes depend on it.
The authenticator also accepts legacy unprefixed HMAC andsha256: hashes so older records can be migrated without an immediate outage.
Scopes
| Scope | Purpose | Status |
|---|---|---|
| menu:read | Read menu data | Reserved |
| orders:read | Read orders | Reserved |
| orders:write | Create orders | Reserved |
| orders:update_status | Update order lifecycle status | Reserved |
| tables:read | Read table metadata | Reserved |
| service_requests:read | Read service requests | Reserved |
| service_requests:write | Create service requests | Reserved |
| notifications:send | Send notifications | Reserved |
Health check
Use the health endpoint to validate API key format, secret hash, tenant resolution, mode, audit logging, CORS headers, and rate-limit headers.
Method
GET
Path
/api/v1/health
Required scope
none
Rate limit
60/min/key
curl -H "Authorization: Bearer sk_test_<keyId>_<secret>" \
http://localhost:3000/api/v1/health{
"success": true,
"data": {
"ok": true,
"tenantId": "tenant-id",
"mode": "test",
"keyId": "key-id"
}
}Responses and limits
{
"success": true,
"data": {}
}{
"success": false,
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key"
}
}Rate-limit metadata
Successful and rate-limited responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. Reset is a Unix timestamp in seconds.
CORS and browser use
Server-to-server integrations do not need CORS. The API helper supports exact-origin allowlists from each API key record and returns Vary: Origin with the allowed methods and headers.
Authorization
Content-Type
Idempotency-Key
X-API-Key
X-Request-IDSetup checklist
- 1Set `API_KEY_PEPPER` and keep it stable across deploys.
- 2Create an `apiKeys/{keyId}` document with a hashed secret and tenant ID.
- 3Grant only the scopes the integration needs.
- 4Use a test key first: `sk_test_<keyId>_<secret>`.
- 5Call `/api/v1/health` and confirm `tenantId`, `mode`, and `keyId`.
- 6Monitor `apiRequestLogs` and `apiRateLimits` after rollout.