text
Rich text that auto-fits its bounding box.
See also
This is the import-time schema. To override an existing text layer's properties at generation time, see Element Properties → Text.
font_size is a required starting hint
font_size is required on text and button, and it is the requested starting size, not a fixed render size. The system renders at this value and decrements down to min_font_size until the text fits the layer bounding box. If even min_font_size doesn't fit, the import emits a text_fit_failed warning (or fails under ?strict=true).
On round-trip via GET /designs/{uuid}/as-import, the returned font_size is the rendered (post-fit) value — whether or not you supplied min_font_size. This is not warned about: the export cannot tell whether a resize happened, so the note would fire on every text layer and mean nothing.
min_font_size itself is never returned by the export. A design that auto-resizes stores that as a generation setting — the renderer may reshrink the text every time the design is generated — and the import contract has no equivalent yet, so returning the floor would claim a fidelity the round-trip does not deliver. The export drops it and emits a property_not_representable warning naming the layer. font_size still carries the rendered size, which does round-trip.
A min_font_size greater than font_size is accepted, not rejected: the floor is clamped down to the rendered size, and the layer then simply renders at that fixed size with no shrink range.
Omitting it would mean "start at 1000px and let the fitter decide" — a trap rather than a default, since a short string in a large box comes back enormous. Stating the ceiling is part of describing the layer.
| Property | Type | Notes |
|---|---|---|
payload | string | Text content. Up to 2048 chars (invalid_payload beyond). Blank values are accepted: an explicit "", a whitespace-only string (e.g. " ") and an omitted payload are all valid — an omitted one defaults to "", and the layer renders empty. |
color | hex color | Text color. Defaults to #000000. See Color & Length Conventions. |
font | string (uuid) | Font family UUID. List available fonts via GET /fonts. Defaults to Roboto. |
font_size | number | Required. Starting hint — the system shrinks to fit. static: integer 2–1000 (px). printer: float 0.48–240 (pt). |
min_font_size | float | Floor for the auto-resize shrink. Same ranges as font_size. When omitted the system floors at the minimum. Not returned by GET /designs/{uuid}/as-import — see the note above. |
font_weight | int | 100–900. Defaults to 400. |
font_style | enum | normal | italic. |
text_align | enum | left | center | right. |
vertical_align | enum | top | middle | bottom. |
text_decoration | enum | underline | strikethrough | diagonal-strikethrough. |
text_transform | enum | uppercase | lowercase | titlecase. |
text_decoration_color | hex color | Color of the underline / strikethrough rule. Hex/CMYK only — no gradient. See Color & Length Conventions. |
line_height | int | 1–500, a percentage of font_size (130 = 1.3× line spacing). Defaults to 130. Only applied to multiline text. Always present in as-import output. |
char_spacing | int | −100–1000. Letter tracking. Defaults to 0. (The field is char_spacing — not letter_spacing.) |
skew_y | float | −20–20. Vertical shear, for faux-italic / slanted text. |
background_color | hex color | Fill behind the text box. Hex/CMYK only — no gradient. See Color & Length Conventions. |
rotation | float | 0–360 inclusive. |
opacity | int | 0–100. Defaults to 100. |
stroke | object | { color, width } — outline around the glyphs. See Shared Object Shapes for ranges. |
shadow | object | { blur, offset_x, offset_y, color }. See Shared Object Shapes for ranges. |
padding | object | int | { vertical, horizontal }, or one number for both. Signed — static / animated: integers −1000–1000; printer: floats in the format's unit. A negative value pulls the background box inside the glyph run. |
background_fill | enum | normal (box hugs the glyph run) | width (box spans the layer). Optional — omit it and the platform default (normal) applies. |
background_mode | enum | highlight (a box per line) | paragraph (one box behind the block). Optional — omit it and the platform default (highlight) applies. |
background_radius | number | Corner rounding of the background box. static / animated: integer px 0–1000. printer: float ≥ 0 in the format's unit. |
background_offset_x | number | Shifts the background box horizontally; signed. static / animated: integer −1000–1000. printer: float in the format's unit, unbounded. |
background_offset_y | number | Shifts the background box vertically; signed. Same ranges as background_offset_x. |
side_border | object | A rule along one edge — { side, thickness, color, rounded, padding, offset, spread }. side is required; the rest shape it. See below. |
The side border is one rule, on one edge
side_border.side picks the edge and the other six members shape it:
| Member | Type | Notes |
|---|---|---|
side | enum | Required. left, right, top, bottom, or none to remove one. |
thickness | float | Rule thickness. static / animated: px, 0–1000. printer: float in the format's unit, no upper bound. |
color | color | Rule colour. Hex/CMYK only — no gradient. See Color & Length Conventions. |
rounded | boolean | Round the rule's ends. Defaults to false. |
padding | float | Gap between the text and the rule. Same units as thickness. |
offset | float | Shifts the rule along the perpendicular axis; signed, so it moves either way. |
spread | float | Extends the rule past the text box at both ends. |
Omit side_border entirely for a layer with no rule — an import always creates a new design, so there is nothing to clear. side: "none" is accepted and means the same thing; it earns its place at generation time, where it removes a rule the design already has.
The lengths are floats, so a hairline rule like 0.08 is expressible.
Not text properties
letter_spacing (use char_spacing), max_lines and text_shadow (button-only) are not accepted on text — each is unknown_field. Per-character styling travels as inline markup inside payload, not as a separate field.
