# Snaps

> Templates in, finished assets out.

A snap renders a template (or every template in a collection) into a finished image or PDF, with your content substituted into each layer. Render synchronously for an instant result, or asynchronously with a webhook for bulk work. Creating snaps requires an active subscription or trial.

## Create a snap

```http
POST /v1/snaps
```

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.

- **Auth:** Bearer token
- **Token abilities:** `api_requests`
- **Gates:** logApiRequest, hasActiveSubscription
- **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.

### 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 format. Defaults to image. |
| `async` | boolean | No | sometimes, boolean | Queue the render and return 202. |
| `webhook_url` | string | No | url, required_if:async,true | Callback URL invoked when an async snap completes. |
| `variants` | array | No | no server validation | Per-layer content overrides applied to the render. |

### Responses

**201** — Synchronous snap rendered.

```json
{
    "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.

```json
{
    "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.

```json
{
    "message": "Not found."
}
```

**417** — Monthly credit quota exhausted.

```json
{
    "message": "You have reached your snap quota."
}
```

**422** — Validation failed.

```json
{
    "message": "The template id field is required when collection id is not present."
}
```

> 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.

### Examples

*Curl*

```bash
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*

```bash
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"}'
```
