Close-camera UGC for Black Friday: six hook variants in one queue
Run Sume's close-camera UGC Format as one bulk queue to test six Black Friday testimonial hooks, with the TikTok in-feed file limits to check afterward.

The Format and the one call that starts it
To make a handheld, eye-contact testimonial ad for Black Friday, call the Format sume-close-camera-ugc at the reserved sume handle with an API key that carries formats:write. Black Friday 2026 is Friday, November 27, which is 55 days from today (October 3), so a six-hook test can finish in October and leave November for spending behind the winners.
The catalog describes the Format as one that creates "a finished close-camera UGC video with an intimate handheld selfie composition, direct eye contact, natural creator energy, and a product-led hook", for "close-up testimonial ads, creator reactions, personal recommendations, and phone-shot social videos". It is not meant for static campaign deliverables. The call is the ordinary Format run: POST /v1/formats/sume/sume-close-camera-ugc/runs, an Idempotency-Key header, and a body that names at least one of instruction, input, previous_run_id or attachments.
curl -sS -X POST "https://api.sume.com/v1/formats/sume/sume-close-camera-ugc/runs" \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: bf26-ugc-hook-a" \
-d '{
"instruction": "Vertical 9:16 testimonial. Hook in the first line: I waited for Black Friday to buy this. Show the product in hand.",
"input": { "product_name": "Trail Mug", "offer": "25% off, Nov 27 to Nov 30" },
"generation_spend_cap_usd": 40
}'Turn one run into a six-hook test
A test needs the same product and offer with only the opening line changed. Bulk runs queue up to 100 ordinary Format runs with a concurrency window of 1 to 16, so six hooks cost you one request instead of six scripts. Each item carries its own instruction, input and spend cap, exactly as in a single run, and the queue returns an id you poll at GET /v1/format-run-queues/{queue_id}.
The bulk-runs page documents the {handle}/{slug} address for the queue. Because the catalog answers at sume, use a one-item queue first to confirm that your key reaches it before you fill the list. Mint a fresh Idempotency-Key per batch: replaying a spent key returns the old queue.
curl -sS -X POST "https://api.sume.com/v1/formats/sume/sume-close-camera-ugc/bulk-runs" \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: bf26-ugc-batch-1" \
-d '{
"concurrency": 3,
"items": [
{ "instruction": "Hook: I waited for Black Friday to buy this.", "generation_spend_cap_usd": 40 },
{ "instruction": "Hook: This mug survived my whole commute.", "generation_spend_cap_usd": 40 },
{ "instruction": "Hook: Stop scrolling if you drink coffee.", "generation_spend_cap_usd": 40 }
]
}'Read the queue honestly
The queue has no webhook of its own; a per-item communication.webhook_url arms a terminal event for that child only. Queue status completed means every item is terminal, not that every item succeeded, so branch on counts.failed and re-queue only the failed hooks. Each finished child exposes primary_output_url on its run receipt at GET /v1/format-runs/{run_id}, and the media URLs are durable public media.sume.com links.
Runs that make video take minutes, so design the test as asynchronous from the start. Two cheap habits keep the grid comparable: give every item the same offer text in input, and vary only the one hook line you are testing.
Why testimonial hooks are the right thing to vary
In a testimonial the product, the offer and the setting are fixed by the brief, so the opening line is the cleanest variable. Six hooks that read differently in the first second give a real comparison: a deadline hook, a social-proof hook, a price hook, a problem hook, a gift hook and a curiosity hook. Keep the offer text in input identical across items so a difference in results comes from the hook and not from the discount.
A practical split is two items per angle if budget allows: the same hook with and without the product in hand in the first frame. Name each item in your own records by the Idempotency-Key you sent, because the Format's output carries media, not your labels.
Check the file against the platform before you upload
A Format run gives you a finished video; whether a platform accepts it is a separate check. TikTok's help page for in-feed ads lists the limits below for non-Spark ads. Probe each result's size and duration before you upload, rather than assuming.
| Item | Limit on the page |
|---|---|
| Vertical size | 9:16, at least 540 x 960 px |
| Horizontal size | 16:9, at least 960 x 540 px |
| Square size | 1:1, at least 640 x 640 px |
| Formats | .mp4, .mov, .mpeg, .3gp, .avi |
| Duration | up to 10 minutes |
| File size | 500 MB or less |
| Bitrate | 516 kbps or more |
Sources
Related posts
More in Formats
- Continued Format run: artifacts span the thread, usage is per run
A Sume Format run continued with previous_run_id gets a new id and cap. Its artifacts[] lists the whole conversation, while usage stays per run.
- Fashion-editorial Format for a holiday-party lookbook clip
Call Sume's fashion-editorial Format for a magazine-grade holiday-party lookbook clip with a strong pose and restrained motion, from one garment image.
- Format batch commit: files is a change set, so delete is separate
A batch PUT to a Format's contents commits many files at once. Unnamed files stay, deletes need DELETE, and one stale sha lands nothing.
- Format output_schema keywords: pattern and minLength yes, not no
Which JSON Schema keywords a Sume Format output_schema accepts (pattern, minLength, multipleOf, enum, const) and which fail as unsupported_keyword.
Written by Sume