RivermarkRivermark
Guides

Give your agents design taste

Turn Claude Code, Codex, or any shell-capable agent into a designer with one skill file.

Coding agents are already good at shell, HTTP, and file handling — which is all the Design API needs. Give one a key and a short skill file, and it can produce OG images, social posts, ads, and resizes straight into your repo.

This is a three-step setup, and the whole capability is one markdown file you can copy-paste.

1. Get a key into the agent's environment

Create an API key in the API dashboard and expose it as RIVERMARK_API_KEY wherever your agent runs:

export RIVERMARK_API_KEY="rmk_live_…"

Keep the key out of git

Add RIVERMARK_API_KEY to your shell profile or secret manager, never to a committed file. The skill below tells the agent to read it from the environment.

2. Save the skill

Copy the block below into one of these, depending on your agent:

  • Claude Code — .claude/skills/rivermark/SKILL.md
  • Codex — .agent/skills/rivermark/SKILL.md
  • Cursor and other agents — AGENTS.md at the root of your repo, or your agent's project instructions
.claude/skills/rivermark/SKILL.md
---
name: rivermark
description: Create and edit on-brand designs — social posts, ads, OG images, posters, carousels — and extract brand kits, with the Rivermark Design API. Use when asked for visual assets, designs, resizes, or brand extraction.
---

# Rivermark Design API

Generate finished design files from a text brief. Designs are HTML/CSS rendered to images.

- Base URL: `https://api.rivermark.ai` (no version prefix)
- Auth: `Authorization: Bearer $RIVERMARK_API_KEY` — read it from the environment; never print or commit it
- All endpoints are JSON. Use `curl` and `jq`

## Brand kit — do this before your first design

Every project keeps one persistent brand kit at `.rivermark/brand.json`. Check for it before creating any design.

**If it exists**, read `design_id` and pass it as a reference on every design call:

```json
{ "type": "design", "id": "<design_id from .rivermark/brand.json>" }
```

**If it doesn't exist**, extract one:

1. Collect the best brand sources you have for this company: the website URL, plus any logos, guidelines, or past material in the repo (`brand/`, `assets/`, `public/`, a guidelines `.zip`). Upload files with `POST /upload` to get `rmf_…` ids.
2. Extract: `POST /brandkit` with those references, and `"allow_fetch": true` so it can follow links on the site.
3. **Check with the human before saving.** Show them the `brand_board` image URL, the `palette`, `fonts`, and `voice`, and ask if anything is off. If they want changes, `POST /design` with `continue_from` set to the brand kit's `design_id` and their instructions, then use the returned id.
4. Save the confirmed result to `.rivermark/brand.json`:

```json
{
  "design_id": "rmd_cj4hbqz4f0005mz6x7p9q2xr",
  "name": "Acme Coffee Co.",
  "palette": [{ "hex": "#2D1B0E", "name": "Roast", "role": "primary" }],
  "fonts": [{ "family": "Fraunces", "role": "title" }],
  "voice": "Warm, playful, unpretentious."
}
```

5. From then on, pass `{ "type": "design", "id": design_id }` on every design call, and use `palette`, `fonts`, and `voice` to keep copy and UI decisions on-brand.
6. If the brand changes, re-run the extraction and update the file. Commit it if the whole team should share one brand kit.

## POST /design — create or edit

```json
{
  "task": "Create an OG image for a blog post about coffee brewing. Bold headline, minimal, no more than 6 words.",
  "references": [
    { "type": "design", "id": "rmd_cj4hbqz4f0005mz6x7p9q2xr" },
    { "type": "file", "id": "rmf_cj4hbqz9x0001v2x8n6tqz7e" },
    { "type": "url", "url": "https://acmecoffee.co" },
    { "type": "text", "name": "copy.md", "text": "Headline: Slow mornings" }
  ],
  "output": [{ "id": "og_image", "size": "1200x630" }],
  "creativity": 1,
  "continue_from": "rmd_cj4hbqz2w0003mz6x7p9q2xe",
  "image_source": "ai",
  "allow_fetch": false,
  "auto_review": true
}
```

- `task` (required) — the brief. Be specific about the deliverable, the copy, and constraints.
- `references` — any mix of `design` (`rmd_…` id), `file` (`rmf_…` id), `url`, `text`, `html`.
- `output` — `[{ "id": "name", "size": "WIDTHxHEIGHT", "format": "png|jpeg|webp|pdf|html" }]`, or just `"png"`.
- `creativity` — `0` literal (template fills, copy swaps), `1` balanced (default), `2` exploratory (ideas).
- `continue_from` — a design id to iterate on. The original is forked and the reply gets a new id.
- `auto_review` — leave `true`; it catches overflow, clipping, and invented copy.
- Unknown fields are ignored; omitted fields use the defaults above.

Response: `design_id` (`rmd_…`), `output[]` with `{ id, url, format, width, height }`, `changes[]`, `change_summary`, and `cost` in USD.

**`output[].url` expires.** Download every file you want to keep in the same step.

## POST /brandkit — extract a brand

Same `references` shape, plus optional `instructions` and `allow_fetch`. Returns `design_id` (a brand kit is a design — pass it as a `design` reference), plus `name`, `tagline`, `palette`, `fonts`, `assets`, `voice`, `brand_board`, `brand_header`.

## POST /upload — get a file id

`curl -F "file=@path/to.png"` returns `{ "id": "rmf_…" }`. Use it as a `file` reference.
Or `{"url": "https://…"}` to snapshot a page. Files stay reusable across requests.

## GET /design/{id} · DELETE /design/{id}

Design metadata, or permanent removal.

## Streaming

Add `?stream=true` for Server-Sent Events: `progress` (`{message}`), `preview` (`{id,url,label}` — same `id` supersedes), `completed` (full response), `error`.

## Rules

1. Download outputs immediately — the URLs are temporary; `design_id`s are permanent.
2. To reuse a design, keep its id: as a `design` reference (template/style source) or `continue_from` (iterate on it).
3. For copy-only changes at scale, use `creativity: 0` and `image_source: "none"`.
4. Never invent brand assets — pass the brand kit from `.rivermark/brand.json` (extract one first if it is missing).
5. Every response reports `cost`; prefer one render over many retries.

## Commands

```bash
# create, then download the result
curl -s -X POST https://api.rivermark.ai/design \
  -H "Authorization: Bearer $RIVERMARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "task": "Create a 1200x630 OG image for a blog post about coffee brewing. Bold headline, minimal.",
    "output": [{ "id": "og", "size": "1200x630" }]
  }' | tee /tmp/design.json | jq -r '.output[0].url' | xargs curl -s -o public/og.png

# iterate on what you just made (fork + edit)
DESIGN_ID=$(jq -r .design_id /tmp/design.json)
curl -s -X POST https://api.rivermark.ai/design \
  -H "Authorization: Bearer $RIVERMARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"task\": \"Make the headline smaller and add the site URL at the bottom.\",
    \"continue_from\": \"$DESIGN_ID\"
  }" | jq -r '.output[0].url' | xargs curl -s -o public/og-v2.png

# upload a logo for later use
curl -s -X POST https://api.rivermark.ai/upload \
  -H "Authorization: Bearer $RIVERMARK_API_KEY" \
  -F "file=@assets/logo.png" | jq -r .id
```

Full documentation: https://rivermark.ai/docs/design-api
Machine-readable index: https://rivermark.ai/docs/llms.txt · everything in one file: https://rivermark.ai/docs/llms-full.txt

3. Ask for a design

With the skill in place, plain requests work. For example:

  • "Make an OG image for the payments blog post and save it to public/og-payments.png."
  • "Extract our brand from https://acmecoffee.co plus the files in brand/, then create a set of LinkedIn post options using it."
  • "We just shipped v2.5 — generate a release asset set (OG image, X post, and a square LinkedIn post) from the changelog, then iterate on the one I like."
  • "Take public/og-payments.png's design and resize it for Instagram story and X header."

The agent reads the skill, calls the API, downloads the files, and shows you the result — no wrapper code, no SDK, no server to run.

Worth knowing

It's a normal HTTP call, so it works anywhere. The same skill file is useful beyond coding agents: CI jobs, scripts, and internal tools can all shell out to curl.

Give it a budget. Every response includes cost, and the skill tells the agent to read it. In an unconstrained loop, a curious agent can spend real credits — mention a budget in your prompt ("keep it under a few cents") or start with one asset.

Review what it ships. Generations land in your working tree like any other change — check the images before committing, and keep the design IDs the agent reports if you want to iterate later.

On this page