
# Codes tools — decode & color

Two in-process readers that complement the [QR/barcode generators](/docs/cputools-qr-tools). Pure JavaScript ([`jsqr`](https://github.com/cozmo/jsQR) over a [`sharp`](https://sharp.pixelplumbing.com/) decode; color math is plain arithmetic). Each is a `POST https://api.relaystation.ai/v1/codes/<op>` returning a small **JSON object**.

## Billing

Both are **flat** at `cputools.price.codes.<op>.flat_micros` (launch default $0.0002 / call — a placeholder the operator tunes). The live `402` challenge is authoritative.

| Op | Billed on | Rate |
|---|---|---|
| `qr-decode` | per call | $0.0002 flat |
| `color-convert` | per call | $0.0002 flat |

## qr-decode

Read a QR code from an uploaded image. Body: `{ file: <source> }` (inline base64 ≤ 4 MB or an `inputKey` from `/v1/cputools/upload-url`). A non-decodable image is a **paid** `{ found: false }`; a non-image input is a free `422`. Returns `{ found, data?, version? }`.

```json
POST /v1/codes/qr-decode
{ "file": { "inline": "<base64 PNG/JPEG>" } }
```

## color-convert

Convert a color between `hex`, `rgb`, and `hsl` (including alpha forms — `#rrggbbaa`, `rgba()`, `hsla()`). Body: `{ color, to }`. Unrecognized input → `422 COLOR_INVALID`. Returns `{ input, to, result, rgb }`.

```json
POST /v1/codes/color-convert
{ "color": "#ff8800", "to": "hsl" }
```

> **Not yet:** 1D **barcode decoding** is deferred — there's no clean pure-JS Node decoder (the common libraries need a browser DOM or a WASM binary). Barcode **generation** ships today at `/v1/barcode`.
