API Overview
The Typograph API lets your systems, and AI agents acting for your users, manage templates and projects, generate press-ready documents, convert files, and collaborate. For AI agents, the MCP server offers the same capabilities as tools.
An integration built on names from before Typograph's naming convention: Renamed fields and paths lists every old name and its new one.
Base URL
https://api.typograph.nl
API Gateway Architecture
All API requests go through the Typograph API Gateway, which handles:
- Authentication - OAuth 2.0 token validation
- Authorization - Scope-based access control
- Rate Limiting - Request throttling per client
- Request Routing - Proxying to internal microservices
Services
The API consists of these services:
| Service | Description | Base Path | Scope |
|---|---|---|---|
| Identity | Users, sessions, organizations, OAuth clients | /v1/identity/ | identity |
| File | Teams, projects, templates, media, sharing | /v1/file/ | file |
| Publisher | PDF and image generation | /v1/publisher/ | publisher |
| Converter | File format conversion | /v1/converter/ | converter |
| Document | Template validation and schema upgrade | /v1/document/ | document |
| Webhook | Event subscriptions and deliveries | /v1/webhook/ | webhook |
| Subscription | Subscription plan, usage, add-ons | /v1/subscription/ | subscription |
Quick Start
1. Get an Access Token
curl -X POST https://api.typograph.nl/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=file document publisher"
2. Make API Requests
curl https://api.typograph.nl/v1/file/teams \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Rate Limiting
Rate limits are tiered by your organization's subscription and split across four layers (burst, hourly, daily, monthly) and five endpoint categories (general, file, converter, publisher, webhook), plus ai for the portal's AI assistant. Anonymous requests are capped at 100/hour on the general category only.
Rate Limit Headers
Responses use the IETF draft rate-limit headers:
| Header | Description |
|---|---|
RateLimit | Current status, format: "category";r=remaining;t=reset_seconds |
RateLimit-Policy | Configured policies (quota + window per layer) |
Retry-After | On 429, seconds until you should retry |
Example:
RateLimit: "general";r=3542;t=1800
RateLimit-Policy: "general_hourly";q=3600;w=3600, "general_burst";q=50;w=60
Rate Limit Exceeded
{
"error": "rate_limit_exceeded",
"error_description": "Hourly rate limit exceeded for general endpoints."
}
See Rate Limiting for the full breakdown, per-layer error codes, and handler patterns.
Request Headers
Required Headers
| Header | Description |
|---|---|
Authorization | Bearer {access_token} for authenticated requests |
Content-Type | application/json for request bodies |
Response Headers
| Header | Description |
|---|---|
X-Powered-By | Typograph (www.typograph.nl) |
X-Typograph-Request-Id | UUID v7 correlation ID for support |
X-Typograph-User-Id | The ID of the person your token acts for; absent for a token without a person (client credentials) |
X-Typograph-Organization-Id | The ID of the organization the request worked in, the one your token reaches (Which organization a token reaches) |
RateLimit | Current window status (see Rate Limiting) |
RateLimit-Policy | Configured rate-limit policies |
Asynchronous Processing
Most operations are processed asynchronously using a job-based architecture:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Create Job │ ──▶ │ Processing │ ──▶ │ Completed │ ──▶ │ Download │
│ (POST) │ │ (async) │ │ (poll) │ │ (GET) │
└─────────────┘ └─────────────┘ └─────────── ──┘ └─────────────┘
- Create Job - Submit a request, receive a job ID with
queuedstatus - Processing - Job progresses through stages (downloading, processing, uploading)
- Completion - Job reaches
completedorfailedstatus - Download - Retrieve generated files using the job ID
Webhook Notifications
Instead of polling, subscribe to webhooks to receive real-time notifications:
| Event | Description |
|---|---|
publication.completed | Publisher job finished successfully |
publication.failed | Publisher job failed |
conversion.completed | Converter job finished successfully |
conversion.failed | Converter job failed |
See Webhooks for setup, delivery semantics, and signature verification.
File Retention
Generated files are available for 4 days after job completion. After this period, files expire and return 410 Gone.
Job Status Values
Publisher Job States
| Status | Description |
|---|---|
queued | Job is waiting to be processed |
queued_by_csv_processor | Child job queued by CSV batch processing |
queued_by_image_generator | Job queued for image generation |
downloading | Downloading template and data files |
processing_csv | Processing CSV data file |
waiting_for_rows | A CSV merge whose rows are queued, waiting for them to print; printed_row_count and failed_row_count show how far it is |
merging | A CSV merge whose rows have all ended, being finished |
generating | Generating output document |
uploading | Uploading generated files |
completed | Job finished successfully |
failed | Job encountered an error |
expired | Generated files have expired |
Converter Job States
| Status | Description |
|---|---|
queued | Job is waiting to be processed |
downloading | Downloading source file |
converting | Converting file to target format |
uploading | Uploading converted file |
completed | Conversion finished successfully |
failed | Conversion encountered an error |
expired | Converted files have expired |
Error Handling
The API uses standard HTTP status codes:
| Code | Description |
|---|---|
200 | Success |
201 | Resource created |
204 | Success with no content |
400 | Invalid request parameters |
401 | Authentication required |
403 | Insufficient permissions (scope) |
404 | Resource not found |
410 | File expired (no longer available) |
422 | Validation failure |
429 | Rate limit exceeded |
500 | Internal server error |
503 | Service unavailable |
Error Response Format
Error responses follow a hybrid format compatible with OAuth 2.0 (RFC 6749) and inspired by RFC 9457 Problem Details:
{
"error": "invalid_request",
"error_description": "Email is required.",
"request_id": "019397ab-cdef-7890-abcd-ef1234567890"
}
| Field | Type | Description |
|---|---|---|
error | string | Machine-readable error code |
error_description | string | Human-readable error message |
request_id | string | UUID v7 correlation ID (also in X-Typograph-Request-Id header) |
type | string | (optional) URI to error documentation |
details | array | (optional) Field-level validation errors |
Standard Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
400 | invalid_request | Malformed request or missing parameters |
400 | validation_error | Field validation failures |
401 | unauthorized | Missing or invalid authentication |
401 | invalid_token | Token expired or revoked |
403 | access_denied | Insufficient permissions or scope |
404 | not_found | Resource does not exist |
405 | method_not_allowed | HTTP method not allowed |
409 | conflict | Resource conflict (duplicate, concurrent edit) |
409 | in_trash | What the call works on is in the trash, or in a project or team that is: restore it first (see File Service) |
409 | container_in_trash | A restore of something whose project or team is still in the trash |
409 | rotation_in_progress | A webhook secret rotation inside the 24-hour overlap of the previous one (see Rotate Secret) |
410 | gone | The files of a publisher or converter job that has expired (see File Retention) |
422 | validation_error | Valid syntax but semantic validation failed |
429 | rate_limit_exceeded | Too many requests |
500 | server_error | Internal server error |
503 | service_unavailable | Service temporarily unavailable |
A few endpoints return a code of their own, listed with the endpoint. Using a premade template (File Service) can answer 400 with premade_template_not_ready (no package yet), premade_template_unavailable (the package could not be downloaded) or premade_template_invalid (the package is not an importable zip).
Validation Errors
When validation fails, the response includes a details array with field-level errors:
{
"error": "validation_error",
"error_description": "Request validation failed",
"request_id": "019397ab-cdef-7890-abcd-ef1234567890",
"details": [
{
"field": "email",
"code": "required",
"message": "Email is required."
},
{
"field": "handle",
"code": "too_long",
"message": "Handle must be at most 255 characters."
}
]
}
Request Correlation
Every request is assigned a unique request_id (UUID v7):
- Returned in the
X-Typograph-Request-Idresponse header on all responses - Included in the JSON body for error responses
- Used for request tracing and debugging
When contacting support, always include the request_id from the error response for faster issue resolution.
API Discovery
OAuth Server Metadata
Discover OAuth endpoints programmatically:
curl https://api.typograph.nl/.well-known/oauth-authorization-server
API Home Document
Get API metadata and the gateway's routes, with their methods and scopes. It needs no token and counts against the anonymous rate limit:
curl https://api.typograph.nl/
It answers name, version, website_url, portal_url and documentation_url, the OAuth endpoints
by name, and under resources the routes of each service, each with its path, methods, scopes and
authentication: public (no token), token (an access token) or internal (for the platform's own
services).
Supports JSON Home format (RFC draft):
curl https://api.typograph.nl/ \
-H "Accept: application/json-home"
OpenAPI Reference
Explore the complete API specification with the interactive Swagger UI:
Using the API
Typograph's REST API speaks standard HTTP + JSON, so any HTTP client works — fetch/axios in the browser or Node.js, requests in Python, cURL, Postman, etc. See Authentication for how to obtain an access token, and browse the OpenAPI Reference for the full endpoint surface.
Support
- Documentation: docs.typograph.nl
- Contact: the support guide
- Status Page: status.typograph.nl