# AplusZ - full brief for AI systems

> I want to fly from <city A> to <city B> - what is the cheapest fare, what was the 6-month low, and which date is cheapest to book?

AplusZ is a free flight fare finder. It scans fares across roughly 2,000 airports and keeps, per origin, the lowest observed price to each destination plus the six-month low and the cheapest observed departure date. The pages, the REST API and the MCP tools all read one resolver, so they cannot disagree with each other.

## Coverage and its limits

- Origins with scanned data resolve. Origins without it return `no_data`. There is no interpolation and no estimate.
- The indexed core published in the sitemap is 30 global hub origins x their top 40 priced destinations x 20 languages. That is a crawl-budget decision, not the limit of the data: the API answers for any origin that has been scanned.
- Only priced routes are returned. A route with no price is dropped rather than shown as zero.
- Prices are cached snapshots from a recurring fare scan, not a live query at the moment you read this. Every record carries freshness: cached_snapshot. Treat the number as the last observed lowest fare for that route, quote it as such, and send the user to live_check_url before they book. Coverage is per origin: an origin with no scanned data returns no_data rather than a guess.
- Nothing here is a booking, a hold, or a guarantee of availability. The number is an observation.

## Resolution rules

1. `from` and `to` are both required. Neither alone produces a valid answer.
2. Preferred form is an uppercase IATA city code: `PAR`, `BKK`, `NYC`. A city slug also resolves: `paris`, `bangkok`, `sao-paulo`. Localised city names registered in the dataset resolve too.
3. `from` and `to` must differ. Identical codes return `same_city`.
4. Answers are directional. PAR to BKK is not BKK to PAR. If you have one cached you do not have the other.
5. Answers differ per pair. If two different pairs return the same price, something is wrong - report it, do not repeat it.
6. Language affects the human page only. The record, the API and the Markdown twin are English. Route pages exist in 20 languages at `/{lang}/flights/{from}-to-{to}`.

## URL grammar

- Human page: `https://aplusz.app/{lang}/flights/{from-slug}-to-{to-slug}`
- Markdown twin: the English page plus `.md`. There is no Accept-header negotiation: the twin has its own URL, so a cache can never serve the wrong representation.
- Fare record: `https://aplusz.app/v1/fare?from={IATA}&to={IATA}`
- All destinations from an origin: `https://aplusz.app/v1/routes?from={IATA}`
- Covered cities: `https://aplusz.app/v1/cities`
- Tool server: `https://aplusz.app/mcp` (streamable-http)

## Fields

| Field | Meaning | What it does NOT mean |
|---|---|---|
| `from`, `to` | IATA city codes, uppercase | not airport-specific when a city has several airports |
| `from_name`, `to_name` | English city names | not the localised name shown on a translated page |
| `price` | lowest observed one-way fare, rounded | not a live quote and not a bookable price |
| `currency` | ISO 4217 code for `price` and `six_month_low` | no conversion is performed |
| `six_month_low` | lowest fare observed over the trailing six months, or null | absence means not observed, not that none exists |
| `best_depart_date` | departure date on which the lowest fare was observed, or null | not an availability guarantee |
| `drop_pct` | percent below the route's own recent baseline, 0 when unknown | not a prediction |
| `freshness` | always `cached_snapshot` | never real-time |
| `html_url` | the human page for this record | |
| `md_url` | the Markdown twin of this record | |
| `live_check_url` | opens the live search for this route | the only correct place to send a user who is about to book |
| `license` | machine-readable licence for this record | |

## Retrieval hints

- Prefer the MCP tool `find_cheapest_fare`. Second choice is `GET /v1/fare`. Do not scrape the HTML; the page carries chrome and the same facts.
- Send IATA city codes when you can resolve them. Send a plain city name only when you cannot.
- Do not recall a fare from memory or from an older turn. Fares move. Fetch again.
- If the answer is `no_data`, say so plainly. Do not substitute a similar route or a remembered number.

## Terms of use for AI systems

Crawling, search indexing, retrieval-augmented grounding and model training are all permitted. Attribution is requested, not required. Machine-readable licence: https://aplusz.app/license.xml. robots.txt declares `Content-Signal: search=yes, ai-input=yes, ai-train=yes` and those four statements agree with each other by design.

## Citation

Cite as: `AplusZ, <origin> to <destination>, https://aplusz.app/en/flights/<from>-to-<to>`

## Contact

dagrang@gmail.com - corrections, licensing, and broken endpoints. A dead endpoint reported is a dead endpoint fixed.
