Skip to main content
Auric Artisan · Documentation

REST API Reference

Published July 8, 2026 - Updated August 12, 2026

Back to Documentation Manage API Keys

Overview

The Auric Artisan REST API exposes the full color-science toolkit — conversions, palettes, harmonies, gradients, shade scales, WCAG/APCA accessibility checks, color-vision-deficiency simulation and Ishihara plates — as JSON-over-HTTPS endpoints under /v1. Base URL https://api.auricartisan.com. Authenticate with an API key created in your account dashboard.

The URL Analyzer has its own three endpoints and enough behaviour worth explaining — scopes, what a browserless audit can and cannot answer, and why it returns no overall score — that they have a guide of their own: Analyzer API.

Table of contents

  1. 1. Quick start
  2. 2. Authentication
  3. 3. Rate limits, credits and quotas
  4. 4. Endpoint reference
  5. Analyzer API — a guide
  6. 5. Request examples
  7. 6. Errors
  8. 7. SDKs and tooling
  9. 8. Local development
  10. 9. Plans and pricing

1. Quick start

+
  1. Create an API key. Go to Dashboard → API Keys and create a key. The full key is shown once — copy it somewhere safe. You can hold up to 10 active keys and revoke any of them instantly.
  2. Send it with every request in the x-api-key header. Requests without a valid key receive 401 Unauthorized.
  3. Call any endpoint. Tool endpoints accept JSON via POST and reply in JSON. GET /v1 lists everything the API can do.
# Convert a color to OKLCH
curl -X POST https://api.auricartisan.com/v1/color/convert \
  -H "x-api-key: aa_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"color": "#d3af37", "to": "oklch"}'

# → {"input":{"rgb":[211,175,55],"hex":"#d3af37"},"to":"oklch",
#    "value":[0.7655,0.1384,91.55]}

2. Authentication

+

Every metered endpoint requires one of the following credentials.

Method How Best for
API key (recommended) x-api-key: aa_… header, or ?key=aa_… query parameter Servers, scripts, CI — create in the dashboard
OAuth bearer Authorization: Bearer <token> from the CLI device flow The auric CLI and interactive tools

Keys are secret. The full key is displayed once at creation and stored only as a SHA-256 hash — nobody (including us) can recover it later. If a key leaks, revoke it in the dashboard; revocation takes effect within a minute. Successful requests refresh the key's last used timestamp (at most once a minute), which you can audit in the dashboard.

3. Rate limits, credits and quotas

+

Limits follow your account plan. Rate limit, monthly credits and credit balance are pooled per account, not per key — ten keys share one allowance, so splitting traffic across keys buys you nothing.

Credits

The monthly quota is denominated in credits, not calls. One credit is one standard request; endpoints that cost more CPU cost more credits, so a caller doing simple colour maths does not subsidise one rendering PNGs. The cost of a call is returned in the x-credits-cost header of every response.

Credits Endpoints
1 Standard work — /v1/color/convert, /v1/color/contrast, /v1/science/convert, /v1/accessibility/check, /v1/vision/simulate, and any endpoint without a weight of its own
2–4 Generators and multi-step maths — /v1/palette/generate, /v1/harmony/generate, /v1/gradient/generate, /v1/shade/scale, /v1/science/delta-e, /v1/science/temperature, /v1/tokens/generate, /v1/graphql
5 /v1/science/dossier (all 63 colour spaces plus a locus search) and /v1/usage/stream (charged once when the stream opens; events are free)
10–12 Rendered pixels — /v1/palette/png, /v1/gradient/png, /v1/ishihara/png, /v1/vision/simulate-image, /v1/palette/from-image, /v1/accessibility/from-image
25 Async jobs — POST /v1/jobs/{type}. Polling one with GET /v1/jobs/id/{id} costs 1

The table is not exhaustive: the library, corpus, analyzer and personalization endpoints, among others, carry weights of their own, from 1 credit for a single library record to 25 for /v1/accessibility/corpus/stats, and x-credits-cost reports the exact figure on every call. A new endpoint nobody has weighted yet bills as standard work (1 credit) — never free by accident. GET /v1/tiers returns the machine-readable version of the table below, so a client can read its own terms rather than hard-coding them.

What each plan includes

Plan API tier Requests / min Credits / month Hard ceiling Max keys
Apprentice (free) Free — Not included — —
Artisan Free — Not included — —
Specialist Pro 300 1,000,000 10,000,000 10
Industrial Pro Enterprise 3,000 10,000,000 100,000,000 10
Industrial Pro was sold as “Unlimited” before 12 August 2026. Subscriptions created before that date keep that allowance — they are metered at 1,000,000,000 credits a month, a hundred times the new included figure, which at 3,000 requests a minute cannot be reached inside a month with standard 1-credit calls. The finite allowance in the table applies to subscriptions started on or after 12 August 2026.

Past the allowance: overage, spend caps, ceilings

By default, running out of credits stops the traffic: further calls return 429 QUOTA_EXCEEDED until the monthly reset. Nothing is charged.

Pay-as-you-go overage is opt-in, off until you enable it in Dashboard → API Keys, and strictly prepaid — it spends a credit balance bought in advance, at $1.00 (₹85) per 100,000 credits. If the balance will not cover a call, the call is refused with 402 INSUFFICIENT_CREDITS; it is never served on account. No usage produces an invoice after the fact.

  • Spend cap. Set a monthly ceiling in money (up to $10,000). Overage stops there with 402 SPEND_CAP_REACHED — raise it in the dashboard to continue.
  • Hard ceiling. Independent of everything you configure, no account may spend more than ten times its included allowance in one month. Hitting it returns 429 HARD_CEILING_REACHED. It is a safety stop against runaway retries and leaked keys, not a sales lever; support can raise it per key.

Reading the meter

Every response carries your live consumption, so clients can self-throttle:

x-ratelimit-limit: 300            # requests allowed per minute
x-ratelimit-remaining: 297
x-ratelimit-reset: 1783502302     # unix seconds
x-quota-limit: 1000000            # included credits this month
x-quota-used: 412
x-quota-remaining: 999588
x-quota-reset: 1785091200         # unix seconds
x-credits-cost: 10                # what this call consumed

# only present once a call is paid for out of the prepaid balance:
x-credits-overage: 10
x-overage-cost-usd: 0.00          # 1.00 only when this call opens a new
                                  # 100,000-credit block; 0.00 inside one
x-credits-ceiling: 10000000

Check your usage anytime with GET /v1/usage/me, or full analytics with GET /v1/usage. A quota.threshold webhook fires when you cross 80% of the included allowance, so you can find out before your callers do.

4. Endpoint reference

+

Everything lives under /v1. The interactive reference (GET /v1/docs) and the OpenAPI spec (GET /v1/openapi.yaml) are served by the API itself.

Every endpoint the service exposes — 103 of them — generated from the API's own catalogue, which the test suite refuses to let drift from the router. Auth shows the credential required; None means the endpoint is public and unmetered.

MethodPathAuthSummary
GET/v1NoneIndex of every endpoint, with the current version.
GET/v1/healthNoneLiveness probe. Always cheap, never touches storage.
GET/v1/readyNoneReadiness probe — reports whether each backing store is bound.
GET/v1/methods/:toolx-api-keyThe algorithms a given tool supports.
GET/v1/formatsNoneEvery export format, across every exportable resource.
GET/v1/tiersNoneRate limit and monthly quota for each tier.
GET/v1/metricsNonePrometheus exposition of process-level counters.
GET/v1/statusNoneHuman-readable status page.
GET/v1/catalogNoneThis catalogue as JSON — every endpoint with its parameters and examples.
GET/v1/docsNoneInteractive reference (Redoc).
GET/v1/openapi.yamlNoneThe OpenAPI 3.0.3 document.
GET/v1/graphqlNoneGraphQL playground.
POST/v1/graphqlx-api-keyRun a GraphQL query against the same resolvers as the REST surface.
POST/v1/color/convertx-api-keyConvert one colour between the common spaces.
GET/v1/color/atlasx-api-keyBrowse the 8,192-colour atlas under a filter.
GET/v1/color/atlas/statsx-api-keyWhat the atlas actually contains.
GET/v1/color/atlas/:idx-api-keyResolve one sample, whole.
POST/v1/color/nearestx-api-keyThe catalogued colours closest to one you already have.
POST/v1/color/contrastx-api-keyWCAG contrast ratio between two colours, with pass/fail at each level.
GET/v1/science/spacesx-api-keyEvery colour space the platform knows, with provenance.
GET/v1/science/spaces/:keyx-api-keyOne colour space in full, including its conversion matrices.
POST/v1/science/convertx-api-keyConvert a colour into any registry space, or several at once.
POST/v1/science/dossierx-api-keyOne colour rendered in every space at once, plus its colour temperature.
POST/v1/science/delta-ex-api-keyPerceptual difference between two colours.
POST/v1/science/temperaturex-api-keyCorrelated colour temperature from a colour, or the colour of a temperature.
GET/v1/science/illuminantsx-api-keyStandard reference illuminants with their chromaticities.
GET/v1/science/metricsx-api-keyThe difference formulae, their options, and when to use each.
POST/v1/palette/generatex-api-keyGenerate a palette from a seed colour.
POST/v1/palette/evaluatex-api-keyScore a palette for harmony, contrast and accessibility.
POST/v1/palette/exportx-api-keyRender a palette into a design-tool format (ASE, GPL, ACO, …).
POST/v1/palette/from-imagex-api-keyExtract a palette from an uploaded image.
POST/v1/palette/pngx-api-keyGenerate a palette and render it as a PNG swatch strip.
POST/v1/harmony/generatex-api-keyBuild a harmony set (complementary, triadic, analogous, …) from a base colour.
POST/v1/harmony/classifyx-api-keyIdentify which harmony an existing set of colours follows.
POST/v1/harmony/exportx-api-keyExport a harmony set.
POST/v1/gradient/generatex-api-keyInterpolate a gradient between colours, in a chosen space.
GET/v1/shade/libraryx-api-keyBrowse 8,192 measured shade scales under a filter.
GET/v1/shade/library/statsx-api-keyWhat the collection contains, counted rather than asserted.
GET/v1/shade/library/:idx-api-keyOne scale, whole, with every measurement.
POST/v1/shade/evaluatex-api-keyMeasure a scale you already have: does it work as a token ramp?
GET/v1/palette/libraryx-api-keyBrowse five million generated palettes under a filter.
GET/v1/palette/library/statsx-api-keyWhat the collection looks like, measured on a stated sample.
GET/v1/palette/library/:idx-api-keyOne palette, whole, with the derivation that reproduces it.
GET/v1/harmony/libraryx-api-keyBrowse the 8,192-harmony collection under a filter.
GET/v1/harmony/library/statsx-api-keyWhat the collection contains, counted rather than asserted.
GET/v1/harmony/library/:idx-api-keyOne harmony, whole, with the derivation that reproduces it.
POST/v1/harmony/identifyx-api-keyName the scheme the colours you already have form.
GET/v1/gradient/libraryx-api-keyBrowse the 8,192-gradient collection under a filter.
GET/v1/gradient/library/statsx-api-keyWhat the collection contains, counted rather than asserted.
GET/v1/gradient/library/:idx-api-keyOne gradient, whole.
POST/v1/gradient/analysex-api-keyMeasure a gradient you already have: will it band, and where?
POST/v1/gradient/exportx-api-keyExport a gradient as CSS, SVG or JSON.
POST/v1/gradient/pngx-api-keyRender a gradient as a PNG.
POST/v1/shade/scalex-api-keyBuild a tint/shade scale from one colour.
POST/v1/shade/exportx-api-keyExport a shade scale.
POST/v1/tokens/generatex-api-keyTurn one seed colour into a complete, contrast-checked token system.
GET/v1/personalize/vocabularyx-api-keyEverything a brief may name, with the ranges the engine really imposes.
GET/v1/personalize/presetsx-api-keyThe 17 briefs the tool ships, in request shape.
POST/v1/personalize/poolx-api-keyGrow a working set of colours from seeds and a brief.
POST/v1/personalize/scorex-api-keyRank a palette you already have, on the search’s own six scores.
POST/v1/personalize/palettesx-api-keySearch: N candidates in, the best K out, each with its breakdown.
POST/v1/personalize/systemx-api-keyOne brief in, an entire design system out.
POST/v1/tokens/exportx-api-keyRender a token deck for a specific platform.
GET/v1/tokens/formatsx-api-keyThe ten token export targets.
POST/v1/accessibility/checkx-api-keyCheck a foreground/background pair against WCAG 2.2 and APCA.
POST/v1/accessibility/recommendx-api-keySuggest the nearest accessible alternative to a failing pair.
POST/v1/accessibility/from-imagex-api-keyAudit the colour contrast present in an image.
GET/v1/accessibility/corpusx-api-keyBrowse the five-million-pair corpus under a filter, with a cursor.
GET/v1/accessibility/corpus/statsx-api-keyThe measured distribution of contrast across the corpus.
GET/v1/accessibility/corpus/:record_idx-api-keyResolve one record by id or index.
GET/v1/analyzer/stagesx-api-keyWhat the analyzer can be asked for, and how much of it a markup-only run can answer.
POST/v1/analyzer/inspectx-api-keyAudit one page from its markup. No browser, no rendering.
POST/v1/analyzer/renderx-api-keyTurn a report into a document.
POST/v1/accessibility/mapx-api-keyThe whole territory of foreground colour a background leaves you.
POST/v1/accessibility/picksx-api-keyA ready set of foregrounds that clear a target on one background.
POST/v1/accessibility/auditx-api-keyAudit a palette against one background, with a fix for each failure.
GET/v1/vision/modelsx-api-keyThe colour-vision deficiency models available.
POST/v1/vision/simulatex-api-keySimulate how a colour appears under a vision deficiency.
GET/v1/vision/conditionsx-api-keyEvery documented vision condition, and what can simulate it.
GET/v1/vision/conditions/:slugx-api-keyOne condition, with its severity, prevalence and a worked example.
GET/v1/vision/matricesx-api-keyThe CVD matrices, for applying the transform yourself.
POST/v1/vision/palettex-api-keyRun a whole palette through many conditions in one call.
POST/v1/vision/auditx-api-keyFind which pairs in a palette stop being distinguishable.
POST/v1/vision/simulate-imagex-api-keySimulate a vision deficiency on the dominant colours of an image.
POST/v1/ishihara/platex-api-keyGenerate an Ishihara test plate as structured data.
POST/v1/ishihara/pngx-api-keyRender an Ishihara plate as a PNG.
GET/v1/usagex-api-keyDurable per-day, per-endpoint history for your key.
GET/v1/usage/mex-api-keyYour tier, limits and month-to-date quota consumption.
GET/v1/usage/livex-api-keyThe last 100 individual calls, with rolling latency and error stats.
GET/v1/usage/streamx-api-keyThe same live feed, pushed over Server-Sent Events.
GET/v1/jobsx-api-keyThe async job types this deployment can run.
POST/v1/jobs/:typex-api-keyQueue a long-running job and get an id back immediately.
GET/v1/jobs/id/:idx-api-keyPoll one job.
GET/v1/jobs/id/:id/streamx-api-keyFollow a job to completion over SSE instead of polling.
GET/v1/webhooks/eventsNoneEvent types you can subscribe to.
GET/v1/webhooksx-api-keyList your webhook subscriptions.
POST/v1/webhooksx-api-keySubscribe a URL to one or more events.
GET/v1/webhooks/:idx-api-keyFetch one subscription.
DELETE/v1/webhooks/:idx-api-keyRevoke a subscription.
GET/v1/admin/keysx-admin-keyList issued API keys.
POST/v1/admin/keysx-admin-keyIssue a key. The secret is shown once and stored only as a hash.
GET/v1/admin/keys/:idx-admin-keyFetch one key record (never the secret).
DELETE/v1/admin/keys/:idx-admin-keyRevoke a key immediately.

Discovery

GET /v1 No key

Index of every endpoint, with the current version.

Returns version string, endpoints string[]

Example

curl "https://api.auricartisan.com/v1"

GET /v1/health No key

Liveness probe. Always cheap, never touches storage.

Returns ok boolean, time ISO-8601

Example

curl "https://api.auricartisan.com/v1/health"

GET /v1/ready No key

Readiness probe — reports whether each backing store is bound.

Use this in a deploy gate. /v1/health says the process is up; this says it can actually serve.

Returns ready boolean, checks object

Example

curl "https://api.auricartisan.com/v1/ready"

GET /v1/methods/:tool

The algorithms a given tool supports.

Parameters

NameTypeRequiredDescription
toolpathYese.g. palette, harmony, vision.

Example

curl "https://api.auricartisan.com/v1/methods/harmony" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/formats No key

Every export format, across every exportable resource.

Example

curl "https://api.auricartisan.com/v1/formats"

GET /v1/tiers No key

Rate limit and monthly quota for each tier.

Example

curl "https://api.auricartisan.com/v1/tiers"

GET /v1/metrics No key

Prometheus exposition of process-level counters.

Example

curl "https://api.auricartisan.com/v1/metrics"

GET /v1/status No key

Human-readable status page.

Example

curl "https://api.auricartisan.com/v1/status"

GET /v1/catalog No key

This catalogue as JSON — every endpoint with its parameters and examples.

Machine-readable and generated from the same source as the OpenAPI spec, so a client can build its own reference or validate coverage.

Example

curl "https://api.auricartisan.com/v1/catalog"

GET /v1/docs No key

Interactive reference (Redoc).

Example

curl "https://api.auricartisan.com/v1/docs"

GET /v1/openapi.yaml No key

The OpenAPI 3.0.3 document.

Example

curl "https://api.auricartisan.com/v1/openapi.yaml"

Colour

POST /v1/color/convert

Convert one colour between the common spaces.

For the full 63-space registry with white-point control, use /v1/science/convert.

Request body

NameTypeRequiredDescription
colorcolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
tostringNoA single target space. Omit to get every common space at once.

Example

curl -X POST "https://api.auricartisan.com/v1/color/convert" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"color":"#c9a227","to":"lab"}'

POST /v1/color/contrast

WCAG contrast ratio between two colours, with pass/fail at each level.

wcag carries aa_normal, aa_large, aaa_normal and aaa_large; delta_e is { method, value } for the formula deltaE picks.

Request body

NameTypeRequiredDescription
fgcolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
bgcolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
deltaEnumberNoDifference formula: 76, 94, 2000 (default).

Returns fg object, bg object, contrast_ratio number, delta_e object, wcag object

Example

curl -X POST "https://api.auricartisan.com/v1/color/contrast" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"fg":"#767676","bg":"#ffffff"}'

Colour science

GET /v1/science/spaces

Every colour space the platform knows, with provenance.

Sixty-three spaces across RGB working spaces, CIE spaces, perceptual and appearance models, HDR containers, print and video. Ask for full=true to get primaries, transfer curves and the XYZ matrices.

Parameters

NameTypeRequiredDescription
categoryqueryNoFilter: rgb, cie, perceptual, cylindrical, appearance, hdr, print, video, order, opponent.
fullqueryNotrue to include matrices, primaries and transfer functions.

Example

curl "https://api.auricartisan.com/v1/science/spaces?category=perceptual" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/science/spaces/:key

One colour space in full, including its conversion matrices.

Parameters

NameTypeRequiredDescription
keypathYese.g. oklch, display-p3, acescct.

Errors UNKNOWN_SPACE (404) — No space with that key. The response suggests near matches.

Example

curl "https://api.auricartisan.com/v1/science/spaces/oklch" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/science/convert

Convert a colour into any registry space, or several at once.

Request body

NameTypeRequiredDescription
colorcolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
tostring | string[]YesOne space key, or an array of them.
white_pointstringNoReference white, default D65.

Example

curl -X POST "https://api.auricartisan.com/v1/science/convert" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"color":"#c9a227","to":["lab","oklch","display-p3"]}'

POST /v1/science/dossier

One colour rendered in every space at once, plus its colour temperature.

The full lab readout. Expensive relative to convert — reach for it when you want everything, not when you want three spaces.

Request body

NameTypeRequiredDescription
colorcolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
white_pointstringNoReference white, default D65.
categorystringNoRestrict to one category.

Example

curl -X POST "https://api.auricartisan.com/v1/science/dossier" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"color":"#c9a227"}'

POST /v1/science/delta-e

Perceptual difference between two colours.

Returns CIE76, CIE94, CIEDE2000 and CMC together, with a plain-language band. CIEDE2000 is the headline figure and is verified against the Sharma reference set.

Request body

NameTypeRequiredDescription
fromcolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
tocolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
metricstringNociede2000 (default headline), cie94, cie76, cmc, or all.
applicationstringNoCIE94 only: graphic (default) or textile.
lnumberNoCMC lightness weight, default 2.
cnumberNoCMC chroma weight, default 1.

Returns delta_e number, band string, metrics object

Example

curl -X POST "https://api.auricartisan.com/v1/science/delta-e" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"from":"#c9a227","to":"#d3af37"}'

POST /v1/science/temperature

Correlated colour temperature from a colour, or the colour of a temperature.

Send color to measure, or kelvin to render. Always returns Duv alongside the CCT — beyond about ±0.05 the colour is too far from the Planckian locus for a temperature to describe it, and meaningful says so.

Request body

NameTypeRequiredDescription
colorcolorNoMeasure this colour. Mutually exclusive with kelvin.
kelvinnumberNoRender this temperature, 1667–25000 K.

Returns cct_kelvin number, duv number, meaningful boolean, tint string

Example

curl -X POST "https://api.auricartisan.com/v1/science/temperature" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"color":"#fff5e1"}'

GET /v1/science/illuminants

Standard reference illuminants with their chromaticities.

Example

curl "https://api.auricartisan.com/v1/science/illuminants" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/science/metrics

The difference formulae, their options, and when to use each.

Example

curl "https://api.auricartisan.com/v1/science/metrics" \
  -H "x-api-key: $AURIC_API_KEY"

Palettes

POST /v1/palette/generate

Generate a palette from a seed colour.

Request body

NameTypeRequiredDescription
methodstringNoSee /v1/methods/palette. Default triadic.
huenumberNoBase hue, 0-360. Random when omitted.
saturationnumberNo0-1. Default 0.7.
lightnessnumberNo0-1. Default 0.55.
countintegerNoHow many colours, 1-64. Default 5.
seedintegerNoInteger seed, for a repeatable palette.

Example

curl -X POST "https://api.auricartisan.com/v1/palette/generate" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"method":"triadic","hue":45,"saturation":0.7,"lightness":0.55,"count":5}'

POST /v1/palette/evaluate

Score a palette for harmony, contrast and accessibility.

Request body

NameTypeRequiredDescription
paletteobjectYesThe palette to score, as { colors: [{ rgb: [r,g,b] }, ...] } — the shape POST /v1/palette/generate returns, so its output can be fed straight back in.

Example

curl -X POST "https://api.auricartisan.com/v1/palette/evaluate" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"palette":{"colors":[{"rgb":[201,162,39]},{"rgb":[29,42,62]},{"rgb":[255,252,247]}]}}'

POST /v1/palette/export

Render a palette into a design-tool format (ASE, GPL, ACO, …).

Request body

NameTypeRequiredDescription
formatstringYeshex, json, css, scss, tailwind, ase-json or svg. See /v1/formats.
dataobjectYesThe palette, as { colors: [{ rgb: [r,g,b] }, ...] }.
optionsobjectNoFormat-specific options.

Example

curl -X POST "https://api.auricartisan.com/v1/palette/export" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"format":"css","data":{"colors":[{"rgb":[201,162,39]},{"rgb":[29,42,62]}]}}'

POST /v1/palette/from-image

Extract a palette from an uploaded image.

Request body

NameTypeRequiredDescription
imagestringYesA base64 PNG. A data:image/png;base64, prefix is accepted; other image types are not.
countintegerNoColours to extract, 1-32. Default 5.
maxPixelsintegerNoLargest image accepted, 1,000-10,000,000 pixels. Default 1,500,000.

Example

curl -X POST "https://api.auricartisan.com/v1/palette/from-image" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"image":"iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAIAAAB7QOjdAAAAD0lEQVR42mM4uUhdVssOAAlsAhhwGF0kAAAAAElFTkSuQmCC","count":2}'

POST /v1/palette/png

Generate a palette and render it as a PNG swatch strip.

Takes the generator's fields, as POST /v1/palette/generate does, rather than a list of colours.

Request body

NameTypeRequiredDescription
methodstringNoSee /v1/methods/palette. Default triadic.
huenumberNoBase hue, 0-360. Random when omitted.
saturationnumberNo0-1. Default 0.7.
lightnessnumberNo0-1. Default 0.55.
countintegerNoHow many colours. Default 5.
seedintegerNoInteger seed, for a repeatable palette.
widthintegerNoImage width in px. Default 800.
heightintegerNoImage height in px. Default 120.

Returns image/png

Example

curl -X POST "https://api.auricartisan.com/v1/palette/png" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"method":"triadic","hue":45,"count":5}'

Harmony

POST /v1/harmony/generate

Build a harmony set (complementary, triadic, analogous, …) from a base colour.

Request body

NameTypeRequiredDescription
methodstringYesSee /v1/methods/harmony.
huenumberYesBase hue, 0-360.
saturationnumberYes0-1.
lightnessnumberYes0-1.

Example

curl -X POST "https://api.auricartisan.com/v1/harmony/generate" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"method":"triadic","hue":45,"saturation":0.7,"lightness":0.55}'

POST /v1/harmony/classify

Identify which harmony an existing set of colours follows.

Request body

NameTypeRequiredDescription
colorscolor[]YesThe colours to classify, two or more.

Example

curl -X POST "https://api.auricartisan.com/v1/harmony/classify" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"colors":["#FF0000","#00FF00","#0000FF"]}'

POST /v1/harmony/export

Export a harmony set.

Returns the file itself; add ?envelope=json to get it wrapped in JSON.

Request body

NameTypeRequiredDescription
formatstringYeshex, css, scss, tailwind, json, ase, svg or csv.
dataobjectYesThe harmony POST /v1/harmony/generate returns: a harmony_id and colors of { hex, role }.
optionsobjectNoFormat-specific options (svg).

Example

curl -X POST "https://api.auricartisan.com/v1/harmony/export" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"format":"css","data":{"harmony_id":"brand","colors":[{"hex":"#c9a227","role":"base"},{"hex":"#1d2a3e","role":"complement"}]}}'

Gradients

POST /v1/gradient/generate

Interpolate a gradient between colours, in a chosen space.

Request body

NameTypeRequiredDescription
colorscolor[]NoTwo or more colours, spaced evenly. Omit for a generated gradient.
stepsintegerNoSamples to return, 2-1024.
interpolationstringNoInterpolation space, default oklch-short — oklab avoids the grey dip that srgb produces. See /v1/methods/gradient.
easingstringNoEasing curve. See /v1/methods/gradient.
methodstringNoGenerator method, used when colors is omitted.
complexitystringNosimple, detailed or extreme, used when colors is omitted.

Example

curl -X POST "https://api.auricartisan.com/v1/gradient/generate" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"colors":["#c9a227","#1d2a3e"],"steps":7,"interpolation":"oklab"}'

POST /v1/gradient/export

Export a gradient as CSS, SVG or JSON.

Returns the file itself; add ?envelope=json to get it wrapped in JSON.

Request body

NameTypeRequiredDescription
formatstringYescss, json or svg.
dataobjectYesThe gradient object POST /v1/gradient/generate returns, or at least { colors: [{ hex, position }] } with position 0-1.
optionsobjectNoFormat-specific options.

Example

curl -X POST "https://api.auricartisan.com/v1/gradient/export" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"format":"css","data":{"colors":[{"hex":"#c9a227","position":0},{"hex":"#1d2a3e","position":1}]}}'

POST /v1/gradient/png

Render a gradient as a PNG.

Request body

NameTypeRequiredDescription
stopscolor[]YesThe gradient stops, as ["#rrggbb", ...].
widthintegerNoImage width in px. Default 1024.
heightintegerNoImage height in px. Default 96.

Returns image/png

Example

curl -X POST "https://api.auricartisan.com/v1/gradient/png" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"stops":["#c9a227","#1d2a3e"]}'

Shades

POST /v1/shade/scale

Build a tint/shade scale from one colour.

Request body

NameTypeRequiredDescription
colorcolorNoThe base colour. A colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}. base is accepted too. Omit for one picked from seed.
huenumberNoBase hue, 0-360, for a generated base colour. Ignored when color is sent.
stepsintegerNoSteps in the scale, 2-64. Default 11.
methodstringNoSee /v1/methods/shade. Omit for one picked from seed.
seedintegerNoInteger seed, for a repeatable scale.

Example

curl -X POST "https://api.auricartisan.com/v1/shade/scale" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"color":"#c9a227","steps":9}'

POST /v1/shade/export

Export a shade scale.

Returns the file itself; add ?envelope=json to get it wrapped in JSON.

Request body

NameTypeRequiredDescription
formatstringYescss, scss, tailwind or svg.
dataobjectYesThe scale POST /v1/shade/scale returns: steps of { hex, token }.
optionsobjectNoFormat-specific options.

Example

curl -X POST "https://api.auricartisan.com/v1/shade/export" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"format":"css","data":{"steps":[{"hex":"#c9a227","token":"500"}]}}'

Design tokens

POST /v1/tokens/generate

Turn one seed colour into a complete, contrast-checked token system.

Ramps are stepped in OKLCH so every hue is perceptually even, chroma follows a gamut-aware envelope so the light and dark ends stay distinct, and the foreground roles are measured rather than assumed — --color-on-primary is whichever of white or ink actually clears 4.5:1.

Request body

NameTypeRequiredDescription
seedcolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
namestringNoSystem name used in file headers.
harmonystringNoanalogous (default), complementary, triadic, mono.
includestring[]NoAny of color, space, radius, type. Defaults to all.
darkbooleanNoInclude dark-mode roles. Default true.

Returns meta object, contrast array, out_of_gamut string[], tokens array

Example

curl -X POST "https://api.auricartisan.com/v1/tokens/generate" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"seed":"#c9a227","name":"Auric","harmony":"analogous"}'

POST /v1/tokens/export

Render a token deck for a specific platform.

Ten targets, from CSS custom properties to Jetpack Compose. Pass raw: true to get the file itself rather than a JSON envelope.

Request body

NameTypeRequiredDescription
tokensarrayYesObjects of { name, value, group? } — the tokens array from generate, or your own.
formatstringYesSee /v1/tokens/formats.
namestringNoSystem name for the file header.
rawbooleanNotrue returns the file with a download disposition.

Example

curl -X POST "https://api.auricartisan.com/v1/tokens/export" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"format":"css","tokens":[{"name":"--color-primary","value":"#c9a227"}]}'

GET /v1/tokens/formats

The ten token export targets.

Example

curl "https://api.auricartisan.com/v1/tokens/formats" \
  -H "x-api-key: $AURIC_API_KEY"

Accessibility

POST /v1/accessibility/check

Check a foreground/background pair against WCAG 2.2 and APCA.

Request body

NameTypeRequiredDescription
fgcolorYesText colour. foreground is accepted too.
bgcolorYesSurface behind the text. background is accepted too.
standardstringNoWCAG 2.1, WCAG 2.2, WCAG 3.0, Auric SD Flexible, Auric SD Strict, or all (default).

Example

curl -X POST "https://api.auricartisan.com/v1/accessibility/check" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"fg":"#767676","bg":"#ffffff"}'

POST /v1/accessibility/recommend

Suggest the nearest accessible alternative to a failing pair.

Keeps hue, moves lightness — so the fix still looks like the brand. target chooses which half of the pair is allowed to move, not the level: set the level with minRatio.

Request body

NameTypeRequiredDescription
fgcolorYesText colour. foreground is accepted too.
bgcolorYesSurface it sits on. background is accepted too.
targetstringNoWhich side to move: foreground (default) or background.
minRationumberNoContrast ratio to reach. Default 4.5.

Example

curl -X POST "https://api.auricartisan.com/v1/accessibility/recommend" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"fg":"#c9a227","bg":"#ffffff","target":"foreground","minRatio":4.5}'

POST /v1/accessibility/from-image

Audit the colour contrast present in an image.

Request body

NameTypeRequiredDescription
imagestringYesA base64 PNG. A data:image/png;base64, prefix is accepted; other image types are not.
maxPixelsintegerNoLargest image accepted, 1,000-10,000,000 pixels. Default 1,500,000.

Example

curl -X POST "https://api.auricartisan.com/v1/accessibility/from-image" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"image":"iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAIAAAB7QOjdAAAAD0lEQVR42mM4uUhdVssOAAlsAhhwGF0kAAAAAElFTkSuQmCC"}'

Analyzer

GET /v1/analyzer/stages

What the analyzer can be asked for, and how much of it a markup-only run can answer.

The vocabulary, generated from the tool's own stage table so the two cannot drift. Each stage carries markup, which is the honest boundary: full is answered completely from the page source, partial is answered more narrowly and says so in incomplete[], and none needs a rendered page and is refused rather than returned empty. Contrast and the accessibility engine are none — without layout and computed styles they would be confidently wrong, which is the one failure an accessibility product cannot ship.

Returns checks_per_token number, always_on string[], stage_ids string[], stages object[], sections object[], notes string[]

Example

curl "https://api.auricartisan.com/v1/analyzer/stages" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/analyzer/inspect

Audit one page from its markup. No browser, no rendering.

Fetches the URL and runs the checks a page SOURCE can answer: structure, the project model, SEO and metadata, response-header security, the sitemap, responsive signals. scope names the stages you want — ask for one and you get one; dependencies are added for you and echoed back under scope.added_by_dependency. There is deliberately no overall score: several categories are never measured here, and scoring a subset as though it were the whole is how a metadata-only run once reported 92 from six checks that never ran. unscored_categories names what was left out and category_scores carries only what was measured. A stage needing a render is refused with RENDER_REQUIRED; palette and media are answered narrowly and say so in incomplete[].

Request body

NameTypeRequiredDescription
urlstringYesAn absolute http(s) URL. Private and reserved addresses are refused.
scopestring[]NoStage ids from GET /v1/analyzer/stages. Omit for everything markup can answer. An empty array is refused rather than treated as everything.
sectionsstring[]NoNarrows the response only. core is always included, and this does not make a run cheaper.

Returns url string, final_url string, scope object, score null, unscored_categories string[], category_scores object, section_index object[], sections object, incomplete object[]

Example

curl -X POST "https://api.auricartisan.com/v1/analyzer/inspect" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"url":"https://example.com","scope":["seo","security"]}'

POST /v1/analyzer/render

Turn a report into a document.

Takes a report — the one /v1/analyzer/inspect returned, or one you stored — and renders it. html is a self-contained document; pdf is laid out server-side from text and rules only, so non-Latin content will not appear in it. Markdown is not offered: the developer and client reports are built by a browser module that resolves page elements as it loads, so it cannot run here. The tool still writes both from a saved report without rescanning.

Request body

NameTypeRequiredDescription
reportobjectYesAn analyzer report object.
formatstringNohtml or pdf. Default html.

Returns text/html | application/pdf

Example

curl -X POST "https://api.auricartisan.com/v1/analyzer/render" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"report":{"url":"https://example.com/"},"format":"html"}'

Vision

GET /v1/vision/models

The colour-vision deficiency models available.

Example

curl "https://api.auricartisan.com/v1/vision/models" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/vision/simulate

Simulate how a colour appears under a vision deficiency.

Request body

NameTypeRequiredDescription
colorcolorYesA colour as #rrggbb, #rgb, rgb(r,g,b), [r,g,b], or {r,g,b}.
modelstringYesAn engine model id such as brettel-deutan — see GET /v1/vision/models. A condition slug like deuteranopia is refused here; the error names the model it maps to, or use POST /v1/vision/palette.
severitynumberNo0–1, for anomalous trichromacy.

Example

curl -X POST "https://api.auricartisan.com/v1/vision/simulate" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"color":"#c9a227","model":"brettel-deutan","severity":1}'

GET /v1/vision/conditions

Every documented vision condition, and what can simulate it.

Parameters

NameTypeRequiredDescription
kindqueryNocolor or spatial.
categoryqueryNoOne of the eleven category slugs.
complexityqueryNobasic or advanced.

Example

curl "https://api.auricartisan.com/v1/vision/conditions?kind=color" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/vision/conditions/:slug

One condition, with its severity, prevalence and a worked example.

Parameters

NameTypeRequiredDescription
slugpathYesA condition slug such as deuteranopia or glaucoma.

Errors UNKNOWN_CONDITION (404) — The slug names no condition in the catalogue.

Example

curl "https://api.auricartisan.com/v1/vision/conditions/deuteranopia" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/vision/matrices

The CVD matrices, for applying the transform yourself.

Example

curl "https://api.auricartisan.com/v1/vision/matrices" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/vision/palette

Run a whole palette through many conditions in one call.

Request body

NameTypeRequiredDescription
colorsarrayYesUp to 64 colours.
conditionsarrayNoCondition slugs. Omit for all 17 colour conditions. Spatial conditions are listed under refused.
severitynumberNo0–1, overriding each condition's own default.
passesnumberNo1–8. Repeats the transform.

Example

curl -X POST "https://api.auricartisan.com/v1/vision/palette" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"colors":["#D3AF37","#2E8B57"],"conditions":["deuteranopia","tritanopia"]}'

POST /v1/vision/audit

Find which pairs in a palette stop being distinguishable.

Request body

NameTypeRequiredDescription
colorsarrayYesAt least 2, up to 64.
conditionsarrayNoOmit for all 17 colour conditions.
thresholdnumberNoCIEDE2000 below which a pair counts as collapsed. Default 5.

Example

curl -X POST "https://api.auricartisan.com/v1/vision/audit" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"colors":["#B22222","#228B22"],"conditions":["deuteranopia"]}'

POST /v1/vision/simulate-image

Simulate a vision deficiency on the dominant colours of an image.

Returns JSON, not an image: the image is reduced to at most eight dominant colours, and each is returned before and after the simulation, with its weight.

Request body

NameTypeRequiredDescription
imagestringYesA base64 PNG. A data:image/png;base64, prefix is accepted; other image types are not.
modelstringYesAn engine model id such as brettel-deutan — see GET /v1/vision/models.
severitynumberNo0–1. Default 1.
maxPixelsintegerNoLargest image accepted, 1,000-10,000,000 pixels. Default 1,500,000.

Returns image object, model string, severity number, note string, dominant object[]

Example

curl -X POST "https://api.auricartisan.com/v1/vision/simulate-image" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"image":"iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAIAAAB7QOjdAAAAD0lEQVR42mM4uUhdVssOAAlsAhhwGF0kAAAAAElFTkSuQmCC","model":"brettel-deutan"}'

Ishihara

POST /v1/ishihara/plate

Generate an Ishihara test plate as structured data.

Request body

NameTypeRequiredDescription
figurestringYesDigits to hide in the plate, e.g. 74.
axisstringNoDeficiency to discriminate: protan, deutan (default), tritan.
sizeintegerNoPlate size in px, 64-1024. Default 400.
dotsintegerNoDot count, 50-5000. Default 800.
seedintegerNoInteger seed, for a repeatable plate.

Example

curl -X POST "https://api.auricartisan.com/v1/ishihara/plate" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"figure":"74","axis":"deutan","size":400}'

POST /v1/ishihara/png

Render an Ishihara plate as a PNG.

Takes the same body as POST /v1/ishihara/plate.

Request body

NameTypeRequiredDescription
figurestringYesDigits to hide in the plate, e.g. 74.
axisstringNoDeficiency to discriminate: protan, deutan (default), tritan.
sizeintegerNoPlate size in px, 64-1024. Default 400.
dotsintegerNoDot count, 50-5000. Default 800.
seedintegerNoInteger seed, for a repeatable plate.

Returns image/png

Example

curl -X POST "https://api.auricartisan.com/v1/ishihara/png" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"figure":"74","axis":"deutan","size":400}'

Usage

GET /v1/usage

Durable per-day, per-endpoint history for your key.

Parameters

NameTypeRequiredDescription
sincequeryNoEarliest day to include, YYYY-MM-DD. Defaults to seven days back.

Example

curl "https://api.auricartisan.com/v1/usage" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/usage/me

Your tier, limits and month-to-date quota consumption.

Example

curl "https://api.auricartisan.com/v1/usage/me" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/usage/live

The last 100 individual calls, with rolling latency and error stats.

Answers "what is happening right now" where /v1/usage answers "how much have I used". Pass the returned cursor back as since to poll incrementally.

Parameters

NameTypeRequiredDescription
limitqueryNo1–100, default 50.
sincequeryNoSequence number from a previous cursor.

Returns cursor number, stats object, events array

Example

curl "https://api.auricartisan.com/v1/usage/live" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/usage/stream SSE

The same live feed, pushed over Server-Sent Events.

Emits hello on connect with current stats, usage per request, and heartbeat every 15 s. Connections are capped at 10 minutes; EventSource reconnects on its own.

Example

curl "https://api.auricartisan.com/v1/usage/stream" \
  -H "x-api-key: $AURIC_API_KEY"

Jobs

GET /v1/jobs

The async job types this deployment can run.

Example

curl "https://api.auricartisan.com/v1/jobs" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/jobs/:type

Queue a long-running job and get an id back immediately.

The body is the parameter set for the chosen job type, so its shape varies — GET /v1/jobs documents what each type accepts. Poll /v1/jobs/id/:id or follow /v1/jobs/id/:id/stream.

Parameters

NameTypeRequiredDescription
typepathYesFrom GET /v1/jobs.

Example

curl -X POST "https://api.auricartisan.com/v1/jobs/palette-batch" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"count":500}'

GET /v1/jobs/id/:id

Poll one job.

Parameters

NameTypeRequiredDescription
idpathYes

Example

curl "https://api.auricartisan.com/v1/jobs/id/<id>" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/jobs/id/:id/stream SSE

Follow a job to completion over SSE instead of polling.

Parameters

NameTypeRequiredDescription
idpathYes

Example

curl "https://api.auricartisan.com/v1/jobs/id/<id>/stream" \
  -H "x-api-key: $AURIC_API_KEY"

Webhooks

GET /v1/webhooks/events No key

Event types you can subscribe to.

Public: it is a static list of event names, useful for deciding whether the API fits before you buy.

Example

curl "https://api.auricartisan.com/v1/webhooks/events"

GET /v1/webhooks

List your webhook subscriptions.

Example

curl "https://api.auricartisan.com/v1/webhooks" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/webhooks

Subscribe a URL to one or more events.

Deliveries are signed; verify the signature header before trusting a payload.

Request body

NameTypeRequiredDescription
urlstringYesHTTPS endpoint to deliver to.
eventsstring[]YesFrom /v1/webhooks/events.

Example

curl -X POST "https://api.auricartisan.com/v1/webhooks" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"url":"https://example.com/hook","events":["job.succeeded"]}'

GET /v1/webhooks/:id

Fetch one subscription.

Parameters

NameTypeRequiredDescription
idpathYes

Example

curl "https://api.auricartisan.com/v1/webhooks/<id>" \
  -H "x-api-key: $AURIC_API_KEY"

DELETE /v1/webhooks/:id

Revoke a subscription.

Parameters

NameTypeRequiredDescription
idpathYes

Example

curl -X DELETE "https://api.auricartisan.com/v1/webhooks/<id>" \
  -H "x-api-key: $AURIC_API_KEY"

GraphQL

GET /v1/graphql No key

GraphQL playground.

Example

curl "https://api.auricartisan.com/v1/graphql"

POST /v1/graphql

Run a GraphQL query against the same resolvers as the REST surface.

Useful when one round trip should answer several questions — convert a colour, check its contrast and simulate it at once.

Request body

NameTypeRequiredDescription
querystringYesThe GraphQL document.
variablesobjectNoVariable values.

Example

curl -X POST "https://api.auricartisan.com/v1/graphql" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"{ colorContrast(fg: \"#000\", bg: \"#fff\") { ratio wcag { aaNormal } } }"}'

Admin

GET /v1/admin/keys Admin

List issued API keys.

Example

curl "https://api.auricartisan.com/v1/admin/keys" \
  -H "x-admin-key: $AURIC_ADMIN_KEY"

POST /v1/admin/keys Admin

Issue a key. The secret is shown once and stored only as a hash.

Request body

NameTypeRequiredDescription
tierstringNoOne of free, pro, enterprise.
labelstringNoWho this key is for.

Example

curl -X POST "https://api.auricartisan.com/v1/admin/keys" \
  -H "x-admin-key: $AURIC_ADMIN_KEY" \
  -H "content-type: application/json" \
  -d '{}'

GET /v1/admin/keys/:id Admin

Fetch one key record (never the secret).

Parameters

NameTypeRequiredDescription
idpathYes

Example

curl "https://api.auricartisan.com/v1/admin/keys/<id>" \
  -H "x-admin-key: $AURIC_ADMIN_KEY"

DELETE /v1/admin/keys/:id Admin

Revoke a key immediately.

Parameters

NameTypeRequiredDescription
idpathYes

Example

curl -X DELETE "https://api.auricartisan.com/v1/admin/keys/<id>" \
  -H "x-admin-key: $AURIC_ADMIN_KEY"

Colour atlas

GET /v1/color/atlas

Browse the 8,192-colour atlas under a filter.

A finite catalogue, so matched is how many of the 8,192 qualify -- a real total, not a scan rate. hue_from/hue_to wrap, so hue_from=340&hue_to=20 is the reds. Page with offset; the summary record is the default and full=true adds the vision simulations and labels.

Parameters

NameTypeRequiredDescription
hue_fromqueryNoStart of a hue range, 0-360. Wraps past 360.
hue_toqueryNoEnd of the hue range, 0-360.
min_lightnessqueryNoOKLCH lightness floor, 0-1.
max_lightnessqueryNoOKLCH lightness ceiling, 0-1.
min_chromaqueryNoChroma floor, 0-1.
min_contrast_on_whitequeryNoKeep only colours readable on white at this ratio.
min_contrast_on_blackqueryNoKeep only colours readable on black at this ratio.
emotionqueryNoLabel filter, e.g. calm. See /v1/color/atlas/stats.
art_movementqueryNoLabel filter, e.g. Fauvism.
ai_moodqueryNoLabel filter, e.g. serene. (The record also has an always-empty mood; this is the populated one.)
ai_design_usagequeryNoLabel filter, e.g. typography, web-hero, data-viz.
design_tagqueryNoLabel filter, e.g. accent, pastel, jewel-tone.
sortqueryNoid (default), hue, lightness, chroma, contrast_on_white.
orderqueryNoasc (default) or desc.
limitqueryNoColours per page, 1-200. Default 24.
offsetqueryNoWhere to start. Use next_offset.
fullqueryNotrue for the complete record.

Returns matched number, share_of_atlas number, next_offset number|null, colors object[]

Example

curl "https://api.auricartisan.com/v1/color/atlas?min_contrast_on_white=4.5&sort=chroma&order=desc&limit=5" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/color/atlas/stats

What the atlas actually contains.

Counted from the records: hue occupancy, the lightness spread, the label vocabulary, and how much of the catalogue is usable as text on white or on black -- which is the question a designer reaching for a colour is really asking.

Returns readable_as_text object, hue_distribution object[], lightness_distribution object[], labels object

Example

curl "https://api.auricartisan.com/v1/color/atlas/stats" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/color/atlas/:id

Resolve one sample, whole.

Takes the numeric id or a hex the atlas contains. For a colour that is NOT in the atlas, use POST /v1/color/nearest.

Parameters

NameTypeRequiredDescription
idpathYesAn id 0-8191, or a hex like %2376cdf6.

Returns color object

Errors INVALID_INPUT (400) — No sample with that id or hex.

Example

curl "https://api.auricartisan.com/v1/color/atlas/0" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/color/nearest

The catalogued colours closest to one you already have.

This is what makes the atlas useful on a real brand: give it your hex and get the nearest sampled colours with all their metadata. Distance is CIE76 in Lab -- a straight walk over the whole atlas in about a millisecond -- and the response names the metric rather than leaving you to assume it.

Request body

NameTypeRequiredDescription
colorcolorYesThe colour to match.
countnumberNoHow many matches, 1-50. Default 5.
fullbooleanNotrue for the complete record on each match.

Returns metric string, matches object[]

Example

curl -X POST "https://api.auricartisan.com/v1/color/nearest" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"color":"#D3AF37","count":5}'

Corpus

GET /v1/accessibility/corpus

Browse the five-million-pair corpus under a filter, with a cursor.

Records are derived from a seed, not fetched from a table, so paging costs arithmetic. Read scanned and hit_rate alongside records: 88% of the corpus fails AA for body text, so twenty-four AAA pairs may represent seven hundred looked at. When truncated is true the scan budget ran out before the page filled -- follow next_cursor rather than assuming the filter is empty.

Parameters

NameTypeRequiredDescription
min_ratioqueryNoLowest contrast ratio to include, 1-21.
max_ratioqueryNoHighest contrast ratio to include, 1-21.
levelqueryNoAA, AAA, fail, or any (default).
gradequeryNoAuric SD grade: A+, A, B, C, D, F.
polarityqueryNoBoW (dark on light), WoB, or any.
limitqueryNoRecords per page, 1-200. Default 24.
cursorqueryNoCorpus index to resume from. Use next_cursor.
max_scanqueryNoHow many records this call may examine. Default 100,000, max 1,000,000.
fullqueryNotrue for the complete record, including all ten vision models.

Returns count number, scanned number, hit_rate number, next_cursor number|null, exhausted boolean, truncated boolean, records object[]

Example

curl "https://api.auricartisan.com/v1/accessibility/corpus?level=AAA&limit=5" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/accessibility/corpus/stats

The measured distribution of contrast across the corpus.

Counted, not asserted -- it walks a deterministic prefix, so the same sample always returns the same numbers. This is the endpoint that says most colour pairs are unusable, which a "5,000,000 combinations" claim hides.

Parameters

NameTypeRequiredDescription
samplequeryNoRecords to measure, 1,000-1,000,000. Default 200,000.

Returns sample number, mean_contrast_ratio number, share_at_least object, share_failing_aa_body number, distribution object[]

Example

curl "https://api.auricartisan.com/v1/accessibility/corpus/stats?sample=50000" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/accessibility/corpus/:record_id

Resolve one record by id or index.

The citation endpoint. Put acc_2j in a report and anyone can recover the same two colours from the seed, without being handed a database. Accepts either the record id or a bare corpus index.

Parameters

NameTypeRequiredDescription
record_idpathYese.g. acc_2j, or an index like 91.

Returns record object, cite string, recompute string

Errors INVALID_INPUT (400) — The id does not parse, or the index is outside the corpus.

Example

curl "https://api.auricartisan.com/v1/accessibility/corpus/acc_2j" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/accessibility/map

The whole territory of foreground colour a background leaves you.

For each hue, the lightness at which the most saturated colour of that hue just reaches the target on this ground. territory_pct is the share of the slice that qualifies -- which is how one background gets compared with another, rather than with a threshold. A null lightness means that hue never reaches the target at any lightness, which is a real answer and worth surfacing.

Request body

NameTypeRequiredDescription
groundcolorYesThe background colour.
targetsnumber[]NoContrast ratios to contour. Default [3, 4.5, 7], at most 6.
resolutionnumberNoHues sampled around the circle, 12-360. Default 72.

Returns ground string, polarity string, contours object[]

Example

curl -X POST "https://api.auricartisan.com/v1/accessibility/map" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"ground":"#1D2A3E","targets":[4.5,7]}'

POST /v1/accessibility/picks

A ready set of foregrounds that clear a target on one background.

Walks the hue circle, takes each hue to its boundary lightness, then steps margin past it so rounding cannot land a pick under the target. Hues that still cannot make it are dropped and counted, because a set whose promise is that everything in it works has to keep that promise.

Request body

NameTypeRequiredDescription
groundcolorYesThe background colour.
targetnumberNoContrast ratio to clear. Default 4.5.
countnumberNoHues to try, 1-72. Default 12.
marginnumberNoLightness held back from the boundary, 0-0.5. Default 0.10.

Returns count number, dropped number, picks object[]

Example

curl -X POST "https://api.auricartisan.com/v1/accessibility/picks" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"ground":"#1D2A3E","target":4.5,"count":12}'

POST /v1/accessibility/audit

Audit a palette against one background, with a fix for each failure.

The fix keeps the hue and moves the lightness onto the contour, so a corrected brand colour still looks like the brand. Where a hue cannot reach the target on that ground at all, it says so instead of returning a colour that does not work.

Request body

NameTypeRequiredDescription
groundcolorYesThe background everything sits on.
colorscolor[]YesThe palette, 1-64 colours.
targetnumberNoContrast ratio to clear. Default 4.5.

Returns verdict string, passing number, failing number, results object[]

Example

curl -X POST "https://api.auricartisan.com/v1/accessibility/audit" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"ground":"#1D2A3E","colors":["#D3AF37","#4A5568","#F7FAFC"],"target":4.5}'

Gradient library

GET /v1/gradient/library

Browse the 8,192-gradient collection under a filter.

A finite catalogue, so matched is a real total rather than a scan rate. The filter worth reaching for is banding: about one gradient in five steps visibly somewhere, and that is the thing a thumbnail cannot show you.

Parameters

NameTypeRequiredDescription
schemequeryNoe.g. Aurora, Spectral, Terrain. See /v1/gradient/library/stats.
complexityqueryNosimple, detailed or extreme.
bandingqueryNosmooth, subtle-compression or visible-step-risk.
typequeryNolinear, radial or conic.
min_scorequeryNoQuality floor, 0-1.
min_stopsqueryNoFewest colour stops.
max_stopsqueryNoMost colour stops.
sortqueryNoid (default), score or stops.
orderqueryNoasc (default) or desc.
limitqueryNoPer page, 1-100. Default 24.
offsetqueryNoWhere to start. Use next_offset.
fullqueryNotrue for the interpolation space, easing and metrics.

Returns matched number, share_of_collection number, next_offset number|null, gradients object[]

Example

curl "https://api.auricartisan.com/v1/gradient/library?banding=smooth&sort=score&order=desc&limit=5" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/gradient/library/stats

What the collection contains, counted rather than asserted.

The headline is the banding split: how much of a generated set actually steps smoothly. Also the scheme, complexity, interpolation-space and easing tallies.

Returns banding object[], scheme object[], interpolation_space object[]

Example

curl "https://api.auricartisan.com/v1/gradient/library/stats" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/gradient/library/:id

One gradient, whole.

Parameters

NameTypeRequiredDescription
idpathYesA row number, 0-8191.

Returns gradient object

Errors INVALID_INPUT (400) — The id is not a row in the collection.

Example

curl "https://api.auricartisan.com/v1/gradient/library/0" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/gradient/analyse

Measure a gradient you already have: will it band, and where?

Samples the ramp, converts each sample to OKLab, and measures the perceptual distance between consecutive samples. The verdict is the WORST step against the AVERAGE one -- a ratio, so it does not move when you ask for more samples. The thresholds are not invented: measured across 3,000 gradients the generator had already labelled, that ratio runs a median of 1.55 for the ones it calls smooth and 5.09 for the ones it calls a step risk. worst_transition_at says WHERE, which is the part you can act on.

Request body

NameTypeRequiredDescription
stopsarrayYesTwo to 64 stops, as ["#rrggbb", ...] (spaced evenly) or [{pos, hex}, ...] with pos 0-1.
stepsnumberNoSamples along the ramp, 8-1024. Default 96.

Returns banding string, step_ratio number, delta_e_mean number, delta_e_max number, worst_transition_at number, note string

Example

curl -X POST "https://api.auricartisan.com/v1/gradient/analyse" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"stops":["#001a33","#003d66","#ffcc00"]}'

Harmony library

GET /v1/harmony/library

Browse the 8,192-harmony collection under a filter.

A finite catalogue, so matched is a real total rather than a scan rate. The filter worth reaching for is min_contrast: only about a quarter of the collection contains a pair that carries body text, which is the thing a row of swatches cannot show you.

Parameters

NameTypeRequiredDescription
methodqueryNoOne of the 23, e.g. triadic. See /v1/harmony/library/stats.
familyqueryNocomplementary, analogous, polyadic, monochromatic or compound.
huequeryNoBase hue band: red, orange, yellow, green, cyan, blue, purple, pink.
colorsqueryNoHow many members, 2-7.
min_contrastqueryNoWorst pair must clear this ratio, 1-21.
min_adherencequeryNoHow closely it holds its canonical angles, 0-1.
sortqueryNoid (default), contrast, spread, adherence or colors.
orderqueryNoasc (default) or desc.
limitqueryNoPer page, 1-100. Default 24.
offsetqueryNoWhere to start. Use next_offset.
fullqueryNotrue for per-colour HSL/OKLCH, roles and the canonical angles.

Returns matched number, share_of_collection number, next_offset number|null, harmonies object[]

Example

curl "https://api.auricartisan.com/v1/harmony/library?family=polyadic&sort=contrast&order=desc&limit=5" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/harmony/library/stats

What the collection contains, counted rather than asserted.

The headline is with_an_aa_pair: how much of a generated set of colour schemes actually contains two members that can be used as text on each other. Also the method, family and size tallies.

Returns with_an_aa_pair object, method object[], family object[], color_count object[]

Example

curl "https://api.auricartisan.com/v1/harmony/library/stats" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/harmony/library/:id

One harmony, whole, with the derivation that reproduces it.

Records are not stored: each is computed from the manifest seed and its index, so the response carries the seed and batch that recompute it. That is what makes a harmony id citable rather than a row number.

Parameters

NameTypeRequiredDescription
idpathYesA harmony id (har_5k) or a number 0-8191.

Returns harmony object

Errors INVALID_INPUT (400) — The id names no harmony in the collection.

Example

curl "https://api.auricartisan.com/v1/harmony/library/har_0" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/harmony/identify

Name the scheme the colours you already have form.

Takes 2-12 colours and matches their hue pattern against all 23 schemes. Anchored on each colour in turn, so the answer does not depend on the order you send them in -- which also matters because several schemes' canonical angles are written relative to their MIDDLE member. Schemes that are the same shape on the hue circle and differ only in lightness or saturation (shades and monochromatic_5; triad_shifted and triadic) come back together in ties rather than one being chosen for you.

Request body

NameTypeRequiredDescription
colorsarrayYes2 to 12 colours as ["#rrggbb", ...].

Returns verdict string, best_match object, ties string[], candidates object[], hue_offsets number[], min_pair_contrast number, carries_body_text boolean

Example

curl -X POST "https://api.auricartisan.com/v1/harmony/identify" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"colors":["#FF0000","#00FF00","#0000FF"]}'

Palette library

GET /v1/palette/library

Browse five million generated palettes under a filter.

Palettes are derived from a seed, not stored -- the expanded form would be 3.9 GB. Nothing can walk five million inside a request, so a filtered browse SCANS: it reports scanned, hit_rate, and the two flags that matter. exhausted means the collection really ended. truncated means the scan budget ran out first, which is NOT the same thing -- a rare filter legitimately returns an empty page with a cursor, and a client that stops there stops short of the first match.

Parameters

NameTypeRequiredDescription
methodqueryNocomplementary, triadic, analogous, tetradic, golden_ratio, monochromatic or random.
characterqueryNoMeasured, not generated: neutral, monochrome, analogous, triadic or diverse.
huequeryNoFirst colour's hue band: red through pink.
min_contrastqueryNoThe WORST pair must clear this ratio, 1-21.
max_contrastqueryNoUpper bound on the worst pair.
min_lightnessqueryNoMean OKLCH lightness floor, 0-1.
max_lightnessqueryNoMean OKLCH lightness ceiling, 0-1.
min_chromaqueryNoMean OKLCH chroma floor, 0-0.5.
carries_body_textqueryNotrue for palettes with some pair at 4.5:1 or better.
sortqueryNoid (default), contrast, spread, lightness or chroma. Anything but id sorts WITHIN the scan, and the response says so in sorted_within_scan.
orderqueryNoasc (default) or desc.
limitqueryNoPer page, 1-100. Default 24.
cursorqueryNoWhere to resume. Use next_cursor.
max_scanqueryNoScan budget, 1,000-500,000. Default 20,000. Raise it for a rare filter.
fullqueryNotrue for per-colour RGB and OKLCH and the palette metrics.

Returns scanned number, hit_rate number, next_cursor number|null, exhausted boolean, truncated boolean, palettes object[]

Example

curl "https://api.auricartisan.com/v1/palette/library?carries_body_text=true&limit=5" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/palette/library/stats

What the collection looks like, measured on a stated sample.

Five million palettes cannot be counted inside a request, so this measures 70 runs of 600 consecutive palettes spread across the collection and reports the sample size with every figure. The headline: about 55% of these contain a pair that carries body text -- far more than a harmony collection, because five random colours differ in lightness where five hue rotations do not.

Returns measured_on object, with_an_aa_pair object, method object[], character object[]

Example

curl "https://api.auricartisan.com/v1/palette/library/stats" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/palette/library/:id

One palette, whole, with the derivation that reproduces it.

Records are computed from the manifest seed and their index, so the response carries the seed and batch that recompute them. A palette id is a claim anyone can check rather than a row somebody could edit.

Parameters

NameTypeRequiredDescription
idpathYesA palette id (pal_1z) or a number 0-4999999.

Returns palette object

Errors INVALID_INPUT (400) — The id names no palette in the collection.

Example

curl "https://api.auricartisan.com/v1/palette/library/pal_0" \
  -H "x-api-key: $AURIC_API_KEY"

Personalization

GET /v1/personalize/vocabulary

Everything a brief may name, with the ranges the engine really imposes.

The 18 style profiles with the chroma, lightness and saturation windows each one applies, the five intents, the 19 hue relationships and their offsets, the 17 type systems, and the gradient and poster catalogues. Read this before writing a brief: it is why neon cannot return a pastel.

Returns styles array, intents string[], relationships array, type_systems array, limits object

Example

curl "https://api.auricartisan.com/v1/personalize/vocabulary" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/personalize/presets

The 17 briefs the tool ships, in request shape.

Each brief can be posted straight to any endpoint in this group.

Returns count integer, presets array

Example

curl "https://api.auricartisan.com/v1/personalize/presets" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/personalize/pool

Grow a working set of colours from seeds and a brief.

The generator searches WITHIN a pool, so the pool decides how wide the search is. This is that growth step alone, for a caller who wants to inspect or edit the colours before sweeping them. The response also returns the brief resolved to numbers: what a style plus a warmth actually means to the engine.

Request body

NameTypeRequiredDescription
colorsstring[]NoSeed colours, up to 64. Defaults to the tool’s own eight.
stylesstring[]NoStyle keys from /v1/personalize/vocabulary.
intentstringNoui (default), brand, poster, editorial, dashboard.
targetintegerNoPool size to grow to, 1-240. Default 64.
warmthnumberNo0-100. Default 52.
seedintegerNoOmit for a random one; it is always returned.

Returns brief object, pool string[], profile object

Example

curl -X POST "https://api.auricartisan.com/v1/personalize/pool" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"colors":["#0F172A","#D3AF37"],"styles":["luxe","editorial"],"target":24}'

POST /v1/personalize/score

Rank a palette you already have, on the search’s own six scores.

Preference, harmony, diversity, contrast, style fit and accessibility — the same scorers the search ranks by, so a palette from a brand book can be measured against the brief you care about. Omit relationship and every hue geometry is tried and the best-fitting reported, which is the answer to what a palette actually is.

Request body

NameTypeRequiredDescription
palettestring[]Yes2-12 colours.
relationshipstringNoA relationship id to measure against. Omit to match the best.
stylesstring[]NoThe brief the palette is being judged for.
intentstringNoOne of the five intents.
accessibilitynumberNo0-100, how hard accessibility is weighted. Default 72.

Returns score object, measured_as object, best_pair object, alternatives array

Example

curl -X POST "https://api.auricartisan.com/v1/personalize/score" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"palette":["#0F172A","#F8FAFC","#D3AF37","#14B8A6"],"styles":["tech","minimal"]}'

POST /v1/personalize/palettes

Search: N candidates in, the best K out, each with its breakdown.

The response reports what the sweep DID, not only what it kept — how many candidates were sampled, how many survived de-duplication, and where the cut fell. Contrast and colour-vision are WEIGHTS in the score, never filters: a candidate that reads badly is ranked down, not discarded, so kept does not mean the accessible ones.

Request body

NameTypeRequiredDescription
colorsstring[]NoSeed colours the search draws on.
stylesstring[]NoStyle keys from /v1/personalize/vocabulary.
intentstringNoOne of the five intents.
notestringNoFree text; matched against the curated colour memories.
depthintegerNoCandidates to sample, 8-1200. Default 320.
keepintegerNoHow many to return, 1-120. Default 24.
palette_sizeintegerNoColours per palette, 5-12. Default 6.
diversitynumberNo0-100. Default 68.
accessibilitynumberNo0-100. Default 72.
cvd_safebooleanNoWeight colour-vision separation. Default true.
uniquebooleanNoDrop repeated signatures. Default true.
seedintegerNoThe same seed and brief always give the same result.

Returns brief object, sweep object, palettes array

Example

curl -X POST "https://api.auricartisan.com/v1/personalize/palettes" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"colors":["#0F172A","#D3AF37"],"styles":["luxe","editorial"],"intent":"brand","depth":400,"keep":12}'

POST /v1/personalize/system

One brief in, an entire design system out.

The sweep, then from its leader: gradients, type pairings, UI colour pairs with WCAG and APCA measured, poster compositions, and a production token deck with tonal ramps, synced light/dark/high-contrast themes and a contrast matrix. include trims the response and skips the work, not just the serialisation.

Request body

NameTypeRequiredDescription
colorsstring[]NoSeed colours the search draws on.
stylesstring[]NoStyle keys from /v1/personalize/vocabulary.
intentstringNoOne of the five intents.
includestring[]NoAny of palettes, gradients, typography, ui_pairs, posters, tokens. Defaults to all.
derivedintegerNoHow many palettes each derived section covers, 1-24. Default 8.
depthintegerNoCandidates to sample, 8-1200. Default 320.
keepintegerNoPalettes to keep, 1-120. Default 24.
seedintegerNoOmit for a random one; it is always returned.

Returns leader object, palettes array, gradients array, typography array, ui_pairs array, posters array, tokens object

Example

curl -X POST "https://api.auricartisan.com/v1/personalize/system" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"colors":["#0F172A","#D3AF37"],"styles":["tech","minimal"],"intent":"ui","include":["tokens","ui_pairs"]}'

Shade library

GET /v1/shade/library

Browse 8,192 measured shade scales under a filter.

Every scale carries three measurements a token ramp lives or dies by: whether it runs one way, how even its steps are, and whether any step can carry text on any other. All 8,192 are monotonic and all can carry text -- what actually separates them is evenness, and only 8.2% are clean.

Parameters

NameTypeRequiredDescription
methodqueryNoOne of ten, e.g. tailwind-like, oklch-ramp, ink-paper.
evennessqueryNoeven, slightly-uneven or lumpy. The filter worth reaching for.
huequeryNoBase hue band: red through pink.
stepsqueryNoExactly this many steps, 2-64.
min_spanqueryNoContrast between the extremes, 1-21.
min_scorequeryNoGenerator quality floor, 0-1.
monotonicqueryNotrue for scales that never turn round.
carries_body_textqueryNotrue for scales with a pair at 4.5:1 or better.
sortqueryNoid (default), score, steps, span or evenness (evenest first).
orderqueryNoasc (default) or desc.
limitqueryNoPer page, 1-100. Default 24.
offsetqueryNoWhere to start. Use next_offset.
fullqueryNotrue for the full measurement block.

Returns matched number, share_of_collection number, next_offset number|null, scales object[]

Example

curl "https://api.auricartisan.com/v1/shade/library?evenness=even&sort=span&order=desc&limit=5" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/shade/library/stats

What the collection contains, counted rather than asserted.

The headline is the evenness split. Monotonicity and text-carrying are 100% here, which is worth knowing precisely because it means neither is a useful filter -- evenness is.

Returns evenness object[], monotonic object, carries_body_text object, method object[]

Example

curl "https://api.auricartisan.com/v1/shade/library/stats" \
  -H "x-api-key: $AURIC_API_KEY"

GET /v1/shade/library/:id

One scale, whole, with every measurement.

Parameters

NameTypeRequiredDescription
idpathYesA shade id (shade_000000) or a row number 0-8191.

Returns scale object

Errors INVALID_INPUT (400) — The id names no scale in the collection.

Example

curl "https://api.auricartisan.com/v1/shade/library/shade_000000" \
  -H "x-api-key: $AURIC_API_KEY"

POST /v1/shade/evaluate

Measure a scale you already have: does it work as a token ramp?

Runs the collection's own three measurements against your steps. A scale fails in one of three ways and each has a different fix, so the response says which: it TURNS ROUND (two steps read as the same tone), its steps are LUMPY (the largest is several times the average, which is what makes a scale feel arbitrary in use), or its extremes are too close to set text between (a surface ramp, not a text scale).

Request body

NameTypeRequiredDescription
stepsarrayYes3 to 64 colours, as ["#rrggbb", ...], in scale order.

Returns verdict string, notes string[], monotonic boolean, step_ratio number, evenness string, usable_span number, text_pairs object

Example

curl -X POST "https://api.auricartisan.com/v1/shade/evaluate" \
  -H "x-api-key: $AURIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"steps":["#FFFFFF","#E0E0E0","#A0A0A0","#606060","#202020"]}'

Errors returned by any endpoint

CodeStatusWhen
UNAUTHENTICATED401No key, or a key that is not recognised.
FORBIDDEN403Valid key without rights for this route (for example a non-admin key on /v1/admin/*).
NOT_FOUND404No route matches. GET /v1 lists them all.
METHOD_NOT_ALLOWED405Right path, wrong verb. The Allow header lists what is accepted.
INVALID_INPUT400A field failed validation. The message names the field.
INVALID_JSON400The body is not parseable JSON.
RATE_LIMITED429Per-minute rate limit exceeded. Retry-After says when to try again.
QUOTA_EXCEEDED429Monthly quota exhausted. x-quota-reset gives the reset time.
INTERNAL500Unhandled server error. Quote the request_id when reporting it.

5. Request examples

+

Contrast check (WCAG + APCA)

curl -X POST https://api.auricartisan.com/v1/accessibility/check \
  -H "x-api-key: aa_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"fg": "#1a1712", "bg": "#d3af37"}'

Generate a palette

curl -X POST https://api.auricartisan.com/v1/palette/generate \
  -H "x-api-key: aa_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"method": "analogous", "count": 5, "hue": 45}'

Simulate protanopia

curl -X POST https://api.auricartisan.com/v1/vision/simulate \
  -H "x-api-key: aa_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"color": "#d3af37", "model": "brettel-protan", "severity": 1}'

Check your usage

curl https://api.auricartisan.com/v1/usage/me -H "x-api-key: aa_YOUR_KEY"

# → {"tier":"pro","plan":"specialist","auth_type":"api_key",
#    "limits":{"rate_per_minute":300,"monthly_quota":1000000},
#    "this_month":{"slot":"2026-08","used":412}}
#
# `used` counts credits, not calls — see section 3.

6. Errors

+

Errors are JSON with a stable code and a human-readable message; most include a request_id for support.

{
  "error": {
    "code": "INVALID_INPUT",
    "message": "seed: not a number"
  },
  "request_id": "daebcbed-508b-4d4d-91ef-87ee99d32f03"
}
Status Code Meaning
400INVALID_INPUTA parameter is missing or malformed — the message names it.
401UNAUTHENTICATEDMissing, invalid or revoked API key.
404NOT_FOUNDUnknown endpoint or resource id.
413PAYLOAD_TOO_LARGEBody over 4 MB on any endpoint. Sent by the Node server (npm run api), which reads the limit from AURIC_API_MAX_BODY.
429RATE_LIMITEDPer-minute rate exceeded — honor retry-after.
429IP_RATE_LIMITEDToo many requests from one address, regardless of key.
429QUOTA_EXCEEDEDIncluded monthly credits are used up and pay-as-you-go is off. Enable it, or wait for the reset — details.resets_at says when.
429HARD_CEILING_REACHEDThe absolute monthly ceiling (ten times the included allowance) was hit. A safety stop, not a sales gate — contact support to raise it.
402INSUFFICIENT_CREDITSPay-as-you-go is on but the prepaid balance will not cover the call. Top up; nothing is billed after the fact.
402SPEND_CAP_REACHEDYour own monthly overage spend cap was reached. Raise it in the dashboard.
402CREDIT_DEBIT_FAILEDThe balance could not be debited, so the request was not served. No charge was made — retry.
402PLAN_UPGRADE_REQUIREDValid key on a plan without API access. Included from Specialist upward.
503NOT_CONFIGUREDOptional subsystem disabled in this deployment.
503ENFORCEMENT_UNAVAILABLERate limiting, quota or idempotency could not be evaluated. Nothing was executed — retry later.

429 or 402 — which is which

The split is by what you should do about it, which is what a status code is for. 429 means back off and retry: the condition resets on its own, on the clock named in retry-after and details.resets_at. Every SDK already retries on it, and an exhausted allowance keeps returning it exactly as this API did before overage existed. 402 means only a money decision unblocks it — a top-up or a raised spend cap — and retrying without one is pointless.

Every refusal names its remedy in details.remedy (enable_overage, buy_credits, raise_spend_cap, contact_support) alongside credits_used, credits_included, credits_this_request and resets_at, so a client can log something actionable rather than “quota exceeded”.

{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Pay-as-you-go is on, but the prepaid credit balance is empty. Top up to continue — nothing is billed after the fact.",
    "details": {
      "tier": "pro",
      "credits_used": 1000010,
      "credits_included": 1000000,
      "credits_this_request": 10,
      "resets_at": "2026-09-01T00:00:00.000Z",
      "remedy": "buy_credits",
      "credits_needed": 10
    }
  },
  "request_id": "daebcbed-508b-4d4d-91ef-87ee99d32f03"
}

7. SDKs and tooling

+

Official clients and integrations, all speaking the same v1 surface.

Client Package / location Notes
JavaScript@auric-artisan/apiNode 18+, browsers, Workers. Typed methods for every endpoint.
Pythonauric-artisanPython 3.8+, stdlib-only, zero dependencies.
CLI@auric-artisan/cliauric contrast '#222' '#fff' straight from your terminal.
MCP serverapi/sdk/mcp/Give Claude, Cursor or any MCP host direct access to the color tools.
Postmanapi/postman.jsonReady-made collection covering the whole API.
GraphQLPOST /v1/graphqlSingle-endpoint alternative; playground included.

8. Local development

+

Contributors running the repo can start the API locally with npm run api (port 3002). That server is a local development convenience — it is not a public endpoint, and hosted clients should always call https://api.auricartisan.com. To accept the keys you create in the dashboard, point the local server at your auth worker:

AURIC_AUTH_WORKER_URL=http://127.0.0.1:8787 npm run api
  • AURIC_API_KEYS=key1,key2 seeds ad-hoc in-memory keys.
  • AURIC_API_OPEN_MODE=1 allows anonymous requests (local only).
  • AURIC_ADMIN_KEY=… enables the /v1/admin/* endpoints.

For account-level key management (create, revoke, last-used audit), see the API Keys tab in your dashboard.

9. Plans and pricing

+

The API is metered in credits — one credit per standard request, more for heavier work (see section 3). Each plan includes a monthly allowance of credits; past it, prepaid pay-as-you-go overage can be turned on, and nothing is ever invoiced after the fact.

PlanAPI accessCredits / monthRate limitOverage
Apprentice (free)Not included———
ArtisanNot included———
SpecialistIncluded1,000,000300 / min$1.00 / 100,000 credits, prepaid & opt-in
Industrial ProIncluded10,000,0003,000 / min$1.00 / 100,000 credits, prepaid & opt-in

Industrial Pro subscriptions started before 12 August 2026 are grandfathered. That plan was sold with unlimited API requests, and we are not taking that back from anyone who bought it: those accounts keep an allowance of 1,000,000,000 credits a month — a hundred times the figure above. At 3,000 requests a minute that is not reachable with standard 1-credit calls; sustained image (10–12 credits) or async-job (25 credits) traffic could reach it, and the hard ceiling for these accounts scales with the allowance rather than sitting below it. The 10,000,000 figure applies to subscriptions started on or after that date.

The API is a paid feature. It is included from Specialist upward — see plans. A key created on a plan without API access authenticates but is refused on metered endpoints with 402 PLAN_UPGRADE_REQUIRED, and the response names the upgrade path.

Discovery stays open to everyone, with or without a key, so you can evaluate the API before buying: GET /v1, GET /v1/catalog, GET /v1/openapi.yaml, GET /v1/docs, GET /v1/tiers and GET /v1/health.

Exceeding a plan's allowance returns 429 QUOTA_EXCEEDED rather than a surprise charge. Overage is off until you enable it, spends only credits bought in advance, respects a spend cap you set, and stops unconditionally at ten times the included allowance. Credit top-ups are self-serve: buy a pack from Dashboard → API keys → Add credits, and note that purchased credits do not expire at period end. For volume beyond the largest pack, a custom rate limit, or a contract, talk to us.

Billing terms — expiry, cancellation, downgrade and refunds on prepaid credits — are in the Subscription & Billing Policy.

Compare plans Manage API keys