API
Every operation ScaiScribe exposes, across both transports. The SDKs wrap these; you can also call them directly.
REST#
Base URL: https://scaiscribe.scailabs.ai/v1
All endpoints require Authorization: Bearer <token> unless marked PUBLIC.
Response envelopes are resource-keyed, not generic. List endpoints wrap in a plural resource key ({"themes": […]}, {"fonts": […]}, {"templates": […]}); job-producing endpoints return top-level {status, job_id, outputs}; errors always use the {"error": {code, message, details, request_id}} envelope. There is deliberately no generic data wrapper — the key tells you what you're holding.
Documents#
| Method | Path | Body / params | Returns |
|---|---|---|---|
POST |
/v1/documents |
{format, theme?, title?, metadata?} |
DocumentEnvelope |
GET |
/v1/documents/{doc_id} |
— | DocumentEnvelope (with spec) |
DELETE |
/v1/documents/{doc_id} |
— | {ok} |
POST |
/v1/documents/{doc_id}/close |
— | {ok} |
PATCH |
/v1/documents/{doc_id} |
{operations: PatchOp[]} |
{doc_id, version, applied} |
POST |
/v1/documents/{doc_id}/finalize |
{formats?: string[], sync?: bool} |
{doc_id, version, renders: RenderArtefact[]} |
POST |
/v1/documents/{doc_id}/preview |
{mode} |
preview payload |
POST |
/v1/documents/from_template |
{template_id, data, format?, theme?} |
DocumentEnvelope |
POST |
/v1/documents/ingest |
multipart: file, format, sync |
IngestResponse |
PatchOp shape#
1 2 3 4 5 6 7 8 | |
Jobs#
| Method | Path | Returns |
|---|---|---|
GET |
/v1/jobs |
List the caller's OWN jobs. Strict per-user isolation. Supports status, limit, offset query params. |
GET |
/v1/jobs/{job_id} |
Poll one of your own jobs; returns JobEnvelope. 404 if the job exists in your tenant but was submitted by a colleague. |
DELETE |
/v1/templates/{template_id} |
Soft-delete a template in your tenant (any authenticated user). |
Both endpoints scope strictly to tenant_id == caller.tenant_id AND submitted_by == caller.user_id. A user can't see colleagues' jobs even by guessing IDs — colleagues' jobs return 404, not 403, so existence isn't leaked. Operators wanting tenant-wide visibility (across all submitters) should use /v1/admin/jobs (requires tenant_admin or higher).
Sync-wrapped operations (finalize, ingest_document, preview) block until the job completes and return the final result inline. Pass sync=false to those endpoints to get a JobEnvelope immediately and poll yourself.
Themes#
| Method | Path | Notes |
|---|---|---|
GET |
/v1/themes |
Every theme visible to your tenant (builtins + your registered themes). Rows carry the resolved font + colour scheme inline — build a theme picker in one round-trip. |
GET |
/v1/themes/{theme_id} |
Full theme JSON in registered form (what you'd PUT back). |
PUT |
/v1/themes/{theme_id} |
Create/update a tenant theme. Body is a theme JSON; brand onboarding is typically {"extends": "office", "fonts": {…}, "colors": {…}}. Compile-checked before persisting — 422 means nothing saved. |
DELETE |
/v1/themes/{theme_id} |
Soft-delete a tenant theme. Builtins are 403; a tenant theme shadowing a builtin reverts to the builtin. |
Assets / fonts / templates#
| Method | Path | Notes |
|---|---|---|
POST |
/v1/assets |
multipart upload; `kind=image |
GET |
/v1/assets |
paginated list |
POST |
/v1/fonts |
multipart upload, TTF/OTF/WOFF/WOFF2 — web-font wrappers are decompressed to TTF server-side so every uploaded face is embeddable; metadata (family/weight/style) extracted via FontTools |
GET |
/v1/fonts |
paginated list |
DELETE |
/v1/fonts/{font_id} |
— |
POST |
/v1/templates |
multipart upload; name, format. Response carries placeholder_schema ({name, type, required, example} per variable, derived from the template grammar) |
GET |
/v1/templates |
paginated list; rows carry placeholder_schema |
POST |
/v1/templates/{id}/preview |
Gallery preview: identity-filled instantiation (+PDF via Gotenberg). Returns download URLs + placeholder_schema + sample_variables |
Health#
| Method | Path | Auth | Returns |
|---|---|---|---|
GET |
/v1/health |
PUBLIC | {status: "ok"} |
GET |
/v1/health/ready |
PUBLIC | {status, checks} |
Admin#
18 endpoints under /v1/admin/*. Require admin-scoped tokens. See the SDK reference for usage; the admin UI is the friendliest entry point for browser-based operators.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/admin/config (PUBLIC) |
SPA bootstrap signal |
GET |
/v1/admin/me |
Current identity |
GET |
/v1/admin/health |
Dashboard counts |
GET |
/v1/admin/jobs |
Paginated job list |
GET |
/v1/admin/jobs/{id} |
Job + full result_json |
GET |
/v1/admin/users |
Paginated user list (from ScaiKey mirror) |
GET |
/v1/admin/users/{u}/roles |
List of role assignments |
POST |
/v1/admin/users/{u}/roles |
Grant a role |
DELETE |
/v1/admin/users/{u}/roles/{id} |
Revoke a role |
GET |
/v1/admin/users/{u}/groups |
Groups the user belongs to (direct + transitive) |
GET |
/v1/admin/groups |
List ScaiKey groups across visible tenants |
GET |
/v1/admin/groups/{id} |
One group + members + parent/child group context |
GET |
/v1/admin/tenants |
List of tenants (with quota usage) |
GET |
/v1/admin/partners |
List of partners |
GET |
/v1/admin/quotas/partner/{id} |
Aggregate quota usage across a partner's tenants |
GET |
/v1/admin/quotas/tenant/{id}/users |
Break a tenant's quota usage down by acting user |
POST |
/v1/admin/scaikey/rotate-webhook-secret |
Mint a fresh ScaiKey webhook signing secret (superadmin) |
GET |
/v1/admin/templates |
List templates across visible tenants |
POST |
/v1/admin/templates |
Upload a template on behalf of a tenant (multipart) |
GET |
/v1/admin/templates/{id}/download |
Presigned download URL for the source binary |
GET |
/v1/admin/templates/{id}/file |
Stream the source binary directly (fallback when presigning isn't supported) |
DELETE |
/v1/admin/templates/{id} |
Soft-delete a template |
MCP#
The MCP server is reachable at https://scaiscribe.scailabs.ai/mcp/ over Streamable HTTP. AI agents (Claude, GPT, custom) can connect and call any of the 49 scribe_* tools.
Tool catalogue#
The full tool list is mechanically derived from the running MCP server. Categories at a glance:
| Category | Tools |
|---|---|
| Document lifecycle | scribe_create, scribe_open, scribe_get_spec, scribe_set_spec, scribe_close, scribe_delete |
| Body elements (DOCX only) | scribe_add_heading, scribe_add_paragraph, scribe_add_list, scribe_add_table, scribe_add_image, scribe_add_callout, scribe_add_code_block, scribe_add_chart, scribe_add_toc, scribe_add_page_break |
| Slides (PPTX only) | scribe_add_slide, scribe_add_slide_element, scribe_set_slide_title, scribe_set_slide_layout, scribe_set_slide_notes |
| Sheets (XLSX only) | scribe_add_sheet, scribe_set_cells, scribe_set_named_range, scribe_add_sheet_chart |
| Editing | scribe_list_elements, scribe_get_element, scribe_edit_element, scribe_move_element, scribe_delete_element, scribe_find_replace |
| Render + jobs | scribe_finalize, scribe_preview, scribe_poll_job, scribe_list_jobs |
| Ingestion | scribe_ingest |
| Templates | scribe_register_template, scribe_instantiate_template, scribe_list_templates, scribe_delete_template, scribe_preview_template |
| Themes | scribe_list_themes, scribe_get_theme, scribe_register_theme, scribe_delete_theme |
| Assets | scribe_upload_asset, scribe_list_assets |
| Fonts | scribe_upload_font, scribe_list_fonts |
Every tool's input_schema is exposed by the MCP server itself — most agent runtimes auto-discover them on connect.
Connecting an agent#
For Claude Desktop, GPT-customs, or any MCP-aware agent, add the transport:
// Example MCP server config
{
"scaiscribe": {
"transport": "streamable_http",
"url": "https://scaiscribe.scailabs.ai/mcp/",
"headers": {
"Authorization": "Bearer <your scaikey-issued token>"
}
}
}
The token is the same one the REST SDKs use — get it via client_credentials against ScaiKey.
Spec format#
The document specification is the canonical payload — what gets PATCHed into a document and what comes back out of ingest_document. It's documented in detail in the Concepts → Spec format page; the formal JSON Schema lives at schema/scaiscribe.schema.json and is the source of truth for SDK-generated types.
OpenAPI#
The full OpenAPI spec is served at https://scaiscribe.scailabs.ai/openapi.json. The interactive Swagger UI at /docs is gated behind auth for the alpha; we'll move it to a public docs page once content is stable.