# Randomly API

> A free, keyless HTTP API returning random data — numbers, passphrases, maths problems, procedural images and audio — seeded from 10 real-world entropy sources, with a receipt naming the physical source and linking to third-party proof. No signup, no key, no account. 63 generators.

## Base URL

```
https://randomly.cluxnei.dev/api/v1
```

No authentication, no key, no signup, no account — matching every source this project
draws from. The site's own pages call these same endpoints; there is no private path
with different behaviour.

**Rate limits, per IP.** 60 requests a minute overall, of which at most
20 may be PNG or WAV renders. A render starts a Node process and costs
a hundred times what a JSON response costs, so it is charged against *both* buckets. A
`429` carries `retry_after_seconds` and both limits, because the caller is usually a
script or a model rather than a person reading a page. The count is per server, not
distributed — this is a showcase, and claiming otherwise would be the kind of
overstatement the rest of the project exists to avoid.

## The one-liner

```bash
curl -s 'https://randomly.cluxnei.dev/api/v1/g/numbers.integers?count=6&min=1&max=60&unique=1' -H 'Accept: text/plain'
# 20, 22, 26, 35, 47, 51
```

## Endpoints

| Method | Path | Returns |
|---|---|---|
| `GET` | `/api/v1/generators` | the whole catalogue with every generator's declared parameters |
| `GET` | `/api/v1/sources` | the 10 entropy sources, their class and live status |
| `GET` | `/api/v1/g/{key}?…` | generate — the shorthand, for one-liners |
| `POST` | `/api/v1/generate` | generate — `{"generator", "params", "source"}` as JSON |
| `GET` | `/api/v1/replay/{token}?g=&v=` | recompute a past result exactly |

## Discover before you call

```bash
curl -s 'https://randomly.cluxnei.dev/api/v1/generators'
```

Every entry carries `key`, `name`, `tagline`, `module`, `renderer`, `version`, the
`formats` it can be served as, the three behaviour flags below, and `params` — each with
its `type`, `default`, and `min`/`max` or `options`. **Read `params` rather than
guessing.** Numbers outside their bounds are clamped rather than rejected, so a request
always succeeds, but it may not do what you meant.

Three flags decide what a client may do with a generator:

| Flag | What it tells a caller |
|---|---|
| `sensitive` | `true` for a generator that produces secrets — a password, a passphrase, an identifier. It is given **no token and no permalink**, and `/api/v1/replay` returns `404`. A secret with a replayable URL is not a secret. |
| `reproducible` | `true` means a permalink recomputes the result exactly. `false` for a generator built on live external material that moves, so no permalink is issued — a link that quietly stops working is worse than no link. |
| `uses_entropy` | `true` for almost everything. `false` for a pure function of its input (an identicon): no source is consulted, nothing is spent waiting on a beacon, and the receipt says so rather than crediting a source that changed nothing. |

## Generating

```bash
# GET shorthand
curl -s 'https://randomly.cluxnei.dev/api/v1/g/numbers.dice?notation=4d6kh3&rolls=6'

# POST, for long parameter sets
curl -s -X POST 'https://randomly.cluxnei.dev/api/v1/generate' \
     -H 'Content-Type: application/json' \
     -d '{"generator":"numbers.integers","params":{"count":6,"min":1,"max":60,"unique":true},"source":"drand"}'
```

The JSON envelope is the same for every generator:

| Field | Type | What it is |
|---|---|---|
| `value` | varies | the structured result — a list of numbers, a string, a render spec |
| `display` | string | the human-readable form, and the entire body of a `text/plain` response |
| `meta` | object | instrumentation: `entropy_out_bits`, `rejections`, `duration_us`, and whatever else the generator measured |
| `receipt` | object | where the randomness came from — see below |
| `seed.token` | string\|null | 26 Crockford base32 characters. This **is** the seed. `null` for a sensitive generator. |
| `seed.permalink` | string\|null | a URL that recomputes this exact result |

## The receipt

The receipt is the product. Every generated result carries one:

| Field | What it is |
|---|---|
| `source` / `source_label` | which of the 10 sources answered |
| `class` | `A` cryptographic, `B` public beacon, `C` observational |
| `caveat` | the honest limitation of that class, in words, or `null` for Class A |
| `narrative` | one sentence a human can read: the earthquake, the pulse index, the block |
| `proof_url` | a link to the third party's own record of it, so the claim is checkable |
| `reference` | that source's own identifier — a pulse index, a drand round, a block hash |
| `observed_at` | when the material was observed, ISO 8601 |
| `mixed_with_csprng` | `true` whenever a Class B or C source was folded in with fresh local entropy |
| `degraded` | `true` if the requested source was unreachable and the kernel answered instead |

## Choosing an entropy source

`?source=` takes any key below, or `auto` (the default).

| Key | Source | Class | What it physically is |
|---|---|---|---|
| `csprng` | Operating System CSPRNG | A | The kernel entropy pool — interrupt timings, device jitter and, on this machine, the CPU hardware RNG. |
| `anu-qrng` | ANU Quantum Vacuum | A | Fluctuations of the quantum vacuum field, measured by homodyne detection at the Australian National University. |
| `random-org` | RANDOM.ORG | A | Atmospheric radio noise, largely driven by lightning discharges, captured by receivers in Dublin. |
| `nist-beacon` | NIST Randomness Beacon | B | A hardware entropy source at the US National Institute of Standards and Technology, hash-chained and signed every minute. |
| `drand` | drand · League of Entropy | B | A threshold BLS signature jointly produced every three seconds by independent operators across several continents. |
| `bitcoin` | Bitcoin Proof-of-Work | B | The block header hash the entire Bitcoin network spent roughly ten minutes of global hashrate searching for. |
| `seismic` | USGS Seismic Feed | C | Every earthquake above the detection threshold recorded anywhere on Earth in the past hour, published by the US Geological Survey. |
| `space-weather` | NOAA Space Weather | C | The planetary K-index — how much the solar wind is currently disturbing Earth's magnetic field, measured by NOAA. |
| `atmosphere` | Live Weather | C | Temperature, wind and pressure read from a weather station somewhere on Earth, chosen at random for each draw. |
| `iss` | ISS Position | C | The ground track of the International Space Station, 408 km up and moving at 27,600 km/h. |

**Class A** stands alone. **Class B** is unpredictable until published and public forever
after. **Class C** is flavour — an earthquake carries tens of bits of genuine surprise,
not the kilobytes its JSON weighs. Class B and C are therefore *always* mixed with fresh
CSPRNG bytes before anything is generated, and the receipt says so. **If you need a
secret, ask for Class A or do not use this API at all.**

An unreachable source degrades to the kernel rather than failing the request; check
`receipt.degraded`.

## Output formats

| `Accept:` / `?format=` | Returns | Available on |
|---|---|---|
| `application/json` (default) | the envelope above | every generator |
| `text/plain` | just `display` | every generator |
| `image/png` | the rendered image | the 24 canvas generators |
| `audio/wav` | 16-bit PCM, 44.1 kHz | the 8 audio generators |

```bash
curl -o noise.png 'https://randomly.cluxnei.dev/api/v1/g/patterns.perlin?variant=ridged&palette=viridis&format=png'
curl -o beat.wav  'https://randomly.cluxnei.dev/api/v1/g/audio.rhythm?format=wav'
```

Canvas and audio generators return a **render spec** as JSON by default — the algorithm,
its parameters, the palette and a render key — rather than pixels or samples, because the
browser re-derives them from the same byte stream. That keeps a four-minute generative
piece a 2 KB response. An API caller who wants the artefact asks for `format=png` or
`format=wav`; those are rendered by running the same JavaScript the browser runs, under
Node, so the file matches what the studio draws.

Asking for a format a generator cannot produce returns **`406`** naming the ones it can,
never a silent JSON fallback. `formats` in the catalogue tells you in advance.

## Reproducing a result

There is no database. The token **is** the seed, so a permalink recomputes rather than
looks up:

```bash
curl -s 'https://randomly.cluxnei.dev/api/v1/replay/{token}?g=numbers.integers&v=1&p={base64url-params}'
```

`g` (generator key) and `v` (version) are required; `p` defaults to the generator's
defaults. `s` and `r` optionally carry the original source key and its reference, from
which the receipt is rebuilt and marked `reconstructed` — because inventing a fresh
receipt for an old result and presenting it as the original is exactly the lie this
project exists not to tell.

The response is identical to a generation, plus `"replayed": true`.

## Errors

| Status | `error` | Meaning |
|---|---|---|
| `400` | `invalid_params` | a parameter failed the generator's own schema; `fields` names it |
| `400` | `invalid_token` | the token is not 26 valid Crockford base32 characters |
| `404` | `unknown_generator` | not in the catalogue; `available` lists every key that is |
| `404` | `not_replayable` | that generator is `sensitive`, so it never had a replayable link |
| `406` | `unsupported_format` | no such representation; `available` lists the ones there are |
| `409` | `version_changed` | the generator's algorithm changed, so the old output cannot be reproduced. It says so rather than quietly returning something different. |
| `429` | `rate_limited` | includes `retry_after_seconds` and both limits |

`503` is documented as unreachable on purpose: the kernel CSPRNG always answers, so
"all sources down" cannot happen.

## Every generator key

Each links to its own documentation, generated from its declared schema.

**Numbers** — Integers, distributions, dice and the points on a sphere everyone gets wrong.

- [`numbers.integers`](https://randomly.cluxnei.dev/g/numbers/integers.md): Whole numbers in any range, drawn without the bias everyone else ships.
- [`numbers.dice`](https://randomly.cluxnei.dev/g/numbers/dice.md): Full dice notation, rolled without the bias a modulo would introduce.
- [`numbers.gaussian`](https://randomly.cluxnei.dev/g/numbers/gaussian.md): The normal distribution by Box–Muller, plotted as you draw it.
- [`numbers.distribution`](https://randomly.cluxnei.dev/g/numbers/distribution.md): Poisson, Pareto, Zipf, Beta, Cauchy — sampled and plotted.
- [`numbers.decimals`](https://randomly.cluxnei.dev/g/numbers/decimals.md): Floats in a range, at a precision you choose.
- [`numbers.coordinates`](https://randomly.cluxnei.dev/g/numbers/coordinates.md): Uniform on a sphere — not the latitude bug everyone ships.
- [`numbers.lottery`](https://randomly.cluxnei.dev/g/numbers/lottery.md): Mega-Sena, Powerball and EuroMillions — with the odds printed on them.
- [`numbers.coin`](https://randomly.cluxnei.dev/g/numbers/coin.md): Biased or fair, showing the longest run against the expected log₂ n.
- [`numbers.uuid`](https://randomly.cluxnei.dev/g/numbers/uuid.md): UUID v4 and v7, ULID, NanoID — and what each one gives away.
- [`numbers.password`](https://randomly.cluxnei.dev/g/numbers/password.md): Random characters, with the entropy stated in bits instead of a green bar.
- [`numbers.bytes`](https://randomly.cluxnei.dev/g/numbers/bytes.md): The entropy itself, in hex, base64 or binary.
- [`numbers.prime`](https://randomly.cluxnei.dev/g/numbers/prime.md): Miller–Rabin, forty rounds, at the bit width you ask for.
- [`numbers.timestamp`](https://randomly.cluxnei.dev/g/numbers/timestamp.md): A random instant inside a window you define.

**Words** — Passphrases with real entropy, and words that never existed.

- [`words.passphrase`](https://randomly.cluxnei.dev/g/words/passphrase.md): 12.9 bits per word, from a list of 7,776 — and zero for the capital letters.
- [`words.pseudo`](https://randomly.cluxnei.dev/g/words/pseudo.md): Order-n Markov chains over real vocabulary — noise at 2, plagiarism at 4.
- [`words.syllabic`](https://randomly.cluxnei.dev/g/words/syllabic.md): Syllable grammars rather than a list lookup — elvish, nordic, latin, brand.
- [`words.brand`](https://randomly.cluxnei.dev/g/words/brand.md): Two open syllables and a plausible domain — no registrar was consulted.
- [`words.lorem`](https://randomly.cluxnei.dev/g/words/lorem.md): Sentence lengths drawn log-normally, so it reads like prose and not like a list.
- [`words.article`](https://randomly.cluxnei.dev/g/words/article.md): A Wikipedia summary you would never have gone looking for.
- [`words.species`](https://randomly.cluxnei.dev/g/words/species.md): A real species drawn from GBIF — twenty million names, one of them yours.
- [`words.related`](https://randomly.cluxnei.dev/g/words/related.md): Means-like, rhymes-with and sounds-like, via Datamuse.
- [`words.identity`](https://randomly.cluxnei.dev/g/words/identity.md): Names that hold together across a nationality.

**Equations** — Problems with clean answers, built backwards from the solution.

- [`equations.arithmetic`](https://randomly.cluxnei.dev/g/equations/arithmetic.md): Drills at a digit count and operation set you pick, and division always comes out even.
- [`equations.expression`](https://randomly.cluxnei.dev/g/equations/expression.md): A probabilistic grammar grows the expression; you get the tree it grew from too.
- [`equations.linear`](https://randomly.cluxnei.dev/g/equations/linear.md): Built root-first, so the answer is always clean and never needs checking.
- [`equations.quadratic`](https://randomly.cluxnei.dev/g/equations/quadratic.md): Integer, rational or surd roots — built from the roots, so they factor.
- [`equations.system`](https://randomly.cluxnei.dev/g/equations/system.md): 2×2 and 3×3, guaranteed to have one solution and to reach it without fractions.
- [`equations.calculus`](https://randomly.cluxnei.dev/g/equations/calculus.md): Derivatives and integrals per rule — the integrals exist because they were built backwards.
- [`equations.matrix`](https://randomly.cluxnei.dev/g/equations/matrix.md): Any, invertible, symmetric or positive-definite — constructed, not rejection-sampled.
- [`equations.identity`](https://randomly.cluxnei.dev/g/equations/identity.md): A real identity — half of them subtly broken. You guess; the verdict is checked, not assumed.
- [`equations.sequence`](https://randomly.cluxnei.dev/g/equations/sequence.md): Arithmetic, geometric, quadratic or Fibonacci-like — with enough terms to be unambiguous.

**Patterns** — Noise, growth and decay — Perlin, Gray-Scott, cellular automata.

- [`patterns.perlin`](https://randomly.cluxnei.dev/g/patterns/perlin.md): Gradient noise, stacked into fractals and folded through itself.
- [`patterns.simplex`](https://randomly.cluxnei.dev/g/patterns/simplex.md): Fewer directional artefacts, cheaper in higher dimensions.
- [`patterns.worley`](https://randomly.cluxnei.dev/g/patterns/worley.md): Distance to the nth-nearest feature point.
- [`patterns.spectral`](https://randomly.cluxnei.dev/g/patterns/spectral.md): 1/f^β synthesised in the frequency domain.
- [`patterns.automaton`](https://randomly.cluxnei.dev/g/patterns/automaton.md): All 256 rules, including the one that is a PRNG.
- [`patterns.life`](https://randomly.cluxnei.dev/g/patterns/life.md): Conway from a random soup, with a density control.
- [`patterns.reaction`](https://randomly.cluxnei.dev/g/patterns/reaction.md): Gray–Scott, run until the pattern stops moving.
- [`patterns.truchet`](https://randomly.cluxnei.dev/g/patterns/truchet.md): Random tile orientation. Instant beauty, ten lines of code.
- [`patterns.poisson`](https://randomly.cluxnei.dev/g/patterns/poisson.md): Poisson-disk beside uniform random — the difference is the lesson.
- [`patterns.voronoi`](https://randomly.cluxnei.dev/g/patterns/voronoi.md): Cells from random sites, coloured so no two neighbours match.
- [`patterns.maze`](https://randomly.cluxnei.dev/g/patterns/maze.md): DFS, Kruskal and Wilson side by side — algorithm as bias.
- [`patterns.lsystem`](https://randomly.cluxnei.dev/g/patterns/lsystem.md): Stochastic rewrite rules: plants, snowflakes, dragon curves.
- [`patterns.wfc`](https://randomly.cluxnei.dev/g/patterns/wfc.md): Overlapping model, min-entropy heuristic, backtracking.
- [`patterns.walk`](https://randomly.cluxnei.dev/g/patterns/walk.md): Brownian, self-avoiding and Lévy — the fat tail is visible.
- [`patterns.dla`](https://randomly.cluxnei.dev/g/patterns/dla.md): Dendritic crystals, grown one sticky particle at a time.

**Images** — Flow fields, superformula blobs, perceptual palettes, real art.

- [`images.flowfield`](https://randomly.cluxnei.dev/g/images/flowfield.md): Thousands of particles advected through fractal noise.
- [`images.blob`](https://randomly.cluxnei.dev/g/images/blob.md): One equation: starfish, gears, leaves, sea urchins.
- [`images.identicon`](https://randomly.cluxnei.dev/g/images/identicon.md): A deterministic avatar from a hash. Same input, same face.
- [`images.circles`](https://randomly.cluxnei.dev/g/images/circles.md): Grow until collision, keep what fits.
- [`images.mondrian`](https://randomly.cluxnei.dev/g/images/mondrian.md): Recursive subdivision, split at U(0.3, 0.7).
- [`images.gradient`](https://randomly.cluxnei.dev/g/images/gradient.md): Random control points, dithered to kill the banding.
- [`images.spray`](https://randomly.cluxnei.dev/g/images/spray.md): A Gaussian mixture with k random components.
- [`images.tiles`](https://randomly.cluxnei.dev/g/images/tiles.md): A random glyph and rotation per cell.
- [`images.strata`](https://randomly.cluxnei.dev/g/images/strata.md): Band heights from a Dirichlet draw, colours walking a palette.

**Audio** — Noise colours, Euclidean rhythms and strings plucked out of static.

- [`audio.noise`](https://randomly.cluxnei.dev/g/audio/noise.md): White, pink, brown, blue, violet — and perceptually flat grey.
- [`audio.rhythm`](https://randomly.cluxnei.dev/g/audio/rhythm.md): k onsets spread as evenly as possible across n steps — which is most of the world’s rhythms.
- [`audio.melody`](https://randomly.cluxnei.dev/g/audio/melody.md): Random walk, Markov, or the 1/f kind that sounds written — on a scale that cannot clash.
- [`audio.pluck`](https://randomly.cluxnei.dev/g/audio/pluck.md): Karplus–Strong: fill a delay line with pure noise and a guitar comes out.
- [`audio.chord`](https://randomly.cluxnei.dev/g/audio/chord.md): A functional-harmony transition matrix, not a random draw — so it sounds written.
- [`audio.drone`](https://randomly.cluxnei.dev/g/audio/drone.md): Detuned partials, beating slowly against each other.
- [`audio.bleep`](https://randomly.cluxnei.dev/g/audio/bleep.md): Success, error, notify, coin — as a downloadable pack.
- [`audio.ambient`](https://randomly.cluxnei.dev/g/audio/ambient.md): A mood preset that evolves and never repeats.

Or fetch the whole catalogue with its parameters at once:

```bash
curl -s 'https://randomly.cluxnei.dev/api/v1/generators'
```

## More

- [Everything in one file](https://randomly.cluxnei.dev/llms-full.txt) — this contract plus all 63 generators and all 10 entropy sources.
- [Index](https://randomly.cluxnei.dev/llms.txt) — the short version, per the llmstxt.org convention.
- [Source code](https://github.com/Cluxnei/randomly)
