← Blog

Running a numerology API in production: keys, versions, errors and quotas

·5 min read

Getting a first chart back takes five lines. Keeping an integration healthy for years takes a few more things: keys you can replace without downtime, answers that don’t shift under stored data, errors your code can act on, and limits you see coming before your users do.

This is how each of those works with the Simple Numerology API, and what to do with it in your own code.

One key per environment

Every key spends the plan’s monthly quota. Give production, staging and CI a key each: when one leaks, or a test suite runs away, you can roll or revoke that key alone. A test suite calls the API like any other client, so in unit tests, mock the API rather than calling it on every run.

Rolling a key without downtime

An account can hold up to 20 active keys. When a key needs replacing, because someone left or a key ended up in a log, roll it from the dashboard instead of revoking it. Rolling issues a new key and can keep the old one working for up to 168 hours, so you deploy the new key first and the old one expires on its own afterwards.

Every key that is created, rolled or revoked sends an email to the account, so a change you didn’t make gets noticed.

Pin the version you built against

A numerology answer depends on conventions: whether Y is a vowel, whether master numbers survive, how names are reduced. Here those conventions are part of the contract. Anything that could change an existing answer ships as a new, dated version, and the changelog records it.

Send the version you tested with on every request:

curl -X POST https://simplenumerologyapi.com/v1/charts/pythagorean \
  -H 'X-API-Key: nk_live_…' \
  -H 'Numerology-Version: 2026-10-26' \
  -H 'content-type: application/json' \
  -d '{"first_name": "Ana", "last_name": "Smith", "birthdate": "1990-01-01"}'

Without the header you get the current version, which is fine while prototyping. In production, pinning means a new version never reaches you until you choose to upgrade, and the response echoes the version that served it. The SDKs take it once: Client(api_version="2026-10-26").

Errors you can branch on

Every error has the same shape. Here is the answer to a birthdate of 1990-02-30:

{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "birthdate: Date has wrong format. Use one of these formats instead: YYYY-MM-DD.",
    "param": "birthdate",
    "doc_url": "https://simplenumerologyapi.com/docs#error-parameter_invalid",
    "request_id": "f4e4874404c7466188221e37a00d4721",
    "errors": [ … ]
  }
}

Branch on type and code, never on message, which is written for people and may change. param names the field at fault, so a form can highlight it, and a validation error also lists every invalid field in errors. Each code has its own entry in the error reference.

The status codes that matter most in production:

  • 422 parameter_invalid: the input is wrong, so retrying won’t help. Show the user param.
  • 402 quota_exceeded: the month’s allowance is spent. See quotas below.
  • 429 rate_limited: the plan’s requests per second were exceeded. Wait for Retry-After, then retry.
  • 5xx: retry with backoff. Chart requests compute the same answer every time, so a retry is always safe.

The official SDKs do this for you. They retry 429 and 5xx responses with jittered backoff (and Retry-After when present), and raise a typed exception for everything else:

from simple_numerology import Client, InvalidRequestError, QuotaExceeded

client = Client(api_version="2026-10-26")

try:
    chart = client.pythagorean("Ana", "Smith", "1990-01-01")
except InvalidRequestError as error:
    show_field_error(error.param, error.message)
except QuotaExceeded:
    queue_for_later()

Request IDs

Every response carries an X-Request-Id header, and every error repeats it as request_id. Log it next to your own records. If something looks wrong, that ID is what lets a support request find the exact call.

You can also send your own X-Request-Id (a UUID). The API then uses yours, so a single ID follows the call through your logs and ours.

Quota you can see coming

Every successful response says where you stand:

X-Quota-Limit: 10000
X-Quota-Remaining: 9412
X-Quota-Reset: 2026-11-25T09:14:03+00:00

The rate limit reports itself the same way: RateLimit-Limit (requests per second on your plan), RateLimit-Remaining and RateLimit-Reset, so a batch job can slow down before it is refused.

The account email gets a warning at 80% of the monthly quota and again at 100%. At the limit, requests get a 402 with the same headers, so your code can tell “out of quota” from “broken”. On a paid plan you can switch on overage instead: requests keep being served past the quota, billed per 1,000, and X-Overage-Used counts them.

The SDKs keep the latest values, for example client.last_quota.remaining in Python, which is handy for a dashboard or an alert of your own.

Backfills with batch requests

Computing charts for an existing user base one request at a time is slow and fragile. POST /v1/charts/batch takes up to 100 people in one call. Every item is validated before any is computed, and a batch that doesn’t fit in the remaining quota is refused whole, so a backfill never stops halfway through a batch. See batch requests.

Charts never change for the same input and version, so store each one next to the user it belongs to and compute it again only when the name or birthdate changes.

SDKs, OpenAPI and AI agents

  • Python: pip install simple-numerology, standard library only. A client keeps its connection open between calls, so reuse one.
  • JavaScript and Node.js: npm install simple-numerology.
  • Anything else: generate a typed client from the OpenAPI 3.1 document, or import the Postman collection. See generating a client.
  • AI agents: an MCP server exposes charts, cycles and compatibility as tools. See the MCP section of the docs.

Personal data

A numerology request contains a full name and a date of birth. Here they are computed and discarded: never stored, never logged, and sent in the request body rather than the URL, so they stay out of access logs. The privacy policy says so, and a data processing agreement is published for your own compliance records.

A production checklist

  • One key per environment, so any one can be rolled or revoked alone.
  • Numerology-Version pinned on every request.
  • Error handling on type and code, with retries for 429 and 5xx only.
  • request_id logged with every failed call.
  • An alert on X-Quota-Remaining, or overage switched on.
  • Charts stored, not recomputed, and backfills sent as batches.

Compute this properly, in one request

47 Pythagorean fields from a name and a date of birth, to the conventions described above. 100 charts a month free, no card. Quickstarts for Python and JavaScript.

Get a free key

Keep reading