Skip to content

Interpretations

Generates written statements per skill, selecting templates from a versioned library and optionally rewriting them with an LLM in the requested tone.

The same resource also exposes LLM-ready Western interpretation endpoints. These do not ask the model to calculate astrology. The API first builds deterministic grounding from Western calculators, then the LLM writes prose from that JSON. Responses include grounding, features_used, and sources so clients can audit what backed the text.

Create — POST /v1/interpretations

Required scope: interpretations:write

Request

{
    "chart_id": "019e32b5-...",
    "locale": "en",
    "tone": "corporate",
    "use_llm_rewrite": false
}
Field Type Required Notes
chart_id UUIDv7 yes Must belong to the caller's tenant.
locale string no, default "en" BCP-47. Only templates with a matching locale are eligible.
tone enum no, default "corporate" One of corporate, coach, plain, vedic_traditional. Only changes wording when use_llm_rewrite: true.
use_llm_rewrite bool no, default false If true, the configured LLM provider rewrites the template body in the requested tone. Subject to the LLM cost cap.

Response — 201 Created

{
    "id": "019e32cb-...",
    "chart_id": "019e32b5-...",
    "locale": "en",
    "tone": "corporate",
    "statements": [
        {
            "id": "019e32cb-...",
            "skill_id": "resilience",
            "template_id": "resilience-strength-high-en",
            "kind": "strength",
            "locale": "en",
            "body": "Stress tolerance is a standout strength...",
            "score": 0.80,
            "rule_path": ["moon_in_fixed_resilience", "mars_in_fixed_resilience"],
            "created_at": "2026-05-16T22:00:00Z"
        }
    ]
}
Field Type Notes
statements[].kind strength | recommendation | risk Picked by which band the skill score falls into.
statements[].template_id string Stable id of the template chosen. Useful for the feedback loop.
statements[].rule_path string[] The ontology rules that produced the underlying score.

Fetch — GET /v1/interpretations/{id}

Required scope: interpretations:read

Returns the same shape as create.

LLM-ready Western natal — POST /v1/interpretations/natal

Required scope: interpretations:write

{
  "chart_id": "019e32b5-...",
  "language": "en",
  "tier": "standard",
  "fresh": false
}

The grounding includes Western summary, aspects, dignities, balance, natal houses, dispositors, and chart patterns.

LLM-ready Western relationship — POST /v1/interpretations/relationship

Required scope: interpretations:write

{
  "chart_a_id": "019e32b5-...",
  "chart_b_id": "019e32d8-...",
  "language": "en",
  "tier": "standard",
  "fresh": false
}

The grounding includes synastry contacts, bidirectional house overlays, composite/Davison context, and score breakdowns.

LLM-ready Western forecast — POST /v1/interpretations/forecast

Required scope: interpretations:write

{
  "chart_id": "019e32b5-...",
  "starts_at": "2026-01-01T00:00:00Z",
  "ends_at": "2026-01-31T00:00:00Z",
  "language": "en",
  "tier": "standard",
  "fresh": false
}

The grounding includes transit windows, annual profection, forecast themes, and the progressed lunation cycle at the window start.

LLM-ready response

{
  "interpretation_type": "western_natal",
  "language": "en",
  "tier": "standard",
  "content": "The chart is led by a strong air signature...",
  "grounding": {
    "interpretation_type": "western_natal",
    "features_used": [
      {"name": "western.summary", "kind": "deterministic_feature"}
    ],
    "sources": [
      {"name": "/v1/western/charts/{id}/summary", "kind": "api_endpoint"}
    ]
  },
  "features_used": [
    {"name": "western.summary", "kind": "deterministic_feature"}
  ],
  "sources": [
    {"name": "/v1/western/charts/{id}/summary", "kind": "api_endpoint"}
  ],
  "input_tokens": 1200,
  "output_tokens": 480,
  "latency_ms": 900,
  "cost_usd": 0.0021,
  "interpretation_id": "019e4b7a-...",
  "cached": false
}

Use fresh: true to bypass the LLM interpretation cache. Tier rate limits, usage accounting, persistence, and cost caps are shared with the main LLM interpretation layer.

How template selection works

For each skill in the talent profile:

  1. Try strength templates first — picks the one whose band [min, max] contains the score.
  2. If no strength template matches, try recommendation.
  3. If still nothing, try risk.
  4. If the chosen kind has multiple matching templates, sample deterministically by (chart_id, skill_id) so two charts with the same score don't see identical text.

If no template matches at all, the skill is omitted from the response. If every skill is omitted, the use-case returns NoMatchingTemplate (HTTP 422).

Tone caveat — what actually varies

Without use_llm_rewrite: true, the tone parameter is recorded for audit but the template body is returned verbatim. All four tones produce the same surface text. This is intentional — templates are stable, auditable, deterministic. Tone is a styling layer applied by the LLM rewrite pass.

With use_llm_rewrite: true:

Tone Rewrite hint passed to the LLM
corporate "Concise, business-friendly tone suitable for HR reports."
coach "Warm coaching tone, second person."
plain "Plain, jargon-free everyday language."
vedic_traditional "Measured, traditional Vedic-astrologer tone."

The factual claim (which rules fired, which skill, which kind) is preserved across tones — the LLM is instructed to vary phrasing only, not the underlying content. Any deviation triggers an automatic content-faithfulness check before the rewrite is accepted.

Cost considerations

Each use_llm_rewrite: true call generates up to twelve LLM completions (one per skill template). The router fans these out concurrently and records every call in the per-tenant cost ledger.

A typical interpretation costs around $0.01–$0.05 depending on which provider the policy routes to. Set LLM_COST_CAP_PER_HOUR_USD to bound your spend; the cap is enforced before the first call, not after the budget overshoots.