Turn a flat ad image into editable layers — a background plate, product and logo cutouts, live text with typography, and vector shapes — returned as one structured JSON document. Trained exclusively on licensed data for safe commercial use.
Latency is on average under 1 minute.
Input Assumptions
The input is assumed to be a flat ad. Valid images that aren't ads — an ordinary photograph, say — are out of scope, and the result isn't guaranteed.
Fields the API doesn't recognize are currently ignored rather than rejected, so check your spelling — a mistyped parameter name fails silently and you get default behavior.
Submissions are not idempotent — a retried POST is a new job. Failed jobs are never billed.
Response Handling
Submitting returns a request_id and a status_url to poll. On completion the status body carries a pointer, not the layers: fetch result.url to get the layer document, then each image layer's asset_path separately.
One caveat when reporting a problem: the request_id in a response body identifies that response, not your job. The durable handle is the id inside the status_url you got at submit — quote that.
The Layer Document
{
"canvas": { "width": 1000, "height": 1500 },
"font_stylesheets": ["https://fonts.googleapis.com/css2?family=Inter…"],
"layers": [ … ]
}| Field | Type | Description |
|---|---|---|
canvas | object | width / height, matching the input image. |
font_stylesheets | string[] | Returned in the result. Google Fonts stylesheet URLs covering every font referenced by text layers. Load these before rendering. |
layers | array | Every layer in the ad. Sort by z_order before rendering — array order is not guaranteed to match paint order. |
On every layer:
| Field | Type | Description |
|---|---|---|
id | string | Result-scoped: background_1, text_3, image_1, shape_1, plus the literal canvas_background. A copy layer arrives as a pair, suffixed _font and _svg — text_3_font beside text_3_svg. |
type | string | image, vector, or text. |
subtype | string | background, logo, product, primary_copy, secondary_copy, cta, compliance, icon, decorative. |
bbox | object | x, y, width, height in canvas pixels. |
z_order | integer | Paint order, from 0 upward with no gaps; lowest paints first. Sort on this — don't rely on array order. Each half of a copy pair takes its own number, so after dropping hidden layers, gaps in the visible sequence are expected. |
hidden | boolean | Present and true only on the half of a copy pair the mode did not choose. Skip those layers. Absent means visible — it is never false, so test for hidden === true. |
Image layers:
| Field | Type | Description |
|---|---|---|
asset_path | string | Hosted image. Cutouts are transparent. PNG, except on the _svg half of a copy pair, which is an SVG of the traced letterforms. |
image_fit.object_fit | string | cover or contain, with CSS object-fit semantics. |
image_fit.object_position_ximage_fit.object_position_y | string | Optional. Where the image sits in its box when the fit leaves slack — left/center/right and top/center/bottom. Absent means centered. |
Vector layers:
| Field | Type | Description |
|---|---|---|
style.background_color | string | Solid fill, #RRGGBB. |
style.background_gradient | object | stops[] of {offset, color}, plus kind and angle_deg. Stop colors may carry an 8-digit #RRGGBBAA alpha suffix. |
style.border_radius_px | number | Corner radius, when present. |
style.box_shadow | object | Optional. offset_x_px, offset_y_px, blur_px, spread_px, color and inset (boolean), with CSS box-shadow semantics. |
Vector layers carry no shape enum — treat them as boxes with a fill.
Text layers:
| Field | Type | Description |
|---|---|---|
text | string | Live, editable content. Explicit line breaks are \n and are preserved when you re-render. |
text_style.color | string | #RRGGBB. |
text_style.font_family | string | A CSS font stack — nearest match first, fallbacks inline. |
text_style.font_weight | integer | 100–900. |
text_style.font_size_px | number | Pixels. |
text_style.letter_spacing_px | number | Pixels. Omitted when zero. |
text_style.line_height | number | Unitless multiplier over font size. |
text_style.text_align | string | Alignment of the text itself: left, center, right. Optional. |
text_style.align_x / align_y | string | Alignment of the block inside its box, as CSS flexbox values: flex-start, center, flex-end. |
text_style.no_wrap | boolean | true forbids wrapping inside the box. |
text_style.uppercase / underline / italic | boolean | Style flags. |
Click to view a real copy pair (JSON, text_mode: svg)
[
{
"id": "text_5_svg",
"type": "image",
"subtype": "primary_copy",
"bbox": { "x": 150.0, "y": 409.05, "width": 764.0, "height": 139.95 },
"z_order": 8,
"asset_path": "https://temp.bria.ai/results/860f1a2b73f847e59f284d6f860f2ddb/text_5.svg",
"image_fit": { "object_fit": "contain" }
},
{
"id": "text_5_font",
"type": "text",
"subtype": "primary_copy",
"bbox": { "x": 150.0, "y": 409.05, "width": 764.0, "height": 139.95 },
"z_order": 9,
"hidden": true,
"text": "40% OFF*",
"text_style": {
"color": "#FFFFFF",
"font_family": "'Montserrat', 'Inter', 'Helvetica Neue', Arial, sans-serif",
"font_weight": 900,
"font_size_px": 149.58,
"letter_spacing_px": -1.93,
"line_height": 1.0,
"align_x": "flex-start",
"align_y": "center",
"no_wrap": true,
"uppercase": false,
"underline": false,
"italic": false
}
}
]With text_mode: font the same pair returns with hidden: true on text_5_svg instead.
The two halves of a copy layer
Copy comes back in both forms regardless of text_mode, so one result can be rendered either way and an editor can offer the choice without a second job. Each copy slot therefore produces two layers:
| Layer | Type | Carries |
|---|---|---|
<slot>_svg | image | asset_path to an SVG of the letterforms traced out of the reference ad. |
<slot>_font | text | text and text_style — live, editable, in the nearest matching font. |
Both halves carry the copy's subtype (primary_copy, cta, and so on), share the same bbox, and take their own z_order.
text_mode decides which one is live. The other carries hidden: true and must not be drawn — render both and the ad shows its copy twice.
svg is best suited to plain, solid-color type where the original appearance must be preserved. Choose font when the copy will be edited, resized, or localized, and for text with fills, multiple colors, or overlapping elements — filled fonts are not supported in SVG and return a transparent layer.
A wordmark logo — a brand written out in lettering, as against a pictorial mark — is paired the same way, except that both halves are image layers: _svg is the traced outline and _font is the raster crop (on a wordmark the _font suffix marks the fallback half, not a text layer). A logo is never typeset.
Layers with nothing to pair, which is most of them, keep their plain id and never carry hidden.
Two things worth doing rather than ignoring: skipping the hidden half saves an asset download per copy layer, and in svg mode nothing needs font_stylesheets at all, because no text layer is drawn (the field may also be omitted entirely when no webfont is needed, so read it defensively).
Rendering It Back
Drop every layer with hidden: true, then sort the rest by z_order — the array often arrives already in that order, but not always. Then absolutely position each layer at its bbox, inside a canvas-sized stage. Image layers become an <img> with the given object-fit; vector layers become a div with the fill; text layers become a flex box using align_x and align_y. Load font_stylesheets first, or your text metrics will be wrong.
The examples above come from a full-resolution (enterprise) run, which is why the canvas exceeds 800 px.
Exactly one image — a publicly reachable URL, or a data:image/…;base64,… URI. PNG, JPEG or WEBP, up to 10 MB and 800 px per dimension (enterprise accounts have no dimension cap). More than one entry is rejected. This parameter is required.
Where each copy layer's glyphs come from. svg traces them out of the reference ad as vector outlines, so the original letterforms are kept exactly; font typesets them as live, editable text in the nearest matching font. Either way both forms come back and one is marked hidden — see The two halves of a copy layer. The default is svg so the result is faithful to the original by default; the editable half is always present to switch to.
Optional URL for receiving the result via webhook when the async job completes, with the same body as a status poll. See Webhooks.
curl -i -X POST \
https://engine.prod.bria-api.com/v2/ads/delayer \
-H 'Content-Type: application/json' \
-H 'api_token: string' \
-d '{
"attachments": [
"https://bria-image-repository.s3.amazonaws.com/images/c41b39ec1a69a5d3.jpg"
],
"text_mode": "svg"
}'Accepted (Asynchronous). You can track the progress and retrieve the final result using the Status Service. For more details, refer to the Status Service section.
{ "request_id": "860f1a2b73f847e59f284d6f860f2ddb", "status_url": "https://engine.prod.bria-api.com/v2/status/860f1a2b73f847e59f284d6f860f2ddb" }