Brand extraction, then on-brand content
Extract a user's brand once, then create everything on-brand.
The most common integration: during onboarding, extract the user's brand once, then power every subsequent design request with it. Brand extraction is the most expensive single call you'll make — and the one you'll make the least often.
1. Gather brand references
Let the user provide any mix of:
- their website — just a URL,
- images — logos, previous posts, packaging photos,
- a .zip of brand guidelines — the full drop from their designer,
- Canva designs or existing materials.
A single reference works; more references give a more complete picture. Don't make users hunt for perfect inputs — Rivermark reconciles conflicting signals (like a website palette that differs from official guidelines) into one coherent brand.
2. Extract the brand kit
const api = (path: string, body: object) =>
fetch("https://api.rivermark.ai" + path, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIVERMARK_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}).then((r) => r.json());
// 1. Upload any files the user attached
const references = [];
for (const file of userAttachments) {
const form = new FormData();
form.append("file", file);
const uploaded = await fetch("https://api.rivermark.ai/upload", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.RIVERMARK_API_KEY}` },
body: form,
}).then((r) => r.json());
references.push({ type: "file", id: uploaded.id });
}
// 2. Add their website
if (userWebsite) references.push({ type: "url", url: userWebsite });
// 3. Extract the brand
const brandkit = await api("/brandkit", {
references,
allow_fetch: true, // let it reach the About page, media kit, etc.
});
// 4. Store the design ID — this is your permanent brand handle
await db.brandkits.create({ userId: user.id, designId: brandkit.design_id });The response gives you a structured brand definition plus ready-made visuals:
{
"design_id": "rmd_cj4hbqz4f0005mz6x7p9q2xr",
"name": "Acme Coffee Co.",
"tagline": "Slow mornings, fast coffee",
"palette": [{ "hex": "#2D1B0E", "name": "Roast", "role": "primary" }],
"fonts": [{ "family": "Fraunces", "role": "title" }],
"brand_board": "https://cdn.rivermark.ai/rmd_cj4hbqz4f0005mz6x7p9q2xr/q7m2xk4d/board.png",
"brand_header": "https://cdn.rivermark.ai/rmd_cj4hbqz4f0005mz6x7p9q2xr/q7m2xk4d/header.png",
"cost": 0.75
}3. Use what you got
In your interface:
brand_board— a full visual board of the brand; great as an onboarding "this is what we found" confirmation screen.brand_header— a compact 1200x900 card (logo, tagline, palette); use it wherever the user needs to identify the brand, like a brand picker.
Download both immediately — rendered URLs are ephemeral.
In Rivermark: design_id is the brand handle. Everything the agent makes with it uses the extracted fonts, colors, logos, and imagery as-is — never approximated or redrawn. No brand parameters to configure, no style JSON to maintain.
4. Create on-brand content
Now every content request is one call referencing the brand kit:
const design = await api("/design", {
task: [
"Create an Instagram post announcing our new seasonal roast.",
"Headline: 'The Autumn Roast is here'.",
"Subline: 'Notes of fig, cedar, and bonfire smoke.'",
].join(" "),
references: [{ type: "design", id: brandkit.design_id }],
output: [{ id: "post", size: "1080x1350" }],
});The agent will use the brand kit's fonts, hex values, logos, and imagery as-is. No brand parameters to configure, no style JSON to maintain.
Economics
A brand extraction is done once per user and amortizes across every design they ever create — see Costs for typical numbers, and the user-created templates guide for how to make each subsequent design even cheaper.

