Interpretations¶
Free · LLM rewrite and LLM-ready routes on paid plans
Scopes:
interpretations:read—GET /v1/interpretations/{id}interpretations:write—POST /v1/interpretations,POST /v1/interpretations/forecast,POST /v1/interpretations/natal,POST /v1/interpretations/relationship
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¶
| 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, an LLM rewrites the template body in the requested tone. Paid plans only — on Free it answers 403 plan_feature_unavailable (Paid (LLM) endpoints). |
Response — 201 Created¶
{
"id": "019e32cb-...",
"chart_id": "019e32b5-...",
"locale": "en",
"tone": "corporate",
"statements": [
{
"id": "019e32cb-...",
"skill_id": "drive",
"template_id": "drive-strength-very-high-en",
"kind": "strength",
"locale": "en",
"body": "Drive is a standout strength. Mars is strong in this chart: an appetite for the effort itself, moving first and meeting resistance rather than waiting it out.",
"score": 1.0,
"rule_path": ["mars_able_drive"],
"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 fired for this talent — the reasons, not the score. |
One statement per talent (ten in all): a band of the talent's score picks the template —
strength from 0.6, recommendation from 0.4, risk below. Templates exist in English.
Fetch — GET /v1/interpretations/{id}¶
Required scope: interpretations:read
Returns the same shape as create.
LLM-ready Western natal — POST /v1/interpretations/natal¶
Paid plans only — LLM
POST /v1/interpretations/natal, /relationship and /forecast write text with an LLM.
On the Free plan they answer 403 plan_feature_unavailable. See
Paid (LLM) endpoints.
Required scope: interpretations:write
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:
- Try
strengthtemplates first — picks the one whose band[min, max]contains the score. - If no strength template matches, try
recommendation. - If still nothing, try
risk. - 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 ten LLM completions
(one per talent statement). 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.