Core architecture concepts
- Workspace (Tenant)
- An isolated project environment connected to your own PostgreSQL database. Identified in API requests with the
x-tenant-slugheader. - Content Type
- The schema definition for a content model (e.g.,
post,author,product). Its fields dictate the validated data shapes stored in PostgreSQL. - Entry
- An individual content item adhering to a content type. Draft, review, and scheduled entries remain strictly inside Studio; published entries are served globally through the Delivery API.
- Environment
- An isolated PostgreSQL database schema (e.g.
productionby default, orstaging). Selected via thex-environmentheader.
Authentication & request headers
Authenticate all requests by passing a Delivery API key in the Authorization header, accompanied by your workspace slug in x-tenant-slug.
Authorization: Bearer YOUR_DELIVERY_API_KEY
x-tenant-slug: YOUR_WORKSPACE_SLUG
x-environment: production| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token containing an active Delivery API key generated in Studio. |
| x-tenant-slug | Yes | The unique slug of your workspace (e.g. acme-corp). |
| x-environment | Optional | Database schema environment (production by default; staging on Pro and Max). |
REST delivery endpoints
The REST Delivery API provides fast, read-only access to published content. All endpoints respond with JSON.
| Endpoint | Description |
|---|---|
| GET /v1/delivery/entries | List published entries. Query parameters: type, limit, offset, locale, sortBy, order, preview. |
| GET /v1/delivery/entries/:id | Retrieve a single published entry by its UUID or slug. Supports locale and preview. |
| GET /v1/delivery/entries/similar | Semantic vector similarity search across entries using ?text=...&limit=5 (Pro and Max). |
Example: List published entries
curl "https://api.schma.dev/v1/delivery/entries?type=post&limit=10&offset=0" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "x-tenant-slug: YOUR_WORKSPACE_SLUG"{
"entries": [
{
"id": "e4b27c62-1a3f-4e89-b765-92c10df48e01",
"slug": "getting-started-with-schma",
"dataJson": {
"title": "Getting Started with SCHMA",
"excerpt": "Learn how to connect your PostgreSQL database and query content.",
"author": "team"
},
"locale": "en-US",
"status": "published",
"publishedAt": "2026-10-16T08:00:00.000Z",
"createdAt": "2026-10-15T12:00:00.000Z",
"updatedAt": "2026-10-16T08:00:00.000Z"
}
],
"meta": {
"limit": 10,
"offset": 0,
"count": 1,
"total": 42
}
}Example: Retrieve single entry
curl "https://api.schma.dev/v1/delivery/entries/e4b27c62-1a3f-4e89-b765-92c10df48e01" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "x-tenant-slug: YOUR_WORKSPACE_SLUG"{
"id": "e4b27c62-1a3f-4e89-b765-92c10df48e01",
"slug": "getting-started-with-schma",
"dataJson": {
"title": "Getting Started with SCHMA",
"content": "Full markdown or rich text body here...",
"tags": ["cms", "postgres", "nextjs"]
},
"locale": "en-US",
"status": "published",
"publishedAt": "2026-10-16T08:00:00.000Z"
}GraphQL delivery API
SCHMA automatically synthesizes a GraphQL schema from your workspace content types. Send queries as HTTP POST requests to /v1/delivery/graphql.
curl -X POST "https://api.schma.dev/v1/delivery/graphql" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "x-tenant-slug: YOUR_WORKSPACE_SLUG" \
-H "Content-Type: application/json" \
-d '{"query": "query { entries(type: \"post\", limit: 5) { id slug data publishedAt } }"}'query GetBlogPosts($locale: String, $limit: Int) {
entries(type: "post", locale: $locale, limit: $limit) {
id
slug
data
publishedAt
}
}{
"data": {
"entries": [
{
"id": "e4b27c62-1a3f-4e89-b765-92c10df48e01",
"slug": "getting-started-with-schma",
"data": {
"title": "Getting Started with SCHMA",
"excerpt": "Learn how to connect your PostgreSQL database..."
},
"publishedAt": "2026-10-16T08:00:00.000Z"
}
]
}
}Edge caching, rate limits & quotas
Every published GET response includes production-grade HTTP caching headers:
Cache-Control: public, max-age=10, s-maxage=60, stale-while-revalidate=300
Vary: Authorization, x-environment, x-tenant-slug
ETag: W/"3a7c-4f81..."Passing a valid ?preview=TOKEN query parameter bypasses edge caching and sets Cache-Control: private, no-store, no-cache, max-age=0 to ensure real-time preview of draft changes.
Quota and rate-limit headers
Responses include rate-limit headers to help your application stay within thresholds:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum allowed requests per minute (60/min on Free, 300/min on Pro). |
| X-RateLimit-Remaining | Number of requests remaining in the current one-minute sliding window. |
| X-Quota-Limit | Total monthly delivery API requests included in your workspace plan. |
| X-Quota-Remaining | Remaining monthly delivery API quota before rate limiting engages. |
Outbound webhooks & signature verification
SCHMA can dispatch signed HTTP webhooks to your application whenever content or schema changes occur (supporting up to 2 active endpoints on Free and up to 5 on Pro).
| Event Name | Description |
|---|---|
| entry.published | Triggered when an entry is published or updated while published. |
| entry.archived | Triggered when an entry is unpublished or moved to archive. |
| schema.updated | Triggered when fields or validation rules of a content type change. |
{
"event": "entry.published",
"timestamp": "2026-10-27T08:30:00.000Z",
"tenantSlug": "acme-corp",
"environment": "production",
"data": {
"id": "e4b27c62-1a3f-4e89-b765-92c10df48e01",
"type": "post",
"slug": "getting-started-with-schma"
}
}Every webhook request includes an HMAC-SHA256 signature in the x-schma-signature header (t=timestamp,v1=signature). Verify this header using your webhook signing secret before processing payloads.
Error status codes
The Delivery API uses standard HTTP response codes to communicate success and failure:
| Code | Reason | Resolution |
|---|---|---|
| 401 Unauthorized | Missing or malformed Authorization header. | Ensure the header contains Bearer <API_KEY>. |
| 403 Forbidden | INSUFFICIENT_API_KEY_SCOPE or revoked token. | Verify the key has Delivery permissions in your Studio settings. |
| 404 Not Found | Entry or content type does not exist. | Verify the UUID or content type slug matches an active published model. |
| 429 Too Many Requests | Rate limit reached or DELIVERY_QUOTA_EXCEEDED. | Respect Retry-After or upgrade your workspace quota tier. |