Skip to content

Resize an ad into other sizes

Request

Send one finished, flat ad and up to ten target sizes; get back one finished image per size, with the layout redone for each shape rather than cropped or stretched. Trained exclusively on licensed data for safe commercial use.

Input assumptions

The input is assumed to be a flat ad. PSD and Figma files are not inputs. The job is asynchronous only; "sync": true is rejected with 400. On plans other than Enterprise, a source over 2048 px on either side is downscaled to fit before resizing, the outputs still come back at the requested sizes, and result.text says so. Submissions are not idempotent: a retried POST is a new job. Failed jobs are never billed.

Reporting a problem

The request_id in an error body identifies that response, not your job. The durable handle is the id inside the status_url you received at submit; quote that.

Ad Resize takes one finished, flat ad and returns it at other sizes, with the layout redone for each shape rather than cropped or stretched. Send the image and a list of target sizes; get one finished image per size back. Use it to turn a single creative into every placement a campaign needs, from a square feed post to a leaderboard, without a design file.

You sendYou get back
One flat ad image (PNG or JPEG) and up to 10 target sizes, each with a name and a width and height in pixelsOne hosted image per target size, at exactly the pixels requested, laid out again from the ad's layers

How a resize job runs

  1. Submit the ad and its target sizes. The API returns a request_id and a status_url immediately.
  2. Wait for completion by polling the status_url (the shared status endpoint) every few seconds, or pass a webhook_url and let Bria POST the result to you (webhooks). Both deliver the same body.
  3. Download the images. The completed status body carries result.results, one entry per target size, each with a hosted url.

Every size is laid out again from the ad's layers, so a call takes several minutes and finishes when its slowest size does. Set a poll timeout of at least 20 minutes.

Python SDK

from bria_client import BriaSyncClient

client = BriaSyncClient()  # reads BRIA_API_TOKEN

job = client.submit(
    endpoint="ads/resize",
    payload={
        "attachments": ["https://example.com/ads/spring-sale.jpg"],
        "formats": [
            {"name": "feed", "width": 1080, "height": 1080},
            {"name": "story", "width": 1080, "height": 1920},
            {"name": "leaderboard", "width": 970, "height": 90},
        ],
    },
)
status = client.poll(job, interval=10, timeout=1200)

for target in status.result.results:
    print(target["name"], target["status"], target["strategy"], target["url"])

TypeScript SDK

import { BriaClient } from "@bria-ai/client";

const client = new BriaClient(); // reads BRIA_API_TOKEN

// 1 + 2. Submit and wait
const job = await client.submit("ads/resize", {
  attachments: ["https://example.com/ads/spring-sale.jpg"],
  formats: [
    { name: "feed", width: 1080, height: 1080 },
    { name: "story", width: 1080, height: 1920 },
    { name: "leaderboard", width: 970, height: 90 },
  ],
});
const status = await client.poll(job, { interval: 10, timeout: 1200 });

// 3. One entry per target size
type Target = { name: string; status: string; strategy: string | null; url: string | null; error: string | null };
for (const target of (status.result?.results ?? []) as Target[]) {
  console.log(target.name, target.status, target.strategy, target.url);
}

cURL

curl -s -X POST https://engine.prod.bria-api.com/v2/ads/resize \
  -H "api_token: $BRIA_API_TOKEN" -H "Content-Type: application/json" \
  -d '{
    "attachments": ["https://example.com/ads/spring-sale.jpg"],
    "formats": [
      {"name": "feed", "width": 1080, "height": 1080},
      {"name": "story", "width": 1080, "height": 1920},
      {"name": "leaderboard", "width": 970, "height": 90}
    ]
  }'

curl -s "https://engine.prod.bria-api.com/v2/status/<request_id>" -H "api_token: $BRIA_API_TOKEN"

curl -s "https://engine.prod.bria-api.com/v2/status/<request_id>" -H "api_token: $BRIA_API_TOKEN" \
  | jq '.result.results[] | {name, status, strategy, url}'

The completed status body looks like this:

{
  "request_id": "340780795e1b4530a5c7ee4563989f6f",
  "status": "COMPLETED",
  "result": {
    "status": "completed",
    "results": [
      {
        "name": "feed",
        "width": 1080,
        "height": 1080,
        "status": "ok",
        "strategy": "delayer_dispatch",
        "url": "https://editor-media.bria.ai/inventory/.../assets/7b4549c24686472bac04bcfd023a1f0e.png",
        "error": null
      },
      {
        "name": "leaderboard",
        "width": 970,
        "height": 90,
        "status": "ok",
        "strategy": "delayer_dispatch",
        "url": "https://editor-media.bria.ai/inventory/.../assets/860865425a3f4d349dc79d8826e0c2b4.png",
        "error": null
      }
    ]
  }
}

Each target is independent: one can be "status": "failed" with an error while the others carry a url. Check every entry rather than the job as a whole.

How a size is made

Every size is produced the same way: the Ad Delayer separates the ad into layers, Bria's layout engine composes them for the new shape, and the text stays text. The strategy field on each result names that route, delayer_dispatch. It takes several minutes per call, and every image is Bria-made.

An optional prompt steers the layout, for example "keep the logo in the top-left corner".

Resize request essentials

ParameterDescription
attachmentsExactly one image: a public URL or a data:image/…;base64,… URI. PNG or JPEG. Required.
formatsOne to ten target sizes. Each has a name (echoed back on its result), and a width and height in pixels, both greater than zero. Required.
promptOptional guidance for how the ad should adapt to each size.
webhook_urlOptional. Receive the completion body by POST instead of polling.

The job is asynchronous only. A request with "sync": true is rejected with 400, because a layered target can run for minutes. Inputs are assumed to be flat ads; PSD and Figma files are not inputs. Submissions are not idempotent: a retried POST is a new job. Failed jobs are never billed.

Source resolution

On plans other than Enterprise, a source over 2048 px on either side is downscaled to fit 2048 px before resizing. The outputs still come back at the exact sizes requested, and the completed body carries a result.text note saying the source was downscaled. Enterprise accounts resize at full source resolution and receive no note. Contact us about Enterprise.

Limits

Target sizes1 to 10 per call, any width and height in pixels
Input formatPNG or JPEG, one image per call
Source resolutionFull resolution on Enterprise; downscaled to 2048 px per side on other plans, with a note in the response
BillingFailed jobs are not billed

Use resize from an agent

The hosted and local MCP server exposes this capability as the ad_resize tool; agents that write code can use the Python SDK as shown above. To make the ad editable first, or to change its copy before resizing, run the Ad Delayer.

Security
api_token
Bodyapplication/json
attachmentsArray of strings, = 1 itemsrequired

Exactly one image: a publicly reachable URL, or a data:image/…;base64,… URI. PNG or JPEG. More than one entry, or a value that is neither a URL nor base64, is rejected with 422. This parameter is required.

formatsArray of objects, [ 1 .. 10 ] items(TargetSize)required

One to ten target sizes. One result comes back per entry, carrying the same name. This parameter is required.

promptstring

Optional guidance for how the ad should adapt to each size, for example "keep the logo in the top-left corner".

webhook_urlstring, (uri)

Optional URL that receives the completion payload by POST when the job reaches a terminal state, with the same body as a status poll. See webhooks.

POST
/ads/resize
from bria_client import BriaSyncClient

client = BriaSyncClient()  # reads BRIA_API_TOKEN

job = client.submit(
    endpoint="ads/resize",
    payload={
        "attachments": [
            "https://bria-image-repository.s3.amazonaws.com/images/c41b39ec1a69a5d3.jpg",
        ],
        "formats": [
            {
                "name": "feed",
                "width": 1080,
                "height": 1080,
            },
            {
                "name": "story",
                "width": 1080,
                "height": 1920,
            },
            {
                "name": "leaderboard",
                "width": 970,
                "height": 90,
            },
        ],
    },
)
result = client.poll(job, interval=10, timeout=1200)
print(result.result.results)

Responses

Accepted (asynchronous). Track progress with the Status Service or a webhook; the completion payload is shown under Callbacks.

Bodyapplication/json
request_idstringrequired
Example:"860f1a2b73f847e59f284d6f860f2ddb"
status_urlstringrequired
Example:"https://engine.prod.bria-api.com/v2/status/860f1a2b73f847e59f284d6f860f2ddb"
Response
{ "request_id": "340780795e1b4530a5c7ee4563989f6f", "status_url": "https://engine.prod.bria-api.com/v2/status/340780795e1b4530a5c7ee4563989f6f" }

Callbacks

Completion payload (webhook or status poll)
post