Documents
A Typograph document (also called a template when saved in the file service) is the versioned JSON structure that the editor reads, the validator checks, and the publisher renders. This page covers the top-level shape; the remaining pages in this section zoom in on pages, elements, and swatches.
Top-Level Shape
{
"version": "1.0.0",
"type": "template",
"metadata": { ... },
"font_data": [ ... ],
"swatches": [ ... ],
"styles": { ... },
"spreads": [ ... ],
"active_spread_index": 0,
"user_data": null
}
Every key Typograph defines is snake_case, as in all Typograph JSON. Keys taken from an external format keep their own names: the font descriptions inside font_data follow the Google Fonts API (see Font Data).
Documents saved with the older key names are still read (see Older key names).
| Property | Type | Required | Description |
|---|---|---|---|
version | string | yes | Schema version — must match the Typograph schema, currently 1.0.0 |
type | string | yes | Either template (a reusable design) or clip (a fragment) |
metadata | object | yes | name, author, created_at (when the document was first saved; kept on every later save) and updated_at |
font_data | array | yes | Fonts referenced by the document's text elements |
swatches | array of Swatch | yes | Color swatches used for fills, strokes, shadows, gradients. At least 4 required. |
spreads | array of Spread | yes | The spreads in the document, each holding one or more pages and the elements on them; see Pages |
styles | object | no | Paragraph, character, table and cell styles of rich text |
stories | array | no | Text stories that rich-text elements refer to |
roles | array | no | The edit-permission roles built for this document |
masters | array of Spread | no | Master spreads the document's pages apply |
active_spread_index | number | no | Spread to open first in the editor |
facing_pages | boolean | no | Whether the pages are shown as facing pairs |
first_page_left | boolean | no | Whether page 1 is a left-hand page, so pages 1 and 2 form the first pair |
user_data | object | no | Free-form data of your own; Typograph stores it and does not read it |
brand_colors | object | deprecated | Legacy alias for swatches — new documents should use swatches |
Use the Document Service (POST /v1/document/validate) to confirm a payload conforms to the schema before sending it to the publisher.
Type: template vs clip
template— a complete, renderable document. This is what the editor opens, what the publisher turns into PDFs/images, and what the file service stores under/v1/file/templates.clip— a reusable fragment (e.g. a logo block, a call-out) that can be dropped into a template.
Swatch-Based Color System
Typograph does not embed raw colors in individual elements. Instead, the document defines a palette of swatches (at the document level), and elements refer to them by UUID for fills, strokes, shadows, and gradients. This lets a color change in one place propagate throughout the document. See Styles for the swatch model.
Font Data
font_data is the authoritative list of fonts the document uses. Each entry has an index, a source, an is_active flag, a uuid, and a data object describing the font family and its files. The data object follows the shape of the Google Fonts API, so its keys keep that API's names, such as lastModified. The editor fetches font files through the file service's font presigned-URL endpoints — see File Service.
Schema Versioning and Upgrade
Schema versions are semver-tagged and incompatible across major versions. The Document Service exposes:
POST /v1/document/validate— check whether a payload conforms to the current schemaPOST /v1/document/upgrade— migrate a payload from an older schema to the current version
Always validate a document before sending it to the publisher — the publisher rejects invalid documents outright.
Older key names
The keys of the document were brought in line with one naming convention: a timestamp ends in _at, a
boolean that states something starts with is_ or has_, a reference into the document ends in
_uuid, and nothing is abbreviated. A document or package saved with the older names keeps working:
the editor, the canvas, the form widget, the document, publisher and converter services and the file
service read each older key as the current one, and write only the current names. The Document
Service's /upgrade returns a document in the current names. Write new documents in the current
names; the older ones are read, not documented further.
| Where | Older name | Current name |
|---|---|---|
| Document | meta_data (creation_date, modification_date) | metadata (created_at, updated_at) |
font_data[] | active; data.isVariable, data.instanceCoordinates, data.modification_date | is_active; data.is_variable, data.instance_coordinates, data.lastModified |
layout_fonts[] | uuid | font_uuid |
brand_colors.colors[] | rgba | hex |
| Swatches | rgb.R/G/B, cmyk.C/M/Y/K, lab.L; inklist; tint_value; gradient samples[].pos | rgb.r/g/b, cmyk.c/m/y/k, lab.l; ink_list; tint; samples[].position |
| Text properties | marker_char, list_start_at, underline_color, strikethrough_color, fill_gradient_*, stroke_gradient_* | marker_character, list_start_number, underline_swatch_uuid, strikethrough_swatch_uuid, gradient_fill_*, gradient_stroke_* |
| Story tables and table styles | alt_fill_a_uuid, alt_col_fill_a_uuid, alt_first_count, alt_col_next_count, alt_fill_a_tint, … | alternating_row_fill_a_swatch_uuid, alternating_column_fill_a_swatch_uuid, alternating_row_first_count, alternating_column_next_count, alternating_row_fill_a_tint, … |
| Spreads | page_name, page_active, locked, cover, fill_tint_value, stroke_tint_value | name, is_active, is_locked, is_cover, fill_tint, stroke_tint |
| Pages | fill_tint_value; guides visible | fill_tint; guides is_visible |
| Elements | id, hidden, locked, shadow, over_flow (previous_uuid, next_uuid), native_rotation_cx/cy, border_size, native_border_size, fill_tint_value, stroke_tint_value, layer_info.open | index, is_hidden, is_locked, has_shadow, overflow (previous_element_uuid, next_element_uuid), native_rotation_center_x/y, stroke_width, native_stroke_width, fill_tint, stroke_tint, layer_info.is_open |
| Element layout and limits | auto_layout.column_gab, row_gab, margin_left/right/top/bottom; auto_size.page_height_native_offset, auto_size.listeners[].uuid; edit_constraints.move.dx/dy, edit_constraints.resize.aspect_lock | column_gap, row_gap, left_margin, right_margin, top_margin, bottom_margin; native_page_height_offset, element_uuid; horizontal, vertical, lock_aspect_ratio |
| Shapes and images | type circel; native_radiuses; line p1_native, p2_native; save_paths, save_path; image key; asset sizes w, h; asset web_url | circle; native_radii; native_start_point, native_end_point; saved_paths, saved_path; image_id; width, height; editor_url |
| Rich text | story_data, tag_list, native_autoleading, native_margin_button, native_columns_cap, native_lang, native_min_chars_before/after, pod_tekst_style, native_text_stroke_size, gradient_text_fill_*, gradient_text_stroke_*, text_fill_tint_value, text_stroke_tint_value | story, tags, native_auto_leading, native_margin_bottom, native_column_gap, native_language, native_min_characters_before/after, pod_text_style, native_text_stroke_width, native_gradient_text_fill_*, native_gradient_text_stroke_*, text_fill_tint, text_stroke_tint |
| Rich text layout | top_ly, col_edges; cells col, col_span, cell_x/y/w/h; words line_break | top_y, column_edges; column, column_span, x/y/width/height; is_line_break |
| Package | templatebundle.json | template_bundle.json |
A few older keys are read and dropped, because the current document no longer has them:
rotation_center_set, a rounded rectangle's TL, TR, BL and BR (its radii are native_radii),
and a text override's any_property.