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 send | You 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 pixels | One hosted image per target size, at exactly the pixels requested, laid out again from the ad's layers |
- Submit the ad and its target sizes. The API returns a
request_idand astatus_urlimmediately. - Wait for completion by polling the
status_url(the shared status endpoint) every few seconds, or pass awebhook_urland let Bria POST the result to you (webhooks). Both deliver the same body. - Download the images. The completed status body carries
result.results, one entry per target size, each with a hostedurl.
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.
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".
| Parameter | Description |
|---|---|
attachments | Exactly one image: a public URL or a data:image/…;base64,… URI. PNG or JPEG. Required. |
formats | One 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. |
prompt | Optional guidance for how the ad should adapt to each size. |
webhook_url | Optional. 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.
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.
| Target sizes | 1 to 10 per call, any width and height in pixels |
| Input format | PNG or JPEG, one image per call |
| Source resolution | Full resolution on Enterprise; downscaled to 2048 px per side on other plans, with a note in the response |
| Billing | Failed jobs are not billed |
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.
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.
One to ten target sizes. One result comes back per entry, carrying the same name. This parameter is required.
Optional guidance for how the ad should adapt to each size, for example "keep the logo in the top-left corner".
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.
- Three placements from one ad
- With guidance and a webhook
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)Accepted (asynchronous). Track progress with the Status Service or a webhook; the completion payload is shown under Callbacks.
{ "request_id": "340780795e1b4530a5c7ee4563989f6f", "status_url": "https://engine.prod.bria-api.com/v2/status/340780795e1b4530a5c7ee4563989f6f" }