API

Changelog

Last updated 23 October 2026

Every change to the public API, newest first. Breaking changes ship as a new dated API version, chosen per request with the Numerology-Version header. Deprecated endpoints answer with Deprecation and Sunset headers at least six months before they are removed.

Unreleased

Removed — interpretations

The API no longer returns meaning text. Chart, batch, cycles and compatibility requests no longer take expand or lang, and a request that sends either now answers 422 parameter_invalid, like any unknown field. Responses no longer carry interpretations, and Accept-Language is ignored. The numbers themselves are unchanged in every API version.

  • The Python and JavaScript SDKs (2.0.0) drop the expand and lang arguments, and the TypeScript types drop interpretations.
  • The MCP server's get_numerology_chart and get_personal_cycles tools no longer take interpretations or language.

Changed — rate limits per second, by plan

The rate limit on the chart, batch, cycles and compatibility endpoints was 60 requests a minute on every plan. It is now counted per second, over a sliding window, and set by the plan: 5 a second on Free, 25 on Starter and 100 on Pro. Batch work and backfills no longer hit 429 after a minute's worth of calls, and a loop gone wrong is stopped within a second. A batch still counts as one request.

Every paid response now carries RateLimit-Limit (requests per second on your plan), RateLimit-Remaining and RateLimit-Reset (seconds until the window has room), and a 429 rate_limited still carries Retry-After. GET /v1/plans lists each plan's requests_per_second.

Removed — Authorization: Bearer for API keys

API keys are accepted only in the X-API-Key header. A request that sends its key as Authorization: Bearer nk_live_… is now treated as having no key and answers 401 api_key_missing. The official SDKs and the MCP server already send X-API-Key, so they need no change. A 401 from the API now challenges with WWW-Authenticate: X-API-Key realm="numerology".

Removed — test mode, and version 2026-10-26

Test-mode keys are gone: every key is an nk_live_… key and spends the plan's monthly quota. Test keys that existed are revoked and answer 401 api_key_invalid; their test-mode usage history is deleted. Give each environment its own key instead, so one can be rolled or revoked alone.

  • New version 2026-10-26, now the current one. Chart, batch, cycles and compatibility responses no longer carry livemode. Versions 2026-10-22 and 2026-09-26 still do, always true. Pin Numerology-Version: 2026-10-22 to keep the field while you update.
  • GET /v1/account no longer returns livemode, test_quota or test_quota_remaining, and GET /v1/plans no longer returns test_quota.
  • POST /v1/keys no longer takes mode, and keys no longer have one. GET /v1/me drops test_usage and renames live_usage to usage.
  • Billing endpoints (/v1/checkout, /v1/subscription, /v1/portal) accept any API key, and the livemode_key_required error no longer exists.
  • The JavaScript SDK (1.1.0) types livemode as optional.

Changed — compressed chart responses

/v1/charts/pythagorean, /v1/charts/batch, /v1/cycles, /v1/compatibility and /v1/demo answer with Content-Encoding: gzip when the request sends Accept-Encoding: gzip, and with Vary: Accept-Encoding. A batch of 100 charts arrives about ten times smaller. Requests without that header get the same uncompressed JSON as before. The Python SDK (1.1.0) asks for compression and keeps its connection open between calls.

Removed — sign-up and sign-in endpoints

Accounts now sign up with GitHub, Google, or an email and a password at /accounts/signup/. The address is confirmed with an emailed code, and the pages under /accounts/ handle signing in, password resets and sessions. These endpoints are gone: POST /v1/signup, POST /v1/auth/login, POST /v1/auth/verify, POST /v1/auth/logout and POST /v1/auth/logout-all, along with the token_invalid error. The first API key is no longer issued when the address is confirmed: create keys from the dashboard (POST /v1/keys). Accounts created with emailed links have no password yet, so set one with "Forgot your password?" on the sign-in page, or sign in with GitHub or Google using the same address. Signing up with GitHub or Google needs no code. GET /v1/account/export now also lists open sessions, with the IP address and browser of each, and any connected GitHub or Google account.

New — pay without leaving the site

POST /v1/checkout takes an optional ui_mode. The default, hosted, works as before and answers the checkout_url to redirect to. elements answers a client_secret instead (and checkout_url: null), with which Stripe.js draws the payment form (the Payment Element) in your own page. Both responses now carry both fields. The account page uses it, so paying no longer leaves the site.

Changed — downgrades wait for the end of the period

POST /v1/subscription to a smaller plan, or from annual to monthly billing, no longer applies at once with a credit for the unused time. The current plan keeps working until the end of the period already paid for, and the next period is billed at the new one. Until then the response's plan and interval are the current ones, and the new scheduled_plan and scheduled_interval fields (also in GET /v1/me) say what comes next. Posting the current plan undoes the downgrade, and an upgrade or a cancellation replaces it. Upgrades are unchanged: prorated and charged at once.

New — cancel and resume a subscription

DELETE /v1/subscription stops a subscription renewing. The plan keeps working until the end of the period already paid for, then the account returns to Free with the same keys. Posting the current plan to POST /v1/subscription undoes the cancellation, and choosing another plan undoes it too. Both responses, and GET /v1/me, carry the new cancel_at field: when the subscription ends, or null while it renews. GET /v1/me also gains has_billing_portal: whether POST /v1/portal opens, which stays true after a subscription ends so its invoices remain reachable.

Changed — usage carries over a plan change

Changing plan within a billing period no longer resets the requests used: a customer who has used 9,000 on Starter and moves to Pro has 91,000 left, not 100,000. Usage still resets when a new billing period starts: a renewal, a first subscription, or a change between monthly and annual billing.

Changed — plan changes are paid before they apply

POST /v1/subscription now invoices and charges the prorated difference at once, instead of adding it to the next renewal, and the new plan applies only once that payment succeeds. If it fails or needs the customer to confirm it, the response keeps the current plan and interval and gives the invoice to pay in the new pending_payment_url field (otherwise null). Paying it applies the change; an unpaid change lapses after 23 hours.

Changed — the demo is for the website only

POST /v1/demo now needs a captcha_token from the home page's Cloudflare Turnstile widget, and is limited to 15 charts an hour per IP address instead of 30 a minute. A missing token answers 422 parameter_invalid, a rejected one 403 captcha_failed, and 503 captcha_unavailable means Cloudflare couldn't be reached. To call the API from code or a terminal, use a free key.

API version 2026-10-22 — the chart is grouped

Charts from /v1/charts/pythagorean, /v1/charts/batch and the demo group related fields instead of listing them flat. The numbers themselves do not change, and requests with Numerology-Version: 2026-09-26 get the flat chart exactly as before.

  • first_name, middle_name, last_name and birthdate move into person.
  • physical_plane … intuitive_plane become planes_of_expression, with the keys physical, mental, emotional and intuitive.
  • life_path_expression_bridge and soul_urge_personality_bridge become bridges.life_path_expression and bridges.soul_urge_personality.
  • first_pinnacle … fourth_pinnacle, first_challenge … fourth_challenge and first_life_cycle … third_life_cycle become the arrays pinnacles, challenges and life_cycles. Each stage is {stage, number, from_age, to_age}, like the cycles endpoint's current_pinnacle; the last stage's to_age is null.
  • pinnacle_challenge_age_ranges is removed: the stages carry their ages.
  • full_name_number_counts is a list of {number, count} for the digits 1 to 9, in order and zeros included, instead of an object keyed by the digits as strings.
  • chart_text is removed. Build display text from the fields, or pin 2026-09-26 to keep receiving it.
  • With expand: ["interpretations"], interpretations.challenges is an array of {stage, number, summary} instead of an object keyed by first_challenge … fourth_challenge.

Changed — the service now runs on Django

Charts, cycles and compatibility are computed exactly as before, the endpoints and the error envelope are unchanged, and existing API keys keep working. What a client can notice:

  • Request ids in X-Request-Id and error.request_id are now UUIDs (32 hex characters) instead of req_…. A caller's own X-Request-Id is honoured when it is a UUID.
  • Timestamps in account and key responses use the ISO 8601 form 2026-10-21T13:25:01.123456Z.
  • Rate limits: 429 responses still carry Retry-After; the X-RateLimit-Limit and X-RateLimit-Remaining headers, and the demo's X-Demo-* headers, are no longer sent. Live and test keys share one burst limit per account.
  • API versions are chosen per request with Numerology-Version; requests without it use the current version. Accounts are no longer pinned.
  • The dashboard (/v1/me, /v1/keys, …) protects session writes with a CSRF token (X-CSRFToken, from the csrftoken cookie) instead of checking Origin; a refused write is 403 forbidden.
  • POST /v1/portal no longer reads an api_key from the body; send the key in the X-API-Key header.
  • Sign-in links carry the next step in the link itself.
  • The OpenAPI document is generated by drf-spectacular (still OpenAPI 3.1).

Removed

  • POST /numerology, the chart route from before /v1, deprecated in 2026-09-26. Use POST /v1/charts/pythagorean: the same body, and the same 47 fields plus object, system, api_version, livemode and conventions. Errors use the standard envelope.

New

  • Cyrillic names are valued with the Russian numerology table: the 33-letter alphabet in order, 1–9 in repeating rows. Ё is its own letter (7), Ъ and Ь count (1 and 3), Й is a consonant. Planes of expression and intensity points are null for names containing Cyrillic, since both are defined over the Latin alphabet.
  • options.transliteration: "latin" rewrites Latin letters with no A–Z base — ø, ł, ß, æ, œ, đ, ð, þ, ı — before computing. Opt-in: the default ("none") and every existing Latin chart are unchanged. Cyrillic is never transliterated.
  • computed_name on every chart: the letters the chart was actually computed from ("Søren" → sren by default, soren with transliteration).
  • conventions.transliteration is echoed on charts and compatibility results.

Changed

  • Cyrillic first and last names, previously refused, are now accepted and valued. A Cyrillic middle name, previously ignored without warning, now counts — charts for such requests change, because they were computed from the Latin letters alone.
  • Letters from Cyrillic alphabets other than Russian (Ukrainian Ї, Є, Ґ; Serbian Ј; …) are refused with 422 instead of being silently skipped.
  • physical_plane, mental_plane, emotional_plane, intuitive_plane and intensity_points are now nullable in the schema (null only for Cyrillic).

2026-09-26 — API version 2026-09-26

The first dated API version. Accounts that existed before today are pinned to it, so nothing they call changes behaviour.

New

  • POST /v1/charts/pythagorean — the chart endpoint under /v1, returning the same 47 fields plus object, system, api_version, livemode and the conventions that produced it.
  • Opt-in conventions — options.y_rule (consonant · vowel · both · contextual) and options.name_reduction (whole_name · per_name). The defaults are unchanged and frozen.
  • POST /v1/charts/batch — up to 100 charts per request, charged all-or-nothing.
  • POST /v1/cycles — personal and universal year, month and day, and the Pinnacle, Challenge and Life Cycle in force on a date.
  • POST /v1/compatibility — a documented, weighted comparison of two people's core numbers.
  • Interpretations — expand: ["interpretations"] adds meaning text, in English or Spanish (lang, or Accept-Language).
  • Test-mode keys (nk_test_…) with their own allowance, and livemode on every response.
  • Several keys per account: create, name, roll (optionally keeping the old key alive for up to 7 days) and revoke — from the dashboard or /v1/keys.
  • Emailed sign-in — the dashboard signs in with a one-time link instead of a pasted API key. A lost key is recovered by signing in and creating a new one. next also accepts admin, which the admin's own sign-in link continues to.
  • Annual billing, plan changes (POST /v1/subscription, prorated) and opt-in overage billing past the quota.
  • Quota emails at 80% and 100%, and notices for key changes, plan changes and failed payments.
  • Account export and deletion (GET /v1/account/export, DELETE /v1/account). Deletion bills overage already served: it is reported to the meter, and the subscription stops renewing and ends with its paid period, whose invoice bills that overage. If Stripe cannot take the report, deletion answers 503 billing_unavailable and nothing is deleted.
  • Errors now share one shape: {"error": {"type", "code", "message", "param", "doc_url", "request_id"}}.
  • Every response carries X-Request-Id.

Changed

  • Signup verifies the email address first. POST /v1/signup answers 202 and emails a link; the API key is issued when the link is opened. It no longer returns 409 for a known address — it emails a sign-in link instead.
  • POST /v1/checkout requires a signed-in session or a live API key. It no longer creates an account from a bare email address, and refuses (409) for an account that already has a subscription.
  • Validation errors on /v1 routes use the new error shape. Status codes are unchanged.
  • Name fields are limited to 100 characters, and unknown request fields are rejected rather than ignored.

Deprecated

  • POST /numerology — use POST /v1/charts/pythagorean. It still works, byte-for-byte as before, and answers with Deprecation, Sunset (31 March 2027) and a Link to its successor.
  • The api_key body field on POST /v1/portal — send the key as a header.