# AI chat on a real chart

A general LLM answers a question about Saturn from what it remembers about the sign. `POST /v1/ai/chat` answers from the chart we just computed: the position, the house, the aspects with their orbs, and the transit windows for the next six months. The difference shows in the first reply: not "Saturn in Capricorn means discipline" but "Saturn in Capricorn 25.2° retrograde, 5th house, conjunct the Moon at an orb of 1.7°".

## Try it without a key

<AiChatDemo lang="en" client:only="react" />

The demo runs on one fixed chart, five questions per address per day, with the same system prompt the paid endpoint uses. No key needed.

## What the model sees

The demo returns a `context` field: the whole block that went into the prompt. Here it is as of 2 September 2026 for the demo chart (transits are recomputed on every request, so tomorrow's list of windows is a different one):

```text
## Natal Chart
- Sun: Taurus 24.4°, house 9
- Moon: Capricorn 26.9°, house 5
- Saturn: Capricorn 25.2° (R), house 5
- Ascendant: Virgo 20.0°
- Midheaven: Gemini 17.1°

Aspects (computed, use these instead of deriving your own):
- Sun Trine Saturn, orb 0.9°, applying
- Moon Conjunction Saturn, orb 1.7°
- Venus Square Neptune, orb 1.6°

## Transits, computed. Today is 2026-09-02; sampled monthly to 2027-03-01
(These are the only windows that exist. Report a month, not a day.)
- transiting Saturn Conjunction natal Venus: in orb on 2026-09-02, 2026-10-01, 2026-11-01, 2026-12-01, 2027-01-01, 2027-02-01, 2027-03-01 (closest 2027-03-01, orb 0.3°)
- transiting Jupiter Square natal Sun: in orb on 2026-10-01, 2026-11-01, 2026-12-01, 2027-01-01, 2027-02-01, 2027-03-01 (closest 2026-11-01, orb 0.0°)
```

The block is abridged here: in full it carries 12 planets and the angles, up to 20 major natal aspects, and up to 12 transit windows. The same block is assembled for the paid endpoint from the chart you send.

## What it dates and what it will not

Our system prompt lets the model name months for the transits in the block above, and forbids it from dating an event. Asked "when am I likely to get married", the endpoint answers like this (an excerpt from a real reply on 2 September 2026):

> **Transiting Saturn Conjunction natal Venus:** This transit is in orb from September 2026 through March 2027, becoming closest in March 2027. Saturn here brings a focus on commitment, structure, and long-term planning to your relationships. It's a period where you might seriously evaluate your partnerships and define what you truly desire for the future.

The dates are not invented: that is the `transiting Saturn Conjunction natal Venus` row from the context block. A date for the marriage is not in the reply and will not be.

<Aside type="note">
If you are building a product where the answer is your responsibility, that line works for you: a dated prediction from somebody else's model inside your interface is your risk, not ours. Need an exact window instead of a month: [`/v1/transit-calendar`](/docs/api/).
</Aside>

## Personas

`persona` switches the voice, not the data. The values are a closed set, because a string from the request body reaches the system prompt.

| `persona` | Voice |
|---|---|
| `astrologer` | the default, the way the endpoint answered before the parameter existed |
| `plain` | no persona, no greeting, no sign-off |
| `coach` | support, and what to do with it |
| `teacher` | names the technique and defines the terms |

Asked "Describe my Saturn in one paragraph" with `persona: "coach"`:

> Your Saturn in Capricorn, retrograde in the 5th house, suggests a deep-seated sense of responsibility and a structured approach to self-expression, creative pursuits, romance, and potentially children. With Saturn being retrograde, you might find yourself internalizing lessons about discipline and boundaries in these areas, perhaps re-evaluating your approach to fun and passion over time.

And with `persona: "teacher"`:

> Your natal Saturn is in Capricorn at 25.2° in the 5th house and is retrograde. **Saturn** represents discipline, responsibility, structure, and where you seek mastery through effort. In its domicile sign of **Capricorn**, a cardinal earth sign, Saturn's qualities are amplified, suggesting a natural inclination towards ambition, practicality, and building lasting structures.

An unknown persona is a `400 INVALID_INPUT` listing the values it accepts, not a silent default.

## Request and response

<Tabs>
  <TabItem label="cURL">
    ```bash frame="terminal"
    curl -X POST https://api.astroway.info/v1/ai/chat \
      -H "X-Api-Key: aw_live_your_key_here" \
      -H "Content-Type: application/json" \
      -d '{
        "message": "Що означає моє положення Сатурна?",
        "chart": {
          "date": "1990-05-15",
          "time": "14:30:00",
          "timezoneOffset": 3,
          "latitude": 50.45,
          "longitude": 30.52
        },
        "persona": "plain",
        "language": "uk"
      }'
    ```
  </TabItem>
  <TabItem label="Node.js">
    ```ts
    const r = await fetch('https://api.astroway.info/v1/ai/chat', {
      method: 'POST',
      headers: {
        'X-Api-Key': process.env.ASTROWAY_API_KEY!,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        message: 'Що означає моє положення Сатурна?',
        chart: { date: '1990-05-15', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
        persona: 'plain',
        language: 'uk',
      }),
    });
    const { data } = await r.json();
    console.log(data.reply);
    ```
  </TabItem>
  <TabItem label="Python">
    ```python

    r = requests.post(
        'https://api.astroway.info/v1/ai/chat',
        headers={'X-Api-Key': os.environ['ASTROWAY_API_KEY'], 'Content-Type': 'application/json'},
        json={
            'message': 'Що означає моє положення Сатурна?',
            'chart': {'date': '1990-05-15', 'time': '14:30:00', 'timezoneOffset': 3, 'latitude': 50.45, 'longitude': 30.52},
            'persona': 'plain',
            'language': 'uk',
        },
    )
    data = r.json()['data']
    print(data['reply'])
    ```
  </TabItem>
  <TabItem label="PHP">
    ```php
    <?php
    use GuzzleHttp\Client;

    $aw = new Client(['base_uri' => 'https://api.astroway.info/v1/']);
    $r = $aw->post('ai/chat', [
        'headers' => ['X-Api-Key' => getenv('ASTROWAY_API_KEY')],
        'json' => [
            'message' => 'Що означає моє положення Сатурна?',
            'chart' => ['date' => '1990-05-15', 'time' => '14:30:00', 'timezoneOffset' => 3, 'latitude' => 50.45, 'longitude' => 30.52],
            'persona' => 'plain',
            'language' => 'uk',
        ],
    ]);
    $data = json_decode($r->getBody(), true)['data'];
    echo $data['reply'];
    ```
  </TabItem>
</Tabs>

The response:

```json
{
  "ok": true,
  "data": {
    "reply": "Ваш Сатурн знаходиться у знаку Козерога, у 5 домі, і є ретроградним.\n\n**Сатурн у Козерозі** означає, що Сатурн перебуває у своєму домі, де його енергії найсильніші. […] **Місяць у поєднанні з Сатурном (орб 1.7°)**: Це поєднання в Козерозі, у 5 домі, посилює серйозність ваших емоцій та потребу в безпеці.",
    "disclaimer": "Цей текст згенерований ШІ для розваги та саморефлексії. Не є медичною, юридичною чи фінансовою порадою.",
    "model": "gemini-2.5-flash",
    "language": "uk",
    "tokens": { "input": 1822, "output": 758 },
    "duration_ms": 6806,
    "persona": "plain"
  }
}
```

`reply` is abridged here, the rest of the fields are as they came. `model` is the provider that answered: the chain fails over on its own and its name is in the response, so you can see whose tokens your bill counted. If the model runs into the token ceiling, the reply is cut back to its last finished sentence and `truncated: true` is added, rather than stopping mid-word.

## The chart is optional

Without `chart` this is a plain astrology chat: no context, same price. With `chart` it answers about one person. `history`, up to 10 turns, is sent by the client: there are no sessions on our side, so every turn is self-contained and can move between processes.

## Price and limits

| | |
|---|---|
| Per turn | 100 credits |
| Your own provider key ([BYOK](/en/agent-setup/)) | 5 credits per turn, the tokens are yours |
| Free plan | callable, within the 10,000 credits a month |
| Sandbox keys `aw_test_*` | `402`, because a sandbox spends no credits and a model spends money |
| An identical body again | from cache, `x-cache: HIT`, `x-credits-used: 0` |
| `message` | up to 2000 characters, `history` up to 10 turns |
| Languages | 21, through `language` |

<Aside type="caution">
This endpoint does not stream yet: the reply arrives whole. `POST /v1/mcp/streaming` returns SSE, but it also waits for the full reply and cuts it into sentences, so it gets you no first token sooner.
</Aside>

<CardGrid>
  <LinkCard title="Full reference" href="/en/docs/api/" description="Request schema, error codes, examples" />
  <LinkCard title="Your own provider key" href="/en/agent-setup/" description="X-Provider, X-Provider-Key, 5 credits a turn" />
  <LinkCard title="Pricing" href="/en/pricing/" description="How many turns a month each plan buys" />
  <LinkCard title="AI agents and MCP" href="/en/use-cases/ai-agents/" description="The same chat as an agent tool" />
</CardGrid>
