
# Generate tools

Two in-process generators — render and fake data — on [satori](https://github.com/vercel/satori), [sharp](https://sharp.pixelplumbing.com/), and [`@faker-js/faker`](https://fakerjs.dev/), all pure-JS, the same open-source libraries you could run yourself. Every op is a `POST https://api.relaystation.ai/v1/generate/<op>`.

## Billing

Both ops are **flat** per-call at `cputools.price.generate.<op>.flat_micros` (launch defaults: og-image $0.0005, mock-data $0.0002). The live `402` challenge is authoritative.

| Op | Billed on | Rate |
|---|---|---|
| `og-image` | per call | $0.0005 flat |
| `mock-data` | per call | $0.0002 flat |

## og-image

Render a clean social-card **PNG** from a title (and optional subtitle + theme + size): satori builds the SVG, the vendored sharp rasterizes it. Returns the uniform **output envelope** (`image/png`, inline base64 — OG images are always small). One clean template — `title`, optional `subtitle`, `theme` (`light`/`dark`), `width` (600–2000), `height` (300–1200).

```json
POST /v1/generate/og-image
{ "title": "Quarterly report", "subtitle": "Q2 2026", "theme": "dark" }
```

## mock-data

Generate fake rows from a field→type schema. `count` rows (≤ `cputools.generate.mock-data.max_rows`, default 1000), at most `cputools.generate.mock-data.max_fields` fields (default 50). `format` is `json` (default), `csv`, or `ndjson`. Supported field types: `name`, `firstName`, `lastName`, `email`, `uuid`, `int`, `float`, `bool`, `date`, `address`, `city`, `country`, `phone`, `company`, `url`, `word`, `sentence`, `paragraph`. An unknown type → `422 UNSUPPORTED_TYPE` (pre-charge). Returns the uniform output envelope (`application/json` / `text/csv` / `application/x-ndjson`).

```json
POST /v1/generate/mock-data
{ "schema": { "name": "name", "email": "email", "age": "int" }, "count": 100, "format": "csv" }
```

## invoice

Render a clean **invoice PDF** from structured data (pdf-lib, in-process). Pass `seller` + `buyer` (`{ name, address?, email? }`), an `items` array (1–100 of `{ description, quantity, unitPrice }`), and optional `number`, `date`, `currency` (default `$`), `taxRate` (0–100 %), `notes`. Computes subtotal / tax / total. Returns the uniform output envelope (`application/pdf`). Flat per-call price.

```json
POST /v1/generate/invoice
{ "seller": { "name": "Acme LLC", "email": "billing@acme.com" },
  "buyer": { "name": "Globex" },
  "number": "INV-1042", "currency": "$",
  "items": [ { "description": "Widget", "quantity": 3, "unitPrice": 9.99 } ],
  "taxRate": 8.25 }
```

## chart

Render a **bar / line / pie chart PNG** from data points — hand-rolled SVG rasterized by the vendored sharp (no charting library, no browser). `type` is `bar`, `line`, or `pie`; `data` is 1–50 `{ label, value }` points; optional `title`, `width` (200–2000), `height` (150–2000), `color`. Flat per-call price.

```json
POST /v1/generate/chart
{ "type": "bar", "title": "Signups", "data": [ {"label":"Jan","value":120}, {"label":"Feb","value":210} ] }
```

## qr-logo

Render a **QR code with your logo composited in the center**. The QR is generated at error-correction level **H** (30 % recovery) so the centered logo doesn't break scanning, and the logo gets a white pad for quiet-zone contrast. Pass `data` (the encoded string) and `logo` (an image `{ inline }` or `{ inputKey }`), plus optional `size` (128–2000), `margin` (0–16), `logoScale` (0.1–0.35). Returns a PNG. A logo that doesn't decode as an image → `422 IMAGE_PARSE_FAILED` (pre-charge). Flat per-call price.

```json
POST /v1/generate/qr-logo
{ "data": "https://relaystation.ai", "logo": { "inline": "<base64-png>" }, "size": 512 }
```

## favicon

Generate a **favicon set** (PNGs at several sizes) from **either** an image **or** initials text — provide exactly one of `image` (`{ inline }` / `{ inputKey }`) or `text` (1–3 chars). Optional `background`, `color`, and `sizes` (default `[16, 32, 48, 180]`, ≤ 8). Returns `{ icons: [{ size, output }] }`, each `output` a uniform envelope. Flat per-call price.

```json
POST /v1/generate/favicon
{ "text": "RS", "background": "#2563eb", "color": "#ffffff" }
```

## placeholder

Render a **placeholder image** — a solid background with centered dimensions/label text (hand-rolled SVG). Pass `width` + `height` (8–4000), optional `background`, `color`, `text` (defaults to `"W×H"`), and `format` (`png` default, or `svg`). Flat per-call price.

```json
POST /v1/generate/placeholder
{ "width": 600, "height": 400, "text": "Hero image" }
```

## identicon

Render a **deterministic GitHub-style identicon** — a 5×5 mirror-symmetric PNG derived from a seed string (sha256 → colour + cell grid). The **same seed always yields the same image**, so it's a stable avatar for any stable id (email, wallet, username). Pass `seed`, optional `size` (32–1024), `background`. Flat per-call price.

```json
POST /v1/generate/identicon
{ "seed": "alice@example.com", "size": 256 }
```

## Sample

```bash
curl -X POST https://api.relaystation.ai/v1/generate/mock-data \
  -H 'X-Payment: <base64 EIP-3009 auth>' \
  -H 'Idempotency-Key: seed-fixtures-20260609' \
  -H 'Content-Type: application/json' \
  -d '{"schema":{"name":"name","email":"email"},"count":50,"format":"json"}'
```

## Errors

- `402 PAYMENT_REQUIRED` — no valid payment.
- `422 UNSUPPORTED_TYPE` — a mock-data schema field names a type outside the allowlist (the response lists the supported types). Rejected **before** any charge.
- `422 COUNT_TOO_LARGE` / `422 TOO_MANY_FIELDS` — over the row/field cap, pre-charge.
- `422 IMAGE_PARSE_FAILED` — a `qr-logo` logo or `favicon` image input didn't decode as an image. Rejected **before** any charge.
- `404` — a storage-ref `inputKey` (qr-logo logo / favicon image) is not owned by the caller.
- `400 VALIDATION_ERROR` — the body failed schema validation (e.g. an empty `title`, a width/height out of range, or `favicon` given neither/both of `image` and `text`).

## Next

[PDF tools](/docs/pdf-tools) · [CSV tools](/docs/csv-tools) · [Image tools](/docs/image-tools) · [Utils tools](/docs/utils-tools) · [Archive tools](/docs/archive-tools) · [Pricing](/pricing) · [API reference](/api-reference)
