When to use it
- Onboarding flows: capture a customer URL, build their profile before they ever generate their first video.
- Multi-tenant content platforms: cache one brand_id per tenant and reuse it across thousands of generations.
- Agency workflows: bulk-analyze 50 client brands overnight, kick off personalized content the next morning.
- B2B SaaS embedding ReelsBuilder: skip a 5-minute onboarding form with one URL.
Endpoints
POST /api/v1/brand/analyze— Build a fresh profile from a URL (async, returns job_id; final profile via webhook or polling).GET /api/v1/brand/{brand_id}— Fetch an existing profile.GET /api/v1/brand/{brand_id}/recommendations— Get content recommendations (topics, hook formats, voice) tuned to this brand.PATCH /api/v1/brand/{brand_id}— Manual override of any field (tone, voice, colors, etc).
Quickstart
curl -X POST https://api.reelsbuilder.ai/api/v1/brand/analyze \
-H "Authorization: Bearer $REELSBUILDER_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"url": "https://linear.app",
"webhook_url": "https://your-app.example.com/webhooks/brand-ready"
}'Initial response (202 Accepted)
{
"success": true,
"data": {
"job_id": "bjob_01HKZ...",
"brand_id": "brn_01HKZ...",
"status": "analyzing",
"estimated_completion_sec": 12
},
"meta": { "request_id": "req_...", "credits_used": 8, "credits_remaining": 992 }
}Webhook payload (when complete)
POST https://your-app.example.com/webhooks/brand-ready
X-RB-Event-Type: brand.analyzed
{
"event_id": "evt_...",
"event_type": "brand.analyzed",
"data": {
"brand_id": "brn_01HKZ...",
"status": "ready",
"profile": {
"name": "Linear",
"url": "https://linear.app",
"industry": "saas_developer_tools",
"audience": ["product_managers", "engineering_leaders", "indie_hackers"],
"tone": ["minimal", "confident", "direct"],
"voice": {
"recommendation": "elevenlabs:josh",
"alternatives": ["elevenlabs:adam", "elevenlabs:bella"]
},
"topic_pool": [
"issue tracking workflow",
"engineering team productivity",
"shipping velocity",
"async-first culture",
"design-engineering collaboration",
"..."
],
"colors": {
"primary": "#5E6AD2",
"secondary": "#26283D",
"accent": "#FFFFFF",
"background": "#0D0E10"
},
"fonts": {
"headline": "Inter",
"body": "Inter"
},
"video_styles": ["minimal", "screen_recording", "talking_head"],
"anti_styles": ["meme_template", "high_energy_dance"],
"logo_url": "https://cdn.reelsbuilder.ai/brands/brn_.../logo.png",
"tagline": "The issue tracker for high-performance teams"
}
}
}Profile field reference
| Field | Type | How it's derived |
|---|---|---|
industry | enum | Classified from page content + sitemap. 80+ canonical industries. Drives clip-type defaults. |
audience | string[] | 2-5 audience segments inferred from copy + meta tags. Drives hook tone. |
tone | string[] | 2-4 tone descriptors. Drives voice + script style. |
voice.recommendation | string | Best ElevenLabs voice match. Format: elevenlabs:<name>. |
topic_pool | string[] | 20-40 topics the brand could plausibly post about. Used for content calendars + auto-rotation (least-used first). |
colors | object | Extracted from CSS + logo. Primary + secondary + accent + background, all hex. |
fonts | object | Headline + body family. Falls back to safe web defaults if non-web fonts are detected. |
video_styles | enum[] | Recommended video style presets. See Video Generation. |
anti_styles | enum[] | Styles to avoid for this brand. Equally important. |
logo_url | URL | Cached on Cloudflare R2. Usable as brand_logo in video generation requests. |
tagline | string | Brand tagline pulled from meta title / hero. |
Examples
TypeScript (poll for completion)
const r = await fetch("https://api.reelsbuilder.ai/api/v1/brand/analyze", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.REELSBUILDER_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({ url: "https://linear.app" }),
});
const { data: { brand_id } } = await r.json();
// poll every 2s
while (true) {
await new Promise((res) => setTimeout(res, 2000));
const r2 = await fetch(
`https://api.reelsbuilder.ai/api/v1/brand/${brand_id}`,
{
headers: { Authorization: `Bearer ${process.env.REELSBUILDER_API_KEY}` },
},
);
const { data } = await r2.json();
if (data.status === "ready") {
console.log("Brand profile:", data.profile);
break;
}
}Python (webhook-driven)
# Kick off the analysis
import os, uuid, requests
r = requests.post(
"https://api.reelsbuilder.ai/api/v1/brand/analyze",
headers={
"Authorization": f"Bearer {os.environ['REELSBUILDER_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"url": "https://linear.app",
"webhook_url": "https://your-app.example.com/webhooks/brand-ready",
},
)
job = r.json()["data"]
print(f"Started job {job['job_id']} for brand {job['brand_id']}")
# Receive webhook (FastAPI snippet)
from fastapi import FastAPI, Request, Header, HTTPException
app = FastAPI()
@app.post("/webhooks/brand-ready")
async def handle_brand(request: Request, x_rb_signature: str = Header(None)):
body = await request.body()
# verify signature -- see /docs/api/webhooks
payload = await request.json()
if payload["event_type"] == "brand.analyzed":
profile = payload["data"]["profile"]
# store in your DB
return {"ok": True}Brand recommendations endpoint
GET /api/v1/brand/{brand_id}/recommendations returns a content plan for the next 7 days, combining the brand profile with live Viral Trends:
{
"success": true,
"data": {
"brand_id": "brn_...",
"recommendations": [
{
"date": "2026-05-16",
"topic": "shipping velocity benchmarks Q1 2026",
"hook_format_suggestion": "data_point",
"platform_suggestion": "linkedin",
"trend_match_score": 0.78,
"rationale": "Aligned with brand audience (engineering_leaders) and trending in tech category."
}
]
}
}Manual override
Brand DNA gets ~85% of the profile right on first pass. For the fields that need correction, use PATCH:
curl -X PATCH https://api.reelsbuilder.ai/api/v1/brand/brn_01HKZ... \
-H "Authorization: Bearer $REELSBUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tone": ["minimal", "confident", "playful"],
"anti_styles": ["meme_template", "high_energy_dance", "fake_chat"]
}'Overridden fields are flagged and never reverted on subsequent re-analysis (PATCH wins forever; you can clear an override by PATCH-ing the field back to null).
Re-analysis
Brands change. Re-analyze by POST-ing the same URL again — the response includes a previous_brand_id field so you can diff. Manual overrides survive re-analysis.
Pricing
- 8 credits per
POST /brand/analyze(covers crawl + classification + voice match + color extraction). - 0 credits for
GETreads. - 3 credits per
GET /recommendations(includes Viral Trends lookup). - 0 credits for
PATCHoverrides.
Performance
- Cold (new URL): 8-12 seconds end-to-end
- Warm (URL re-analyzed within 7d): 2-4 seconds (cached crawl)
- P99 latency: 30 seconds (cap; throws
PROCESS_TIMEOUT)
See also
- Hook Generator API — pass
brand_idfor tuned hooks - Video Generation API — every endpoint accepts
brand_idfor personalization - Viral Trends API — used internally by
/recommendations