Browse the docs Open

API Reference

every object, every endpoint

The complete reference, generated from the live API spec. Download it whole as Markdown, OpenAPI or Postman.

Objects

Template

A reusable design with addressable layers.

Field Type Description
uuid string Stable public identifier.
title string Human-readable name.
width integer Canvas width in pixels.
height integer Canvas height in pixels.
layers Layer[] Addressable layers and their modifications.
created_at datetime ISO-8601 creation timestamp.

Layer

A single addressable element inside a template.

Field Type Description
layer string Layer key used when overriding content.
type string One of image, text, empty, qr_code, barcode.
available_modifications object Override keys this layer accepts (image_url, text, background_color, qr_content, barcode_content).

Screenshot

A rendered capture of a web page.

Field Type Description
id string Screenshot UUID.
url string Captured page URL.
image_url string URL of the rendered image.
width integer Viewport width in pixels.
height integer Viewport height in pixels.
created_at datetime ISO-8601 creation timestamp.

Snap

A render job produced from a template or collection.

Field Type Description
id string Snap UUID.
media_url string|null URL of the finished asset, null until completed.
type string image or pdf.
status string pending, processing, completed, failed or canceled.
is_async boolean Whether the snap was queued.
webhook_url string|null Callback URL for async completion.
completed_at datetime|null When rendering finished.
last_error string|null Failure reason, when status is failed.
variants array|null Per-layer content overrides applied.
template_id string|null Source template UUID. Null for a snap rendered from an inline design, which has no template.
template_title string|null Source template name. Null for a snap rendered from an inline design.
created_at datetime ISO-8601 creation timestamp.

Endpoints

Authentication

GET /v1/auth

Verify the current token

Returns the account the token belongs to, with the company it belongs to. Use it to confirm a token is valid and to read the signed-in identity. `company` is null when the account belongs to no company.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Example request

curl

curl https://snapsbrew.com/api/v1/auth \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 Token is valid.
{
    "data": {
        "email": "[email protected]",
        "name": "Ada Lovelace",
        "company": "Analytical Engines"
    }
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}
403 Token lacks the api_requests ability.
{
    "message": "Invalid ability provided."
}

Usage

GET /v1/usage

Get current usage

Returns purchased, used and remaining requests for the active billing period.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

The response carries an `X-Request-Uuid` header you can quote in support tickets.

Example request

curl

curl https://snapsbrew.com/api/v1/usage \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 Usage for the active period.
{
    "period_start_date": "2026-05-01T00:00:00Z",
    "period_end_date": "2026-05-31T23:59:59Z",
    "period_purchased_requests": 1000,
    "period_used_requests": 240,
    "period_available_requests": 760
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}

Guides

GET /v1/guides/design

Get the design guide

Returns design guidance for building a template: canvas presets, the back-to-front layer order, typography and color rules, composition recipes, anti-patterns, and a preflight checklist. Read it before you write a `layers` array.

Auth: Bearer token Ability: api_requests Free

The catalog is the same for every account. Cache the response and refresh it on a new API version.

A guide call costs no credits and does not appear in `GET /v1/usage`.

Example request

curl

curl https://snapsbrew.com/api/v1/guides/design \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 The catalog, trimmed here to one entry.
{
    "data": {
        "typography": {
            "scale": "On a 1080px canvas: headline 64\u2013120px, subhead 36\u201356px, body 24\u201336px."
        }
    }
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}

GET /v1/guides/layers

Get the layer schema

Returns the design-time layer vocabulary: the layer object shape, every property name, the value shape of each property, and a worked example. Use it to build the `layers` array a template write accepts.

Auth: Bearer token Ability: api_requests Free

The catalog is the same for every account. Cache the response and refresh it on a new API version.

A guide call costs no credits and does not appear in `GET /v1/usage`.

Example request

curl

curl https://snapsbrew.com/api/v1/guides/layers \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 The catalog, trimmed here to one entry.
{
    "data": {
        "property_names": [
            "textContent",
            "backgroundType",
            "fontFamily"
        ]
    }
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}

GET /v1/guides/variant-properties

List variant properties

Returns every property you can apply to a layer in `variants`, with its value type, the layer types it applies to, and an example. Pair it with the `available_modifications` of a template layer.

Auth: Bearer token Ability: api_requests Free

The catalog is the same for every account. Cache the response and refresh it on a new API version.

A guide call costs no credits and does not appear in `GET /v1/usage`.

Example request

curl

curl https://snapsbrew.com/api/v1/guides/variant-properties \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 The catalog, trimmed here to one entry.
{
    "data": [
        {
            "property": "text",
            "value_type": "string",
            "applies_to": "text layers",
            "description": "Replace a text layer's content.",
            "example": {
                "layer": "headline",
                "text": "Summer Sale \u2014 40% off"
            }
        }
    ]
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}

GET /v1/guides/editor-document

Get the editor document contract

Returns the versioned v2 editor-document contract: the resource it describes, property constraints, persistence rules, conflict recovery, and a safe workflow. Read it before you change an editor document.

Auth: Bearer token Ability: api_requests Free

The catalog is the same for every account. Cache the response and refresh it on a new API version.

A guide call costs no credits and does not appear in `GET /v1/usage`.

Example request

curl

curl https://snapsbrew.com/api/v1/guides/editor-document \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 The catalog, trimmed here to one entry.
{
    "data": {
        "contract_version": 2,
        "editor_document_version": 2,
        "resource": "template.editor_document"
    }
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}

GET /v1/guides/platforms

List platform guides

Returns one line per platform: the size preset to start from, its dimensions and why that preset is the default. Read it to choose a platform, then read that platform for the full rules. The response also carries `specs_reviewed`, the month the published specs were last checked.

Auth: Bearer token Ability: api_requests Free

The catalog is the same for every account. Cache the response and refresh it on a new API version.

A guide call costs no credits and does not appear in `GET /v1/usage`.

Example request

curl

curl https://snapsbrew.com/api/v1/guides/platforms \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 The catalog, trimmed here to one entry.
{
    "data": [
        {
            "platform": "instagram",
            "name": "Instagram",
            "start_here": "instagram_post",
            "dimensions": "1080x1350",
            "why": "A 4:5 portrait post fills the most vertical space the feed will give a single image."
        }
    ]
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}

GET /v1/guides/platforms/{platform}

Get one platform guide

Returns everything one platform does to an image: how it crops the frame, the directional UI safe zones where it paints its own controls, the accepted formats and size limits, the export width and color profile, its size presets, and its rules and anti-patterns.

Auth: Bearer token Ability: api_requests Free

Parameters

Name In Type Required Description
platform path string Yes A key from the index route, or a common alias. Maximum 64 characters. Valid keys: instagram, facebook, x, linkedin, threads, pinterest, tiktok, youtube, snapchat, whatsapp, web, ads, print.

The catalog is the same for every account. Cache the response and refresh it on a new API version.

A guide call costs no credits and does not appear in `GET /v1/usage`.

An alias is accepted. `/v1/guides/platforms/insta` returns the same guide as `/v1/guides/platforms/instagram`.

Example request

curl

curl https://snapsbrew.com/api/v1/guides/platforms/instagram \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 The catalog, trimmed here to one entry.
{
    "data": {
        "platform": "instagram",
        "name": "Instagram",
        "specs_reviewed": "2026-09",
        "start_here": "instagram_post"
    }
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}
404 No guide matches the key. The body names every valid key.
{
    "message": "No platform guide matches `myspace`.",
    "available": [
        "instagram",
        "facebook",
        "x",
        "linkedin",
        "threads",
        "pinterest",
        "tiktok",
        "youtube",
        "snapchat",
        "whatsapp",
        "web",
        "ads",
        "print"
    ]
}
422 The key is longer than 64 characters.
{
    "message": "The platform field must not be greater than 64 characters."
}

GET /v1/guides/purposes

List image purpose guides

Returns one line per purpose: what that kind of image is, when to use it and the size presets that fit it. Read it to choose a purpose, then read that purpose for the full rules.

Auth: Bearer token Ability: api_requests Free

The catalog is the same for every account. Cache the response and refresh it on a new API version.

A guide call costs no credits and does not appear in `GET /v1/usage`.

Example request

curl

curl https://snapsbrew.com/api/v1/guides/purposes \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 The catalog, trimmed here to one entry.
{
    "data": [
        {
            "purpose": "link_preview",
            "name": "Link preview / meta tag image",
            "use_when": "You are shipping a page and you want the shared link to look deliberate.",
            "sizes": [
                "open_graph",
                "twitter_card"
            ]
        }
    ]
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}

GET /v1/guides/purposes/{purpose}

Get one image purpose guide

Returns the job one kind of image has to do: the size presets that fit it, the rules and failure modes specific to it, a layer recipe in the Snapsbrew vocabulary, an anti-pattern list and a preflight checklist. The `link_preview` purpose also returns the og: and twitter: meta tags to put in the page head.

Auth: Bearer token Ability: api_requests Free

Parameters

Name In Type Required Description
purpose path string Yes A key from the index route, or a common alias. Maximum 64 characters. Valid keys: link_preview, feed_post, carousel, story, profile_picture, cover, video_thumbnail, ad, product_shot, email_header, article_header, presentation_slide.

The catalog is the same for every account. Cache the response and refresh it on a new API version.

A guide call costs no credits and does not appear in `GET /v1/usage`.

An alias is accepted. `/v1/guides/purposes/og` returns the same guide as `/v1/guides/purposes/link_preview`.

Example request

curl

curl https://snapsbrew.com/api/v1/guides/purposes/link_preview \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Accept: application/json'

Example responses

200 The catalog, trimmed here to one entry.
{
    "data": {
        "purpose": "link_preview",
        "name": "Link preview / meta tag image",
        "layer_recipe": "base fill -> optional photo with a dark scrim -> headline -> supporting line -> logo."
    }
}
401 Missing or invalid token.
{
    "message": "Unauthenticated."
}
404 No guide matches the key. The body names every valid key.
{
    "message": "No purpose guide matches `wallpaper`.",
    "available": [
        "link_preview",
        "feed_post",
        "carousel",
        "story",
        "profile_picture",
        "cover",
        "video_thumbnail",
        "ad",
        "product_shot",
        "email_header",
        "article_header",
        "presentation_slide"
    ]
}
422 The key is longer than 64 characters.
{
    "message": "The purpose field must not be greater than 64 characters."
}

Templates

GET /v1/templates

List templates

Returns a cursor-paginated list of your templates.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Parameters

Name In Type Required Description
cursor query string No Cursor token from a previous response's meta.next_cursor.

Example request

curl

curl https://snapsbrew.com/api/v1/templates \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 A page of templates.
{
    "data": [
        {
            "uuid": "141e8454-8aa1-420a-bd0b-18a85ba949a2",
            "title": "Template 1",
            "width": 1200,
            "height": 630,
            "layers": [
                {
                    "layer": "review_title",
                    "type": "text",
                    "available_modifications": {
                        "text": "The worst Time-Travel movie ever made"
                    }
                }
            ],
            "created_at": "2026-05-01T12:00:00Z"
        }
    ],
    "meta": {
        "previous_cursor": null,
        "next_cursor": "eyJpZCI6MTB9"
    }
}

GET /v1/templates/sizes

List canvas size presets

Returns every canvas size preset a template write accepts as `size` — Instagram, Facebook, X, LinkedIn, Threads, Pinterest, TikTok, YouTube, Snapchat, WhatsApp, web and email, display ads, and print. Each preset gives its dimensions, aspect ratio, and the safe margin to keep content away from the edges.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Example request

curl

curl https://snapsbrew.com/api/v1/templates/sizes \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 The preset catalog.
{
    "data": [
        {
            "size": "instagram_story",
            "name": "Instagram Story (1080x1920)",
            "platform": "Instagram",
            "width": 1080,
            "height": 1920,
            "aspect_ratio": "9:16",
            "safe_margin_px": 97
        },
        {
            "size": "open_graph",
            "name": "Open Graph / Link Preview (1200x630)",
            "platform": "Web & email",
            "width": 1200,
            "height": 630,
            "aspect_ratio": "1.9:1",
            "safe_margin_px": 47
        }
    ]
}

GET /v1/templates/{templateUuid}

Get a template

Returns a single template, its parsed layers and its publish state. The layers are the draft, so read `has_unpublished_edits` to know whether the draft is what renders.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Parameters

Name In Type Required Description
templateUuid path string Yes UUID of the template.

BREAKING CHANGE. The template fields moved under a `data` key. Read `data.uuid`, not `uuid`. Every success body of this API is `{"data": ...}`, a list adds `meta` and a write adds `message`.

`size` is the canvas size preset the template is stored under, the same value POST /v1/templates returns. It reads `custom` when the dimensions match no preset. GET /v1/templates/sizes lists every preset.

`published_version` is the version number snaps and previews render. It is null until you publish the template.

`has_unpublished_edits` is true when the draft is not the same as the published version. A layer edit, a resize and an editor-document edit all set it. Call POST /v1/templates/{templateUuid}/publish to make the draft render.

Example request

curl

curl https://snapsbrew.com/api/v1/templates/<uuid> \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 The template.
{
    "data": {
        "uuid": "141e8454-8aa1-420a-bd0b-18a85ba949a2",
        "title": "Template 1",
        "size": "open_graph",
        "width": 1200,
        "height": 630,
        "layers": [
            {
                "layer": "review_poster",
                "type": "image",
                "available_modifications": {
                    "image_url": "https://snapsbrew.com/crazy-doc-brown-jailed"
                }
            },
            {
                "layer": "review_title",
                "type": "text",
                "available_modifications": {
                    "text": "The worst Time-Travel movie ever made"
                }
            }
        ],
        "published_version": 2,
        "has_unpublished_edits": true,
        "created_at": "2026-05-01T12:00:00Z"
    }
}
404 Template not found in your company.
{
    "message": "Not found."
}

POST /v1/templates

Create a template

Creates a template and generates its preview image. Requires the create-template policy.

Auth: Bearer token Ability: api_requests Gate: policy:create,Template Free

Request body

Content-Type: application/json

Field Type Required Validation Description
title string Yes required|string|max:255 Template name.
size string No nullable|in:<preset> Canvas size preset, for example "instagram_story" or "youtube_thumbnail". It sets width and height for you. GET /v1/templates/sizes lists every preset.
width integer No required_without:size|numeric|min:1|max:4000 Canvas width in pixels. Required when you send no size preset. Ignored when you send a size preset.
height integer No required_without:size|numeric|min:1|max:4000 Canvas height in pixels. Required when you send no size preset. Ignored when you send a size preset.
layers array No nullable|array Layer definitions; stored JSON-encoded. An absent or null list creates an empty canvas.

Send a `size` preset or an explicit `width`/`height`. A template saved with dimensions that match a preset is stored under that preset.

A body with no `size` and no `width`/`height` answers 422. A create has no stored canvas to fall back on.

The response holds the six fields above and nothing more. Read GET /v1/templates/{templateUuid} for the parsed layers and the publish state.

Example request

curl

curl -X POST https://snapsbrew.com/api/v1/templates \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"title":"Launch card","size":"open_graph","layers":[]}'

Example responses

200 Template created.
{
    "data": {
        "uuid": "141e8454-8aa1-420a-bd0b-18a85ba949a2",
        "title": "Launch card",
        "size": "open_graph",
        "width": 1200,
        "height": 630,
        "created_at": "2026-05-01T12:00:00Z"
    },
    "message": "Template created successfully"
}
422 The body names no canvas, or a field failed a rule.
{
    "message": "Send a `size` preset or an explicit `width` and `height`.",
    "errors": {
        "width": [
            "Send a `size` preset or an explicit `width` and `height`."
        ],
        "height": [
            "Send a `size` preset or an explicit `width` and `height`."
        ]
    }
}

PATCH /v1/templates/{templateIdentifier}

Update a template

Updates a template and regenerates its preview image. The path segment accepts the template UUID or the numeric template ID. GET /v1/templates returns the UUID.

Auth: Bearer token Ability: api_requests Free

Parameters

Name In Type Required Description
templateIdentifier path string Yes Template UUID or numeric template ID, scoped to your company. A value of only digits reads the numeric ID. Every other value reads the UUID.

Request body

Content-Type: application/json

Field Type Required Validation Description
title string Yes required|string|max:255 Template name.
size string No nullable|in:<preset> Canvas size preset, for example "instagram_story" or "youtube_thumbnail". It sets width and height for you. GET /v1/templates/sizes lists every preset.
width integer No nullable|numeric|min:1|max:4000 Canvas width in pixels. Ignored when you send a size preset.
height integer No nullable|numeric|min:1|max:4000 Canvas height in pixels. Ignored when you send a size preset.
layers array No nullable|array Layer definitions; stored JSON-encoded.

`data` holds the same six fields POST /v1/templates returns. It is a new key, so a client that reads `message` still works.

Read `data.size`, `data.width` and `data.height` after the write. A body that sends `size` sets the dimensions, and a body that sends the dimensions sets `size`.

Example request

curl

curl -X PATCH https://snapsbrew.com/api/v1/templates/<uuid> \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"title":"Updated title"}'

Example responses

200 Template updated.
{
    "data": {
        "uuid": "141e8454-8aa1-420a-bd0b-18a85ba949a2",
        "title": "Updated title",
        "size": "open_graph",
        "width": 1200,
        "height": 630,
        "created_at": "2026-05-01T12:00:00Z"
    },
    "message": "Template updated successfully"
}
404 Template not found in your company.
{
    "message": "Not found."
}

POST /v1/templates/{templateUuid}/publish

Publish a template

Publishes the current draft of a template as a new immutable version and returns that version number. Snaps and previews render the published version, so an edit takes effect only after this call. The call is safe to repeat: a draft with no new edits returns the version which is already live and creates no second version.

Auth: Bearer token Ability: api_requests Gate: policy:update,Template Free

Parameters

Name In Type Required Description
templateUuid path string Yes UUID of the template whose draft you want to publish.

BREAKING CHANGE. The response fields moved under a `data` key. Read `data.published_version`, not `published_version`.

`data.id` is deprecated. It repeats the value of `data.uuid`, which is the name every other template field uses. Read `data.uuid`. `data.id` stays until a major version removes it.

Example request

curl

curl -X POST https://snapsbrew.com/api/v1/templates/<uuid>/publish \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 The published version.
{
    "data": {
        "id": "141e8454-8aa1-420a-bd0b-18a85ba949a2",
        "uuid": "141e8454-8aa1-420a-bd0b-18a85ba949a2",
        "published_version": 2
    },
    "message": "Template published. New snaps and previews now render this version."
}
404 Template not found in your company.
{
    "message": "Not found."
}

DELETE /v1/templates/{templateIdentifier}

Delete a template

Deletes a template. The path segment accepts the template UUID or the numeric template ID. GET /v1/templates returns the UUID. Requires the delete-template policy.

Auth: Bearer token Ability: api_requests Gate: policy:delete,Template Free

Parameters

Name In Type Required Description
templateIdentifier path string Yes Template UUID or numeric template ID, scoped to your company. A value of only digits reads the numeric ID. Every other value reads the UUID.

This body carries no `data` key. Every other success body of this API holds one, and a delete is the exemption: the template is gone, so there is no resource to return.

Example request

curl

curl -X DELETE https://snapsbrew.com/api/v1/templates/<uuid> \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 Template deleted.
{
    "message": "Template deleted successfully"
}
404 Template not found in your company.
{
    "message": "Not found."
}

Editor documents

GET /v1/templates/{templateUuid}/document

Get the editor document

Returns the stored v2 editor document and its revision. A template with no draft returns a null document and revision 0. Read this before every write.

Auth: Bearer token Ability: api_requests Gate: throttle:editor-document Free

Parameters

Name In Type Required Description
templateUuid path string Yes UUID of the template.

The read gate and the write gate name the same people. Every account in your company that can write the document can also read it.

Example request

curl

curl https://snapsbrew.com/api/v1/templates/<uuid>/document \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 The document and its revision.
{
    "document": {
        "version": 2,
        "layers": [
            {
                "key": "headline",
                "type": "text",
                "properties": [
                    {
                        "name": "fontWeight",
                        "value": 700
                    }
                ]
            }
        ],
        "groups": []
    },
    "revision": 4
}
403 Your account is not allowed to read templates.
{
    "message": "This action is unauthorized."
}
404 Template not found in your company.
{
    "message": "Not found."
}

PATCH /v1/templates/{templateUuid}/document

Apply editor operations

Applies a closed list of layer operations and saves the result under the next revision. `set_layer_property` takes `layer_key`, `property` and `value`. `set_layer_type` takes `layer_key` and `type`. Every operation in one call applies together, or none of them applies.

Auth: Bearer token Ability: api_requests Gate: throttle:editor-document Free

Parameters

Name In Type Required Description
templateUuid path string Yes UUID of the template.

Request body

Content-Type: application/json

Field Type Required Validation Description
revision integer Yes required|integer|min:0 The revision the last read returned.
operations array Yes required|array|max:100 One to 100 operation objects, applied in order.

A rejected operation returns a stable `code`, for example `editor_operation_layer_not_found` or `editor_operation_invalid_value`. Correct the operation and call again.

A malformed body returns the standard validation shape instead, with a message under `errors.revision` or `errors.operations`.

The route allows 30 calls a minute for one token and 180 a minute for one company.

Example request

curl

curl -X PATCH https://snapsbrew.com/api/v1/templates/<uuid>/document \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"revision":4,"operations":[{"operation":"set_layer_property","layer_key":"headline","property":"fontWeight","value":700}]}'

Example responses

200 The saved document and its new revision.
{
    "document": {
        "version": 2,
        "layers": [
            {
                "key": "headline",
                "type": "text",
                "properties": [
                    {
                        "name": "fontWeight",
                        "value": 700
                    }
                ]
            }
        ],
        "groups": []
    },
    "revision": 5
}
409 The stored revision moved. Nothing was saved.
{
    "code": "editor_document_conflict",
    "current_revision": 5,
    "current_document": {
        "version": 2,
        "layers": [],
        "groups": []
    }
}
422 The body is malformed, or the document rejects an operation.
{
    "code": "editor_operation_layer_not_found"
}

PUT /v1/templates/{templateUuid}/document

Replace the editor document

Replaces the whole v2 editor document and saves it under the next revision. Send the document you read, with your change applied to it. Any layer or property you leave out is gone. Prefer `PATCH` unless you rebuild the document.

Auth: Bearer token Ability: api_requests Gate: throttle:editor-document Free

Parameters

Name In Type Required Description
templateUuid path string Yes UUID of the template.

Request body

Content-Type: application/json

Field Type Required Validation Description
revision integer Yes required|integer|min:0 The revision the last read returned.
document object Yes required|array The complete v2 document, with `layers` and `groups`.

The document is bounded: 262144 bytes, 1000 nodes, depth 12, and 16384 characters for one string. A document over a limit returns `editor_document_too_large` or `editor_document_budget_exceeded` under `errors.document`.

The route allows 30 calls a minute for one token and 180 a minute for one company.

Example request

curl

curl -X PUT https://snapsbrew.com/api/v1/templates/<uuid>/document \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"revision":4,"document":{"version":2,"layers":[],"groups":[]}}'

Example responses

200 The saved document and its new revision.
{
    "document": {
        "version": 2,
        "layers": [],
        "groups": []
    },
    "revision": 5
}
409 The stored revision moved. Nothing was saved.
{
    "code": "editor_document_conflict",
    "current_revision": 5,
    "current_document": {
        "version": 2,
        "layers": [],
        "groups": []
    }
}
422 The body is malformed, or the document breaks a limit.
{
    "message": "The given data was invalid.",
    "errors": {
        "document": [
            "editor_document_too_large"
        ]
    }
}

GET /v1/templates/{templateUuid}/document/preflight

Inspect the editor document

Reads the stored document and returns the known draft problems it carries, each with a code, a JSON pointer and a message. An empty `issues` list means the known checks pass. It does not guarantee that the render looks right.

Auth: Bearer token Ability: api_requests Gate: throttle:editor-document Free

Parameters

Name In Type Required Description
templateUuid path string Yes UUID of the template.

Run it after the last write and before you publish the template.

Example request

curl

curl https://snapsbrew.com/api/v1/templates/<uuid>/document/preflight \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 The issues and the revision they were read from.
{
    "issues": [
        {
            "code": "image_asset_missing",
            "path": "/layers/0/source",
            "message": "Image layers require a pinned asset id."
        }
    ],
    "revision": 4
}
403 Your account is not allowed to read templates.
{
    "message": "This action is unauthorized."
}
404 Template not found in your company.
{
    "message": "Not found."
}

Media

GET /v1/media

List media

Returns your uploaded images, 12 per page, newest first.

Auth: Bearer token Ability: api_requests Free

Parameters

Name In Type Required Description
page query integer No Page number for the standard paginator.

Example request

curl

curl https://snapsbrew.com/api/v1/media \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 A page of media.
{
    "data": [
        {
            "id": 12,
            "file_name": "logo.png",
            "src": "https://snapsbrew.com/storage/12/conversions/logo-image.jpg"
        }
    ],
    "links": {
        "first": "...",
        "last": "...",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "per_page": 12,
        "total": 1
    }
}

POST /v1/media

Upload media

Uploads an image into your media library. Send as multipart/form-data.

Auth: Bearer token Ability: api_requests Free

Request body

Content-Type: multipart/form-data

Field Type Required Validation Description
file file Yes required, file, image The image to upload.

Example request

curl

curl -X POST https://snapsbrew.com/api/v1/media \
  -H 'Authorization: Bearer <your-token>' \
  -F '[email protected]'

Example responses

200 Media uploaded.
{
    "id": 12,
    "file_name": "logo.png",
    "src": "https://snapsbrew.com/storage/12/conversions/logo-image.jpg"
}
422 File missing or not an image.
{
    "message": "The file must be an image."
}

Screenshots

GET /v1/screenshots

List screenshots

Returns a cursor-paginated list of your screenshots.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Parameters

Name In Type Required Description
cursor query string No Cursor token from meta.next_cursor.

Example request

curl

curl https://snapsbrew.com/api/v1/screenshots \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 A page of screenshots.
{
    "data": [
        {
            "uuid": "a1b2c3",
            "url": "https://example.com",
            "image_url": "https://snapsbrew.com/storage/screenshots/a1b2c3.png",
            "width": 1330,
            "height": 780,
            "created_at": "2026-05-01T12:00:00Z"
        }
    ],
    "meta": {
        "previous_cursor": null,
        "next_cursor": null
    }
}

GET /v1/screenshots/{screenshotUuid}

Get a screenshot

Returns a single screenshot.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Parameters

Name In Type Required Description
screenshotUuid path string Yes UUID of the screenshot.

Example request

curl

curl https://snapsbrew.com/api/v1/screenshots/<uuid> \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 The screenshot.
{
    "data": {
        "id": "a1b2c3",
        "url": "https://example.com",
        "image_url": "https://snapsbrew.com/storage/screenshots/a1b2c3.png",
        "width": 1330,
        "height": 780,
        "created_at": "2026-05-01T12:00:00Z"
    }
}
404 Screenshot not found in your company.
{
    "message": "Not found."
}

POST /v1/screenshots

Create a screenshot

Captures a web page. Defaults to a 1330x780 viewport when width/height are omitted.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Gate: hasActiveSubscription Costs credits

Credits — Requires available credits (canCreateSnap); returns 417 when exhausted.

Request body

Content-Type: application/json

Field Type Required Validation Description
url string No url Page to capture. Validated as a URL when present.
width integer No integer Viewport width. Defaults to 1330.
height integer No integer Viewport height. Defaults to 780.

Example request

curl

curl -X POST https://snapsbrew.com/api/v1/screenshots \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com","width":1330,"height":780}'

Example responses

200 Screenshot created.
{
    "data": {
        "id": "a1b2c3",
        "url": "https://example.com",
        "image_url": "https://snapsbrew.com/storage/screenshots/a1b2c3.png",
        "width": 1330,
        "height": 780,
        "created_at": "2026-05-01T12:00:00Z"
    }
}
401 No active subscription or trial.
{
    "message": "Unauthenticated."
}
417 Monthly credit quota exhausted.
{
    "message": "You have reached your snap quota."
}

Snaps

POST /v1/snaps

Create a snap

Renders a snap from a single template (`template_id`) or every template in a collection (`collection_id`). Provide exactly one of the two.

Synchronous (default): the response carries the finished `media_url` and returns 201.

Asynchronous (`async: true`): the snap is queued, the response returns 202 immediately, and the result is delivered to `webhook_url` on completion.

The API always renders the template's **published** version. Unpublished draft edits are not visible to the API until the template is published.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Gate: hasActiveSubscription Costs credits

Credits — Synchronous: 1 credit per rendered template. Asynchronous: 0 credits at accept time (HTTP 202); the credit is charged when the queued snap reaches completed. A repeated `idempotency_key` returns the first snap and charges 0 credits.

Request body

Content-Type: application/json

Field Type Required Validation Description
template_id string No required_without:collection_id, prohibits:collection_id, exists templates.uuid scoped to company UUID of a single template to render.
collection_id string No required_without:template_id, prohibits:template_id, exists template_collections.uuid scoped to company UUID of a collection; one snap is rendered per template.
type string No nullable, in:image,pdf Output type. Defaults to image.
format string No sometimes, in:png,jpeg,webp Image output format (image type only). Defaults to png.
transparent boolean No sometimes, boolean; rejected with png-only/webp-only — 422 when combined with format=jpeg Render on a transparent background. Valid for png and webp only; jpeg + transparent returns 422.
async boolean No sometimes, boolean Queue the render and return 202.
webhook_url string No url, required_if:async,true, must be a public http or https address Callback URL invoked when an async snap completes. The address must be public. A host that resolves to a private, loopback, link-local or reserved range is rejected with 422.
variants array No no server validation Per-layer content overrides applied to the render.
idempotency_key string No sometimes, nullable, string, max:191, letters/digits/underscore/hyphen only, prohibits:collection_id Send the same key when you retry after a timeout. The retry returns the same snap and charges no second credit. Keys are honored for 24 hours and are scoped to your account. Not supported with collection_id.

Every response carries an `X-Request-Uuid` header. Quote it in support tickets.

A collection request returns an array of snap objects, one per template.

A response to a repeated `idempotency_key` carries an `X-Idempotent-Replay: true` header and charges 0 credits.

`webhook_url` must be a public address. A host that resolves to a private, loopback, link-local or reserved range is rejected with 422.

An `idempotency_key` is honored for 24 hours. After that window a retry is a new request and charges a new credit.

Example request

curl

curl -X POST https://snapsbrew.com/api/v1/snaps \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"template_id":"<uuid>","type":"image","variants":[{"layer":"review_title","text":"Hello world"}]}'

async curl

curl -X POST https://snapsbrew.com/api/v1/snaps \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"template_id":"<uuid>","async":true,"webhook_url":"https://example.com/hooks/snap"}'

Example responses

201 Synchronous snap rendered.
{
    "id": "9f1c2d3e",
    "media_url": "https://snapsbrew.com/storage/snaps/9f1c2d3e.png",
    "type": "image",
    "status": "completed",
    "is_async": false,
    "webhook_url": null,
    "completed_at": "2026-05-01T12:00:03Z",
    "last_error": null,
    "variants": [],
    "template_id": "141e8454-8aa1-420a-bd0b-18a85ba949a2",
    "template_title": "Launch card",
    "created_at": "2026-05-01T12:00:00Z"
}
202 Asynchronous snap queued.
{
    "id": "9f1c2d3e",
    "media_url": null,
    "type": "image",
    "status": "pending",
    "is_async": true,
    "webhook_url": "https://example.com/hooks/snap",
    "completed_at": null,
    "last_error": null,
    "variants": [],
    "template_id": "141e8454-8aa1-420a-bd0b-18a85ba949a2",
    "template_title": "Launch card",
    "created_at": "2026-05-01T12:00:00Z"
}
404 Template or collection not found, or collection empty.
{
    "message": "Not found."
}
417 Monthly credit quota exhausted.
{
    "message": "You have reached your snap quota."
}
409 Another request with the same idempotency_key is still in progress. Nothing was created and nothing was charged. Retry.
{
    "message": "A request with this idempotency_key is already in progress. Retry in a moment. Nothing was created and nothing was charged."
}
422 Validation failed.
{
    "message": "The template id field is required when collection id is not present."
}

Snap batches

POST /v1/snaps/batches

Create a batch of snaps

Renders up to 100 snaps from one template. Every item carries its own `variants` and an optional `identifier` you use to recognize it in the result.

The response is always 202. Nothing is charged at accept time. Each item costs 1 credit when it renders.

`type`, `format` and `transparent` apply to every item in the batch. An item that needs a different format belongs in a different batch.

The API always renders the template's **published** version.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Gate: hasActiveSubscription Costs credits

Credits — 0 credits at accept time (HTTP 202). Each item is charged 1 credit when it reaches completed. An item that fails costs nothing. A repeated `idempotency_key` returns the first batch and starts no second one.

Request body

Content-Type: application/json

Field Type Required Validation Description
template_id string Yes required, exists templates.uuid scoped to company UUID of the template every item renders from.
items array Yes required, array, min:1, max:100 One entry per snap. Over 100 entries returns 422 and creates nothing.
items[].variants array No each image_url must be a public http or https address Per-layer content overrides for this item.
items[].identifier string No sometimes, nullable, string, max:191 Your own name for this item. Defaults to item_1, item_2, and so on.
title string No sometimes, string, max:255 A name for the batch, shown in the account. Defaults to "API batch".
webhook_url string No nullable, url, max:2048, must be a public http or https address ONE request is posted to this address when the batch finishes. A host that resolves to a private, loopback, link-local or reserved range is rejected with 422.
type string No sometimes, in:image,pdf Output type for every item. Defaults to image.
format string No sometimes, in:png,jpeg,webp Image output format for every item. Defaults to png.
transparent boolean No sometimes, boolean; 422 when combined with format=jpeg Render every item on a transparent background. Valid for png and webp only.
idempotency_key string No sometimes, nullable, string, max:191, letters/digits/underscore/hyphen only Send the same key when you retry after a timeout. The retry returns the same batch and starts no second one. Keys are honored for 24 hours and are scoped to your account. A key already used by POST /v1/snaps returns 409.

The whole batch is checked against the credit balance before any item is created. A batch of 100 against 40 credits creates nothing, not 40 items.

The balance check is not a reservation. Two batches accepted a second apart read the same balance, so a caller can queue more items than the balance covers. Each item is still charged only when it renders.

Over 100 items returns 422 on `errors.items` and creates nothing. The request is never truncated in silence.

Exactly one webhook is posted, when the batch finishes. There is no per-item webhook on this endpoint.

`webhook_url` must be a public address. A host that resolves to a private, loopback, link-local or reserved range is rejected with 422.

A response to a repeated `idempotency_key` carries an `X-Idempotent-Replay: true` header.

Every response carries an `X-Request-Uuid` header. Quote it in support tickets.

A batch holds one of five statuses. `pending` and `processing` mean it is still running. The three terminal statuses are `completed`, `failed` and `canceled`, and a batch never leaves one. `completed` means the batch ran to the end and at least one item rendered, so read the `failed` count as well as the status. `failed` means zero items rendered. At every terminal status `completed + failed + canceled` equals `total_rows`.

Example request

curl

curl -X POST https://snapsbrew.com/api/v1/snaps/batches \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"template_id":"<uuid>","title":"October launch","items":[{"identifier":"row-1","variants":[{"layer":"headline","text":"Hello"}]},{"identifier":"row-2","variants":[{"layer":"headline","text":"World"}]}]}'

Example responses

202 Batch accepted and queued.
{
    "uuid": "7c1f2a9e-0b44-4a1e-9f2b-5d3c8e1a7b60",
    "title": "October launch",
    "status": "processing",
    "total_rows": 3,
    "processed_rows": 0,
    "completed": 0,
    "pending": 3,
    "failed": 0,
    "canceled": 0,
    "credits_charged": 0,
    "status_url": "https://snapsbrew.com/api/v1/snaps/batches/7c1f2a9e-0b44-4a1e-9f2b-5d3c8e1a7b60"
}
409 The idempotency_key is in progress on another request, or it already belongs to a single snap. Nothing was created and nothing was charged.
{
    "message": "This idempotency_key already belongs to a single snap. Use a new key for a batch."
}
417 The credit balance is smaller than the number of items. Nothing was created.
{
    "message": "You have reached your snap quota."
}
422 Validation failed.
{
    "message": "A batch accepts at most 100 items. Split the request into smaller batches."
}

GET /v1/snaps/batches/{batchUuid}

Read a batch

Returns the counts, the running credit total, and every item with its status and image URL. Poll this about every 5 seconds and stop when `status` is `completed`, `failed` or `canceled`.

This endpoint does not require an active subscription, so a customer whose plan lapsed can still collect work they already paid for.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Parameters

Name In Type Required Description
batchUuid path string Yes The batch id returned by POST /v1/snaps/batches.

A batch holds one of five statuses. `pending` and `processing` mean it is still running. The three terminal statuses are `completed`, `failed` and `canceled`, and a batch never leaves one. `completed` means the batch ran to the end and at least one item rendered, so read the `failed` count as well as the status. `failed` means zero items rendered. At every terminal status `completed + failed + canceled` equals `total_rows`.

`credits_charged` is read from the billing ledger, not counted from `completed`. It rises between polls.

`media_url` is set only on an item with status `completed`.

`last_error` on a failed item carries the render error as the renderer reported it. Treat it as a message for a person, never as a stable code to branch on.

A batch id that belongs to another account returns 404, the same as an id that does not exist.

Example request

curl

curl 'https://snapsbrew.com/api/v1/snaps/batches/<batch-uuid>' \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 The batch and its items.
{
    "uuid": "7c1f2a9e-0b44-4a1e-9f2b-5d3c8e1a7b60",
    "title": "October launch",
    "status": "completed",
    "total_rows": 2,
    "processed_rows": 2,
    "completed": 1,
    "pending": 0,
    "failed": 1,
    "canceled": 0,
    "credits_charged": 1,
    "status_url": "https://snapsbrew.com/api/v1/snaps/batches/7c1f2a9e-0b44-4a1e-9f2b-5d3c8e1a7b60",
    "items": [
        {
            "id": "9f1c2d3e",
            "identifier": "row-1",
            "status": "completed",
            "media_url": "https://snapsbrew.com/storage/snaps/9f1c2d3e.png",
            "last_error": null
        },
        {
            "id": "4b8a7c6d",
            "identifier": "row-2",
            "status": "failed",
            "media_url": null,
            "last_error": "Render failed."
        }
    ]
}
404 No batch with that id exists in your account.
{
    "message": "No batch with that id exists in your account."
}

POST /v1/snaps/batches/{batchUuid}/cancel

Cancel a batch

Stops a batch that is still running.

An item that already rendered keeps its image and stays billed. An item that had not started is marked `canceled` and costs nothing. An item that is rendering at that moment can still finish and can still be charged.

This cannot be undone. A canceled batch cannot be resumed. Start a new batch for the items you still want.

Like the read endpoint, this does not require an active subscription: stopping work only lowers the bill.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Costs credits

Credits — Nothing is charged by this call. Items that already rendered keep the credit they cost. Items that never started cost nothing.

Parameters

Name In Type Required Description
batchUuid path string Yes The batch id returned by POST /v1/snaps/batches.

Canceling twice is safe. A batch that already holds a terminal status is returned unchanged.

One webhook is posted, carrying `event: snap-import.canceled`.

An item that is rendering when the cancel lands can still complete and can still be charged. The counts in the response are the truth at that moment.

A batch id that belongs to another account returns 404, the same as an id that does not exist.

Example request

curl

curl -X POST 'https://snapsbrew.com/api/v1/snaps/batches/<batch-uuid>/cancel' \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 The batch after the cancel, with its items.
{
    "uuid": "7c1f2a9e-0b44-4a1e-9f2b-5d3c8e1a7b60",
    "title": "October launch",
    "status": "canceled",
    "total_rows": 3,
    "processed_rows": 3,
    "completed": 1,
    "pending": 0,
    "failed": 0,
    "canceled": 2,
    "credits_charged": 1,
    "status_url": "https://snapsbrew.com/api/v1/snaps/batches/7c1f2a9e-0b44-4a1e-9f2b-5d3c8e1a7b60",
    "items": [
        {
            "id": "9f1c2d3e",
            "identifier": "row-1",
            "status": "completed",
            "media_url": "https://snapsbrew.com/storage/snaps/9f1c2d3e.png",
            "last_error": null
        },
        {
            "id": "4b8a7c6d",
            "identifier": "row-2",
            "status": "canceled",
            "media_url": null,
            "last_error": null
        },
        {
            "id": "2e5f9a1b",
            "identifier": "row-3",
            "status": "canceled",
            "media_url": null,
            "last_error": null
        }
    ]
}
404 No batch with that id exists in your account.
{
    "message": "No batch with that id exists in your account."
}

Preview

GET /v1/templates/{templateUuid}/preview

Preview a template

Renders a free, watermarked preview of a template using its default layer content, or with `variants` applied. Returns a self-contained HTML document (text/html).

Auth: Bearer token Ability: api_requests Gate: throttle:preview Free

Parameters

Name In Type Required Description
templateUuid path string Yes UUID of the template to preview.
variants query array No Per-layer overrides, e.g. variants[0][layer]=headline&variants[0][text]=Hello. Each item targets a layer key with one of text, image_url (public URL), background_color, qr_content, barcode_content, or hidden.

The preview is watermarked HTML, not a usable final asset.

No credit is charged and no snap is stored.

Example request

curl

curl 'https://snapsbrew.com/api/v1/templates/<uuid>/preview' \
  -H 'Authorization: Bearer <your-token>' \
  --output preview.html

Example responses

200 Watermarked HTML preview (text/html).
"<!DOCTYPE html>\u2026watermarked preview\u2026</html>"
404 Template not found in your account.
{
    "message": "Not found."
}
422 Validation failed (e.g. a non-public image_url).
{
    "message": "The variants.0.image_url must be a public http or https URL."
}
429 Preview rate limit exceeded.
{
    "message": "Too Many Attempts."
}

GET /v1/snaps/preview

Preview a snap

Renders a free, watermarked preview of the snap you intend to create — a template (`template_id`) plus `variants`. Returns a self-contained HTML document (text/html). Pass the same template_id and variants to POST /v1/snaps to create the final billed snap.

Auth: Bearer token Ability: api_requests Gate: throttle:preview Free

Parameters

Name In Type Required Description
template_id query string Yes UUID of the template to render.
variants query array No Per-layer overrides, e.g. variants[0][layer]=headline&variants[0][text]=Hello. Each item targets a layer key with one of text, image_url (public URL), background_color, qr_content, barcode_content, or hidden.

The preview is watermarked HTML, not a usable final asset.

No credit is charged and no snap is stored.

Example request

curl

curl 'https://snapsbrew.com/api/v1/snaps/preview?template_id=<uuid>&variants[0][layer]=headline&variants[0][text]=Hello' \
  -H 'Authorization: Bearer <your-token>' \
  --output preview.html

Example responses

200 Watermarked HTML preview (text/html).
"<!DOCTYPE html>\u2026watermarked preview\u2026</html>"
404 Template not found in your account.
{
    "message": "Not found."
}
422 Validation failed.
{
    "message": "The template id field is required."
}
429 Preview rate limit exceeded.
{
    "message": "Too Many Attempts."
}

Tags

GET /v1/tags

List tags

Returns up to 15 tags, ordered by name, optionally filtered by a search term.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Parameters

Name In Type Required Description
search query string No Case-insensitive substring match on tag name.

Example request

curl

curl 'https://snapsbrew.com/api/v1/tags?search=launch' \
  -H 'Authorization: Bearer <your-token>'

Example responses

200 Matching tags.
{
    "data": [
        {
            "id": 1,
            "name": "Launch",
            "slug": "launch"
        }
    ]
}

POST /v1/tags

Create a tag

Creates a tag. The slug is generated from the name; collisions get a numeric suffix.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Request body

Content-Type: application/json

Field Type Required Validation Description
name string Yes required, string, max:255 Display name of the tag.

Example request

curl

curl -X POST https://snapsbrew.com/api/v1/tags \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Launch"}'

Example responses

201 Tag created.
{
    "data": {
        "id": 1,
        "name": "Launch",
        "slug": "launch"
    }
}
422 Validation failed.
{
    "message": "The name field is required."
}

POST /v1/templates/{templateUuid}/tags

Sync template tags

Replaces all tags on a template with the supplied set. Send an empty array to clear every tag.

Auth: Bearer token Ability: api_requests Gate: logApiRequest Free

Parameters

Name In Type Required Description
templateUuid path string Yes UUID of the template.

Request body

Content-Type: application/json

Field Type Required Validation Description
tag_ids integer[] No array Tag IDs to attach. Replaces the existing set.
tag_ids.* integer No integer, exists tags.id scoped to company Each ID must belong to your company.

Example request

curl

curl -X POST https://snapsbrew.com/api/v1/templates/<uuid>/tags \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
  -d '{"tag_ids":[1,2]}'

Example responses

200 Tags synced.
{
    "message": "Tags updated successfully.",
    "tags": [
        {
            "id": 1,
            "name": "Launch",
            "slug": "launch"
        }
    ]
}
404 Template not found in your company.
{
    "message": "Not found."
}
422 A tag ID is invalid or not yours.
{
    "message": "The selected tag_ids.0 is invalid."
}

Embedded Forms

POST /v1/embedded-forms/{formUuid}

Submit an embedded form

Renders a snap from a configured form. Template forms return one snap; collection forms return an array of snaps.

Layer keys: template forms use the plain layer key (`headline`); collection forms use `{templateUuid}__{layerKey}`. Only layers the form was configured with are accepted; the rest are dropped silently.

Auth: Signed URL Gate: embeddedFormMiddleware Gate: valid signature required Costs credits

Credits — The form owner is charged: 1 credit for a template form, or 1 per template for a collection form.

Parameters

Name In Type Required Description
formUuid path string Yes UUID of the form.
signature query string Yes Laravel URL signature. The whole URL must be signed.

Request body

Content-Type: multipart/form-data

Field Type Required Validation Description
layers object No keys matched against the form configuration Layer overrides. Value keys by layer type: image -> image_url (file), text -> text, empty -> background_color, qr_code -> qr_content, barcode -> barcode_content.

Collection forms return a bare array of snap objects, not a `data`-wrapped object.

This route has no rate limiting.

Example request

curl

curl -X POST 'https://snapsbrew.com/api/v1/embedded-forms/<formUuid>?signature=<sig>' \
  -F 'layers[headline]=Summer sale' \
  -F 'layers[logo][email protected]'

Example responses

201 Snap rendered (template form).
{
    "data": {
        "id": "9f1c2d3e",
        "media_url": "https://snapsbrew.com/storage/snaps/9f1c2d3e.png",
        "type": "image",
        "status": "completed",
        "is_async": false,
        "webhook_url": null,
        "completed_at": "2026-05-01T12:00:03Z",
        "last_error": null,
        "variants": [],
        "template_id": "141e8454",
        "template_title": "Launch card",
        "created_at": "2026-05-01T12:00:00Z"
    }
}
404 Form not found or invalid signature.
{
    "message": "Not found."
}
422 Collection form has no templates configured.
{
    "message": "The form does not include any templates."
}