1. Get keys
In Settings → API create a sandbox key (rb_test_…) and a live key (rb_…). Keep both on your server only and send them as Authorization: Bearer <key>.
export REELSBUILDER_API_KEY=rb_... # live
export REELSBUILDER_TEST_KEY=rb_test_... # sandbox
export RB=https://api.reelsbuilder.ai/api/v12. Check the account (free)
curl $RB/usage -H "Authorization: Bearer $REELSBUILDER_API_KEY"Returns your key mode, prepaid balance (api_credits_usd_cents) and the price list. Top up from $10 in Settings → API. Every paid call (stock video $0.60, YouTube clips $0.40 per delivered clip, AI influencer and AI video by length) draws on this prepaid balance.
3. Queue a stock video
curl -X POST $RB/generate-and-post \
-H "Authorization: Bearer $REELSBUILDER_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: acme-campaign42-creative7" \
-d '{
"prompt": "Why mid-market SaaS teams move to zero-trust security, and how it cuts breach risk without slowing engineers down. End with: Book a demo at acme.com.",
"content_purpose": "education",
"clip_type": "tech",
"duration_target_sec": 30,
"aspect_ratio": "9:16",
"include_branding": false,
"brand": { "name": "Acme Cloud", "website_url": "https://acme.com", "logo_url": "https://acme.com/logo.png", "primary_color": "#0A66C2" }
}'
# -> 202 { "data": { "job_id": "...", "poll_url": "/api/v1/jobs/..." } }Put your call to action in the brief, or send your own narration as script instead of prompt (read word for word; about 65 words for 30 seconds). Use one Idempotency-Key per creative (for example campaign + creative id) so a network retry never renders twice. Send your customer's brand (name, website, logo, colors) on each request; omit it to use your account brand. Fields: Stock video. Sending many at once? Use POST /api/v1/batch (up to 25 jobs per call).
4. Queue YouTube clips
# One video
curl -X POST $RB/clipper/youtube \
-H "Authorization: Bearer $REELSBUILDER_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: acme-webinar-0915" \
-d '{ "youtube_url": "https://www.youtube.com/watch?v=VIDEO_ID", "clip_count": 3, "content_purpose": "education" }'
# -> 200 { "data": { "job_id": "...", "poll_url": "...", "requested_clip_count": 3 } }5. Autoclip your customers' channels on a schedule
Run this once a day per customer channel. Each call clips that channel's newest upload your account has not clipped yet — no bookkeeping on your side.
curl -X POST $RB/clipper/youtube \
-H "Authorization: Bearer $REELSBUILDER_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: acme-channel-$(date +%F)" \
-d '{ "channel_url": "https://www.youtube.com/@acmecloud", "clip_count": 3 }'
# 200 -> new job (data.source_video says which upload was picked)
# 409 NO_NEW_CHANNEL_VIDEOS -> nothing new today; not an error, not charged
# 400 CHANNEL_NOT_FOUND -> fix the channel URL
# 502 CHANNEL_UNAVAILABLE -> retry laterAdd "dry_run": true while onboarding a new customer to see which video would be clipped, at no cost.
6. Poll until done
// TypeScript — works for stock, clip and AI video receipts
async function waitForJob(jobId: string) {
for (;;) {
const r = await fetch(`https://api.reelsbuilder.ai/api/v1/jobs/${jobId}`, {
headers: { Authorization: `Bearer ${process.env.REELSBUILDER_API_KEY}` },
});
const { data } = await r.json();
const job = data.job;
if (job.status === "completed") return job.artifacts; // videoUrl, videoUrls[], thumbnailUrl
if (["failed", "dead_lettered", "cancelled"].includes(job.status)) throw job.error;
await new Promise((resolve) => setTimeout(resolve, 15_000));
}
}Statuses, timings and failure handling: Jobs.
7. Download and hand off
When a job completes, copy every URL in artifacts.videoUrls (and the thumbnail) into your own storage, then attach it to your campaign. Use artifacts.title and artifacts.description (hashtags included) as post copy, or artifacts.clips[] for per-clip titles and transcripts. Generated files are kept for a limited time, so do not hot-link them long-term.
8. Handle errors
| Response | What to do |
|---|---|
402 INSUFFICIENT_API_CREDITS | Stop and top up; retrying will not help. |
400 INPUT_INVALID | Fix the fields listed in error.details. |
429 RENDER_CONCURRENCY_LIMIT_EXCEEDED | Up to 5 stock videos render at once per account; wait for one to finish, then submit the next. |
429 RATE_LIMIT_EXCEEDED | Wait Retry-After seconds. |
Job failed | Charges are refunded. If error.retryable, resubmit with a new idempotency key. |
| Network error / timeout | Wait before retrying with the same idempotency key. Finished responses replay; overlapping requests are not deduplicated. See Idempotency. |
Go-live checklist
- Keys are stored server-side only; sandbox key used in tests, live key in production.
- Every paid request sends a unique, deterministic
Idempotency-Key. - Your client reads the common receipt's
data.job_idanddata.poll_url; top-level aliases are deprecated. - Preview each mode with
dry_run: true, check its normalized input and price, then approve the paid request separately. - Polling uses a 10–15 second delay and stops on
completed,failed,dead_letteredorcancelled. - Finished files are copied to your storage (or, with private delivery, fetched from a fresh signed link each time — links expire after 24 hours).
- Stock renders are queued on your side so no more than 5 run at once.
402pauses the pipeline and alerts a human; nothing retries it automatically.- You ran one live stock video and one live clip end to end before launch.
Help
Questions: admin@reelsbuilder.ai — include meta.request_id or the job id.