# URL conventions and free endpoints

If you're seeing 404s on what should be a routine request — it's almost always a wrong prefix or you're looking for Swagger UI at a non-standard path. This page documents every canonical URL and alias.

## Path prefix

**All endpoints live under `/v1/`.** No other prefix is accepted.

```
✅ https://api.astroway.info/v1/chart
✅ https://api.astroway.info/v1/health
❌ https://api.astroway.info/api/chart        — 404 (missing /v1/ prefix)
❌ https://api.astroway.info/api/v1/chart     — 404 (our internal path, not exposed)
❌ https://api.astroway.info/v1/v1/chart      — 308 redirect to /v1/chart (typical SDK base-URL bug fix)
```

If you accidentally hit `/api/<endpoint>`, we return `404` with `error.code = "WRONG_PREFIX"` and a hint — your SDK can intercept this and surface the correct path.

## Not an LLM proxy

AstroWay is an **astrology calculations API**, not an LLM proxy. If you arrive with OpenAI SDK muscle memory and try to just swap `base_url` to ours — it won't work:

```
❌ POST /v1/chat/completions            — doesn't exist
❌ POST /v1/completions                 — doesn't exist
❌ GET  /v1/models                      — doesn't exist (deliberately)
❌ POST /v1/embeddings                  — doesn't exist
```

We don't publish the AI provider list for two reasons:

1. **Not actionable for integrators.** You call `/v1/interpret/natal` or `/v1/horoscope/daily` — our server picks an LLM from a rotated fallback chain (Gemini → Groq → Cerebras → SambaNova → Mistral → …) on its own. Swapping providers doesn't change the response shape, only latency and occasional rewording.
2. **Operational freedom.** The chain changes without warning (we removed HuggingFace 2026-05-18, added NIM/ZAI). If we declared a fixed `models[]` it would become a de-facto contract.

**AI is present purely as an implementation detail** in `/v1/interpret/*` (natal, synastry, transits), `/v1/horoscope/*` (daily/weekly forecasts), `/v1/dev-assistant` (docs helper) and `/v1/reports/*` (PDF narratives). The remaining **400+** endpoints are deterministic Swiss Ephemeris, no AI involved.

## OpenAPI 3.1 spec

The canonical URL is **`/v1/openapi.json`**. For integration convenience we accept these aliases:

| Alias | Where | Why |
|---|---|---|
| `/v1/swagger.json` | 301 → `/v1/openapi.json` | Swagger 2.0 / openapi-generator default |
| `/v1/api-docs/swagger.json` | 301 → `/v1/openapi.json` | springdoc default |
| `/v1/v3/api-docs` | 301 → `/v1/openapi.json` | Spring Boot 3 |
| `/v1/v2/api-docs` | 301 → `/v1/openapi.json` | Spring Boot 2 |
| `/v1/swagger/v1/swagger.json` | 301 → `/v1/openapi.json` | ASP.NET Core |
| `/v1/swagger`, `/v1/swagger-ui`, `/v1/swagger-ui.html` | 302 → `/v1/docs` | Swagger UI host |

**Interactive Swagger UI** lives at `/v1/docs` (also mirrored in the browseable docs at [/docs/api/](/docs/api/)).

## Free system endpoints

These paths **require no API key and don't burn credits** — call them from any frontend, monitor, or health-check.

| Path | Returns |
|---|---|
| `GET /v1/health` | `{status, version, uptime_seconds, timestamp}` — fast liveness probe |
| `GET /v1/health/deep` | Per-DB reachability check (for UptimeRobot / Pingdom), 503 if any DB is down |
| `GET /v1/version` | `{version, build_commit, started_at, uptime_seconds, docs_url}` — SDK self-check |
| `GET /v1/openapi.json` | Full OpenAPI 3.1 spec with examples + `x-codeSamples` |
| `GET /v1/docs` | Interactive Swagger UI |
| `GET /v1/reference/*` | Canonical reference data (signs, planets, houses, aspects) — IP-rate-limited, no key |
| `GET /v1/i18n/langs`, `GET /v1/i18n/dict/:lang` | Language list + UI dictionaries — for widgets |

## Free endpoints that require an account

Account endpoints accept **a JWT** (issued at login) but **don't deduct credits** from your plan balance.

| Prefix | What |
|---|---|
| `/v1/auth/*` | Register, login, refresh, password reset |
| `/v1/me`, `/v1/me/*` | Profile, usage stats, recent calls |
| `/v1/keys`, `/v1/keys/*` | API key management |
| `/v1/admin/*` | Admin panel (requires `api_role = admin`) |
| `/v1/messages` | Feedback widget submissions (anonymous, rate-limited) |
| `/v1/dev-assistant`, `/v1/dev-assistant/stream` | AI docs assistant (anonymous, separate quota) |
| `/v1/widget-config` | Runtime feature-flags for the widget |
| `/v1/embed/*` | Embeddable iframe widgets (IP-rate-limited) |
| `/v1/oauth/*` | Google / GitHub login |
| `/v1/books/*` | Birth Book — separate scoped JWT (issued by WordPress mu-plugin) |

## Paid calculation endpoints

All **astrology calculations** deduct credits from your plan. Exact per-endpoint cost is on [Per-endpoint Cost](/en/credits/). Summary:

| Tier | Credits | Examples |
|---|---|---|
| **½** | 5 | `/v1/reference/*`, static lookups |
| **1** | 10 | `/v1/planets`, `/v1/sun-times`, `/v1/moon-phase` |
| **2** | 20 | `/v1/chart`, `/v1/harmonics`, `/v1/horary` |
| **3** | 50 | `/v1/synastry`, `/v1/progressions`, `/v1/acg` |
| **4** | 100 | `/v1/transit-calendar`, `/v1/group-synastry` |
| **5** | 250 | `/v1/rectification/trutine` |
| **6** | 500 | `/v1/rectification` |
| **7** | 5000 | PDF reports (`/v1/reports/*`) |

**Cache discounts:** `X-Cache: HIT` (5-min idempotency cache) — 0 credits. AI endpoints (`/interpret/*`) — 50% off on cache hit.

**Response headers** include `X-Credits-Used`, `X-Credits-Remaining`, `X-Credits-Limit` — your SDK can track balance automatically.

## API versioning

Major version in the URL (`/v1/`). Breaking changes only ship as `/v2/`, never in-place. Details — [Versioning](/en/versioning/).

`GET /v1/version` returns the current deploy:

```bash
curl https://api.astroway.info/v1/version
# {
#   "version": "2.71.0",
#   "build_commit": "abc1234",
#   "started_at": "2026-05-27T10:42:00Z",
#   "uptime_seconds": 12345,
#   "docs_url": "https://api.astroway.info/docs/api/"
# }
```

SDKs can call this on boot for debugging "why is the behaviour suddenly different" — the `build_commit` field uniquely identifies the deploy.

## Most-common integrator mistakes

From 90 days of prod logs, the top 5 integration mistakes we see:

1. **`/api/<endpoint>`** instead of `/v1/<endpoint>` — WordPress wp-json muscle memory. We now return JSON 404 with a hint.
2. **`/v1/v1/<endpoint>`** — SDK configured with `baseUrl = .../v1` and the call adds `/v1/X` on top. Now 308 redirected.
3. **`/swagger.json`** instead of `/v1/openapi.json` — Postman/Insomnia auto-probe. Now 301 redirected.
4. **`/v1/me`, `/v1/auth/keys/me`** without `Authorization: Bearer <jwt>` → 401. Check that the token reaches the header.
5. **`/v1/embed/natal`** with an API key instead of an embed token → 401. Embed endpoints accept the **public embed token** from the [dashboard](https://api.astroway.info/dashboard/embeds), not your API key.

## Related

- [Quick Start](/en/getting-started/) — first request in 5 minutes
- [Authentication](/en/authentication/) — JWT, API keys, embed tokens
- [Per-endpoint Cost](/en/credits/) — exact credit table
- [Errors](/en/errors/) — error code reference
- [OpenAPI 3.1](/v1/openapi.json) — full spec
