# Brandiseer Developer API — Reference

Authentication: `X-API-Key: bds_...` header on every request.

Base URL: `https://brandiseer.com/api/v1`

## Endpoints

### `GET /api/v1/health`
Returns `{ "status": "ok" }`. No authentication required.

### `GET /api/v1/credits`
Returns the authenticated user's current credit balance.
- **Auth**: API key.
- **Response**: `{ "credits": <number> }`.

### `GET /api/v1/usage`
Returns API usage summary for the current user.
- **Auth**: cookie session (browser dashboard).

### `GET /api/v1/brands`
Lists the user's custom brands. Each brand has an `id` like `bds_c_42`.
- **Auth**: API key.

### `GET /api/v1/my-brands`
Same as `/brands` but uses the cookie session.

### `POST /api/v2/generate`
Generates one brand-consistent image synchronously (response contains the result directly).
- **Auth**: API key.
- **Body**:
  ```json
  {
    "brandId": "bds_c_42",
    "prompt": "summer sale banner for Instagram",
    "aspectRatio": "1:1",
    "resolution": "1K",
    "mode": "fast",
    "useLogo": false
  }
  ```
- **`mode`** (optional, default `"fast"`): one of `"fast"`, `"design"`, `"pro"`.
- **Response**: `{ "imageUrl": "...", "creditsUsed": 4 }`.
- **Status codes**: `200`, `400`, `401`, `402` (insufficient credits), `404` (brand not found), `500`.
- **Timeout note**: Design mode takes 40–70 s. If your HTTP client has a hard timeout below 60 s, use `/generate/async` instead.
- **v1 note**: `/api/v1/generate` still works for legacy callers but uses `proMode: boolean` instead of `mode` and only supports Fast and Pro.

### `POST /api/v2/generate/async`
Submit a generation job and receive an immediate job ID. Required for Design mode with strict client timeouts.
- **Auth**: API key.
- **Body**: identical to `/api/v2/generate`.
- **Response (HTTP 202)**: `{ "data": { "jobId": "bds_job_xxxx" } }`. Credits deducted immediately.
- Poll `GET /api/v2/jobs/:jobId` every 3–5 s until `status` is `"done"` or `"failed"`.

### `GET /api/v2/jobs/:jobId`
Poll for the result of an async generation job.
- **Auth**: API key (must match the key used to submit).
- **Response when done**: `{ "data": { "status": "done", "imageUrl": "...", "creditsUsed": N, "referenceImage": null } }`.
- **Response when failed**: `{ "data": { "status": "failed", "error": { "code": "...", "message": "..." } } }`.
- Jobs expire after 10 minutes. Credits are automatically refunded on failure.

## Credit cost per generation

| Mode   | 1K | 2K | 4K |
|--------|----|----|----|
| Fast   | 4  | 6  | 8  |
| Design | 5  | 6  | 8  |
| Pro    | 6  | 8  | 10 |

Failed generations refund credits automatically.

## v2.1 — Video generation (additive, image-to-video only)

`https://brandiseer.com/api/v2.1` adds animation on top of v2. It is purely additive: v1 and v2 image
generation are completely unaffected by v2.1, and a v2.1 failure never impacts them. There is no
text-to-video mode — a starting image is always required (image-to-video only), and no automatic
fallback exists between v2.1 and v2.

**Recommended workflow — chain v2 → v2.1**: generate a still image with `POST /api/v2/generate` (or its
async variant), take the returned `imageUrl`, then submit it to v2.1 to animate it.

### `POST /api/v2.1/video/generate`
Submits an image-to-video generation job. Always async: returns immediately with a job ID; poll for the result.
- **Auth**: API key.
- **Source image — exactly one, two ways to provide it**: either `imageUrl` (a publicly reachable URL) in
  the JSON body, or a single multipart file upload under the field name `image`. Never both, never neither.
  No arrays, no indexed fields, no base64/data URLs, no separate audio/video reference uploads.
- **Body**:
  ```json
  {
    "brandId": "bds_c_42",
    "imageUrl": "https://brandiseer.com/assets/...",
    "prompt": "The subject tilts its head. Gentle push-in camera movement. Natural ambience, no dialogue.",
    "tier": "premium",
    "duration": 6,
    "resolution": "720p"
  }
  ```
- **`tier`** (optional, default `"premium"`): `"standard"` or `"premium"`.
- **`duration`** (required, integer seconds): `4-30` for premium, `5-15` for standard.
- **`resolution`** (optional, default `"720p"`): `"720p"` or `"1080p"`, premium tier only. Standard tier is
  fixed-resolution — sending `resolution` with `tier: "standard"` is rejected, not silently ignored.
- **`idempotencyKey`** (optional): a retried request with the same key returns the original job instead of
  submitting (and charging) again.
- **Response (HTTP 202)**: `{ "data": { "jobId": "...", "status": "pending", "tier": ..., "duration": ..., "resolution": ..., "creditsUsed": N, "remainingCredits": N } }`. Credits deducted immediately.

### `GET /api/v2.1/video/jobs/:jobId`
Poll for the result of a video generation job.
- **Auth**: API key (must match the key used to submit — a mismatched key gets `404`, same as an unknown job ID).
- **Response when pending**: `{ "data": { "status": "pending" } }`.
- **Response when completed**: `{ "data": { "status": "completed", "videoUrl": "...", "sourceImageUrl": "...", "tier": ..., "duration": ..., "resolution": ..., "creditsUsed": N } }`. The video is also saved to your Brandiseer asset library.
- **Response when failed**: `{ "data": { "status": "failed", "error": { "code": "...", "message": "..." } } }`. Credits are refunded automatically.

### Credit cost per second (v2.1 video)

| Tier     | Resolution      | Duration | Cost / second |
|----------|-----------------|----------|----------------|
| standard | fixed           | 5-15s    | 10 credits     |
| premium  | 720p (default)  | 4-30s    | 20 credits     |
| premium  | 1080p           | 4-30s    | 30 credits     |

## v2.2 — Automatic brand creation from a website URL (additive)

`https://brandiseer.com/api/v2.2` creates a complete Brandiseer brand profile from only a website
URL. It is purely additive and fully isolated: v1, v2 image generation, and v2.1 video generation are
completely unaffected by v2.2, and a v2.2 failure never impacts them. There is no manual review step —
the server scrapes the site, automatically picks the logo and visual assets, and saves the finished
brand in one pipeline. The resulting brand appears in `GET /api/v2/brands` and works immediately with
`POST /api/v2/generate` and `POST /api/v2.1/video/generate`.

**Recommended workflow**: `POST /api/v2.2/brands/create` with a website URL → poll
`GET /api/v2.2/brands/jobs/:jobId` every 5-10 s → on completion, use the returned `brandId` with v2/v2.1.

### `POST /api/v2.2/brands/create`
Submits an automatic brand-creation job. Always async: returns immediately with a job ID.
- **Auth**: API key or OAuth bearer token.
- **Body**:
  ```json
  {
    "websiteUrl": "https://example.com",
    "idempotencyKey": "optional-client-key"
  }
  ```
- **`websiteUrl`** (required): must be a publicly reachable `http(s)` URL. Private/loopback hosts are rejected.
- **`idempotencyKey`** (optional): a retried request with the same key returns the original job instead of
  submitting (and eventually charging) again.
- **Response (HTTP 202)**: `{ "data": { "jobId": "...", "status": "queued" } }`. No credits are deducted at
  submission time — see credit cost below.

### `GET /api/v2.2/brands/jobs/:jobId`
Poll for the result of a brand-creation job.
- **Auth**: API key or OAuth bearer token (must match the credential used to submit — a mismatched key gets
  `404`, same as an unknown job ID).
- **Response while in progress**: `{ "data": { "status": "queued" } }` or `{ "data": { "status": "processing" } }`.
- **Response when completed**: `{ "data": { "status": "completed", "brandId": "bds_c_123", "brandName": "...", "creditsUsed": 20 } }`.
  The brand is immediately usable with `POST /api/v2/generate` and `POST /api/v2.1/video/generate`.
- **Response when failed**: `{ "data": { "status": "failed", "error": { "code": "...", "message": "..." } } }`.
  No credits are ever charged for a failed job, and no partial brand is created.

### Failure codes
| Code | Meaning |
|------|---------|
| `NO_LOGO_FOUND` | The site could not be scraped, or scraping succeeded but no usable logo was found. A scraped logo is required — visual assets besides the logo are optional. |
| `INSUFFICIENT_CREDITS` | The account did not have 20 credits available (checked both at submission and again right before the brand is committed). |
| `ANALYSIS_FAILED` / `INTERNAL_ERROR` | An unexpected failure during scraping, analysis, or persistence. Safe to retry with a new `idempotencyKey`. |

Every failure response's `message` field directs the caller back to the manual flow: "We couldn't
automatically add your brand. Please visit brandiseer.com to add it manually; the website process requires
your review."

### Idempotency and retries
Supplying the same `idempotencyKey` on `POST /api/v2.2/brands/create` never creates a second brand or a
second charge — a repeated submit while the original job is still running or already finished returns the
existing job's id and current status instead of starting new work. Once a job has failed, retry with a new
`idempotencyKey` to try again from scratch.

### Credit cost
20 credits — identical to the browser Upload Brand flow — charged exactly once, only when the brand is
successfully created. Failed jobs are never charged.

## Guide endpoints (optional, recommended)

Three unauthenticated, read-only, side-effect-free markdown endpoints written for LLM/agent integrators.
None are required — every endpoint above works without calling these first — but each one meaningfully
improves the odds a request succeeds on the first try:

- **`GET /guide/image`** — the Brandiseer Prompt Compatibility Check for `POST /api/v2/generate` (and v1).
  Core point: Brandiseer's brand system prompt already owns color, typography, and visual style on every
  generation, so a prompt that also specifies style ("navy palette", "elegant serif font", "moody cinematic
  lighting") competes with — and can silently override — the real brand identity. This guide gives exact
  rules for what to strip vs. keep, and how to handle ambiguous cases (asking the user rather than guessing).
- **`GET /guide/video`** — prompting guidance for `POST /api/v2.1/video/generate`: prompt structure, camera
  language, timestamps, action/expression description, and audio/dialogue prompting for a single-image
  motion prompt.
- **`GET /guide/docs`** — this document, served as machine-readable markdown at a stable, unauthenticated URL.

## SDKs

No official SDK yet. Use any HTTP client.

## Discovery files

- [OpenAPI spec](https://brandiseer.com/.well-known/openapi.json)
- [API catalog](https://brandiseer.com/.well-known/api-catalog)
- [llms.txt](https://brandiseer.com/llms.txt)
- [MCP manifest](https://brandiseer.com/.well-known/mcp/manifest.json)
