Skip to main content
Auric Artisan · Documentation

The Harmony Library API

Date: August 29, 2026 For: Developers Category: Guide Author: Chirag Bansal
Back to Documentation API reference Open the library

Overview

The harmony library holds 8,192 colour schemes across 23 methods — and holds none of them. The collection ships as a 5 KB manifest: a seed, a batch stride, and the canonical angles each scheme is defined by. Every record is computed from that. This guide is how to drive it from your own code, end to end.

One number is worth having before you start. Only 25.4% of the collection contains a pair of members you could set text with. Colour schemes are built from hue relationships, and hue relationships say nothing about lightness; a row of swatches cannot show you that, which is why every response here carries the contrast alongside the colours.

Table of contents

  1. 1. What this API is for
  2. 2. Getting a key and making your first call
  3. 3. Derived, not stored
  4. 4. Browsing and paging
  5. 5. One harmony, whole
  6. 6. The collection’s own numbers
  7. 7. Naming a scheme you already have
  8. 8. The five schemes hue cannot separate
  9. 9. Three complete tasks
  10. 10. What each call costs
  11. 11. Errors, limits and pitfalls
  12. 12. Endpoint reference

1. What this API is for

+

POST /v1/harmony/generate makes you a scheme from a base colour. These four answer the questions on either side of that one.

  • Show me schemes that actually work as UI — /v1/harmony/library
  • Give me one whole, with the seed that reproduces it — /v1/harmony/library/{id}
  • What is in the collection, counted? — /v1/harmony/library/stats
  • What scheme is my palette? — /v1/harmony/identify

The last one is the reason the other three are worth having. A collection of 8,192 schemes is not primarily a shop; it is the reference a matcher can be checked against. The library page runs the same matcher in your browser, so the page and the API cannot disagree.

2. Getting a key and making your first call

+

Create a key in your dashboard under API keys, then send it as a bearer token.

curl -H "Authorization: Bearer $AURIC_API_KEY" \
  "https://api.auricartisan.com/v1/harmony/library?limit=3"

3. Derived, not stored

+

This is the one structural fact worth understanding before you build on it. harmonies.json is 5 KB and contains no harmonies. It holds a seed (137), a batch size (1,024), a batch seed stride, the 23 method names, how many colours each produces, which family each belongs to, and the canonical hue angles that define it.

Record n is produced by seeding an xorshift generator per batch, stepping it three times per record for a base hue, saturation and lightness, and applying the scheme at n % 23. That is the whole database.

Which is why /v1/harmony/library/{id} returns a derivation block with the seed and batch in it. A stored row is something you have to trust; a derived one is something you can check.

4. Browsing and paging

+
GET /v1/harmony/library?family=polyadic&sort=contrast&order=desc&limit=2
{
  "collection": { "total": 8192, "methods": 23, "families": 5 },
  "filter": { "family": "polyadic", "method": null, "hue": null, "colors": null },
  "sort": "contrast",
  "order": "desc",
  "matched": 2138,
  "share_of_collection": 26.1,
  "next_offset": 2,
  "harmonies": [
    {
      "id": 4395,
      "harmony_id": "har_3e3",
      "method": "triadic",
      "family": "polyadic",
      "color_count": 3,
      "colors": ["#4C09E9", "#E94C09", "#09E94C"],
      "adherence": 1,
      "min_pair_contrast": 2.18,
      "hue_spread": 240
    }
  ]
}

Because the catalogue is finite and enumerated, matched is a real total: filtering to the polyadic family tells you there are exactly 2,138 of them, 26.1% of everything. Every filter walks all 8,192 derivations rather than consulting an index — that is a few hundred milliseconds, and the alternative is a table that can drift from the generator.

Filters

  • method — one of the 23, e.g. triadic.
  • family — complementary, analogous, polyadic, monochromatic or compound.
  • hue — the base colour’s band: red through pink.
  • colors — how many members, 2–7.
  • min_contrast — the worst pair must clear this ratio. The one that matters; see the numbers in section 6.
  • min_adherence — how closely it holds its canonical angles, 0–1.
  • sort — id, contrast, spread, adherence or colors; order is asc or desc.
  • full=true — adds per-colour HSL and OKLCH, the role each plays, and the canonical angles.

Page with next_offset, which is null on the last page.

5. One harmony, whole

+
GET /v1/harmony/library/har_0
{
  "harmony": {
    "id": 0,
    "harmony_id": "har_0",
    "method": "complementary",
    "family": "complementary",
    "color_count": 2,
    "base": { "hue": 3, "saturation": 0.5126, "lightness": 0.6313, "hex": "#D17671" },
    "colors": [
      { "role": "base",       "hex": "#D17671", "rgb": [209, 118, 113], "oklch": [...] },
      { "role": "complement", "hex": "#71CCD1", "rgb": [113, 204, 209], "oklch": [...] }
    ],
    "canonical_angles": [180],
    "adherence": 1,
    "hue_spread": 180,
    "min_pair_contrast": 1.72,
    "derivation": {
      "seed": 137,
      "batch": 0,
      "batch_size": 1024,
      "batch_seed_stride": 2654435761,
      "note": "This record is derived, not stored..."
    }
  }
}

Ids come in two spellings and name the same record: har_1p is base-36 for 61, and /v1/harmony/library/61 returns the same thing.

adherence is the collection’s own measure of how closely a record holds its canonical angles, taken from its first colour. Note that a few families — the analogous ones especially — write those angles relative to their middle member, so their adherence reads below 1 by construction. If you want an anchor-independent answer, use /identify, which is built for exactly that.

6. The collection’s own numbers

+
GET /v1/harmony/library/stats
{
  "collection": { "total": 8192 },
  "mean_adherence": 0.943,
  "mean_min_contrast": 1.274,
  "mean_hue_spread": 148.96,
  "with_an_aa_pair": { "count": 2082, "share": 25.42 },
  "family": [
    { "name": "polyadic",      "count": 2138, "share": 26.10 },
    { "name": "monochromatic", "count": 2136, "share": 26.07 },
    { "name": "analogous",     "count": 1424, "share": 17.38 },
    { "name": "compound",      "count": 1424, "share": 17.38 },
    { "name": "complementary", "count": 1070, "share": 13.06 }
  ],
  "method": [ ... 23 entries ... ],
  "color_count": [ ... ]
}

The number that should change how you use this

with_an_aa_pair is 25.42%. Three quarters of these schemes contain no two members that can be set as text on each other. That is not a defect in the generator — it is what colour harmony is. Schemes are defined by hue relationships, and rotating the hue wheel does not change lightness, so a textbook triadic is three colours of near-identical luminance.

mean_min_contrast of 1.274 says the same thing from the other side: the average scheme’s worst pair is barely distinguishable at all.

So: pick by hue, then filter by min_contrast, and expect to add a light and a dark of your own. A harmony gives you a palette’s character; it does not give you a text colour.

7. Naming a scheme you already have

+
POST /v1/harmony/identify
Content-Type: application/json

{ "colors": ["#FF0000", "#00FF00", "#0000FF"] }
{
  "verdict": "a triadic — though by hue alone it is indistinguishable from triad shifted...",
  "best_match": {
    "method": "triadic",
    "family": "polyadic",
    "mean_angle_error": 0,
    "fit": 1,
    "base_color": "#FF0000",
    "canonical_angles": [120, 240]
  },
  "ties": ["triad_shifted"],
  "candidates": [ ...top five... ],
  "hue_offsets": [0, 120, 240],
  "min_pair_contrast": 2.15,
  "max_pair_contrast": 6.26,
  "carries_body_text": true
}

How the match is made

A harmony is a shape on the hue circle, and a shape has no first element — rotate it and it is the same harmony. So each colour is tried as the base in turn and the best fit wins. fit is one minus the mean angular error over 60°, because 60° is a whole scheme’s worth of wrong: at that much error a triadic reads as a square.

That rotation is not a nicety. Several schemes write their canonical angles relative to their middle member — analogous_3 is [-24, 24] — so a textbook analogous triad handed over in reading order has offsets of +24° and +48° from its first colour and matches nothing at all. Anchoring on each member fixes that, and makes the answer independent of the order you send the colours in.

8. The five schemes hue cannot separate

+

Feed all 23 schemes back through /identify and 18 come back named exactly. The other five come back as ties, and they are the same five every time:

  • shades, tints and neutral — five colours at one hue, exactly like monochromatic_5. Only lightness and saturation tell them apart.
  • warm_cool — two colours 180° apart. That is a complementary.
  • triad_shifted — a triadic’s 120° and 240°, with saturation moved.

A measurement that cannot distinguish two answers should return both, so ties lists every scheme within a hundredth of the winner’s fit and the verdict says so in words. If you need to separate them, the lightness and saturation spread across the members is what does it — full=true on a browse gives you the per-colour values.

9. Three complete tasks

+

Find a scheme you can actually build a UI from

GET /v1/harmony/library?min_contrast=4.5&colors=2&sort=contrast&order=desc&limit=12

Two members, and the worst pair among them already clears AA. That is a small slice of 8,192, which is the point of asking for it explicitly rather than picking a pretty row of swatches and discovering the problem in review.

Name the scheme your brand already uses

const res = await fetch("https://api.auricartisan.com/v1/harmony/identify", {
  method: "POST",
  headers: { "content-type": "application/json", authorization: `Bearer ${KEY}` },
  body: JSON.stringify({ colors: BRAND_PALETTE }),
});
const m = await res.json();
console.log(m.verdict);
if (m.best_match.fit < 0.65) {
  console.log("Not a textbook scheme — hue offsets:", m.hue_offsets);
}
if (!m.carries_body_text) {
  console.warn("No two members clear AA. You need a text colour from outside it.");
}

Cite a harmony in a design document

GET /v1/harmony/library/har_2la

The response carries the seed and batch, so the citation is checkable: anybody can recompute record 3,358 from seed 137 and get the same two colours. That is a different kind of reference from “here is a hex I liked”.

10. What each call costs

+
  • GET /v1/harmony/library/{id} — 1 credit. One derivation.
  • GET /v1/harmony/library — 3 credits. Derives and filters all 8,192.
  • POST /v1/harmony/identify — 3 credits. Matches against 23 schemes, anchored on each colour.
  • GET /v1/harmony/library/stats — 10 credits. Walks the whole collection and counts four dimensions.

API credits are a separate balance from tool tokens; neither pays for the other. Statistics do not change between calls — cache them.

11. Errors, limits and pitfalls

+
GET /v1/harmony/library?method=lovely

{
  "error": {
    "code": "INVALID_INPUT",
    "message": "method: must be one of complementary, split_complementary, triadic, ..."
  }
}
  • Ids run 0–8191, in either spelling. Anything else is a validation error, not a 404.
  • colors is 2–12 on identify. Fewer than two is not a harmony; more than twelve is not one either.
  • Only schemes of the same size are considered. Hand identify four colours and it will never answer “triadic”, however close three of them are.
  • Do not read a high adherence as “this is a good scheme”. It measures conformity to canonical angles, nothing else — a perfectly adherent triadic can still be three colours you cannot tell apart in greyscale.
  • Mind the rate limit when looping. Fetch a page of records rather than an id at a time.

12. Endpoint reference

+
EndpointMethodCreditsAnswers
/v1/harmony/libraryGET3Which schemes match this filter, and how much of the collection is that?
/v1/harmony/library/{id}GET1One harmony, with its roles, angles and the seed that reproduces it.
/v1/harmony/library/statsGET10What is in the collection, counted rather than asserted.
/v1/harmony/identifyPOST3Which of the 23 schemes do these colours form, and how closely?

The machine-readable form is in the API reference, generated from the same catalogue the server routes from, so it cannot drift from the implementation.

To see all of this working without writing any code, open the harmony library — the browse grid and the “what harmony is this?” panel are the same matcher this API exposes.