# Giáo Án 24h

> Vietnamese digital-education marketplace (https://giaoan24h.com) selling K-12 lesson
> plans (giáo án), slide decks, teaching videos, and classroom music as
> instantly downloadable files after payment.

## When to use this

Use the public API when your job is to:

- Discover Vietnamese teaching content metadata - lesson plans (`/giao-an`),
  slides (`/slide`), videos (`/video`), classroom music (`/nhac-nen`) and
  bundles (`/combo`) - including titles, descriptions, prices in VND, and
  category placement, via `GET https://giaoan24h.com/api/v1/catalog/products/{fullPath}`
  and `GET https://giaoan24h.com/api/v1/catalog/categories/{...path}`.
- Search the catalog by keyword via `GET https://giaoan24h.com/api/v1/search?q=...`.
- Check current availability and pricing before recommending a resource.
- Create an order on behalf of an authenticated user and poll its payment
  status via `POST https://giaoan24h.com/api/v1/checkout` and
  `GET https://giaoan24h.com/api/v1/checkout/{orderId}` until it reports a terminal state.
- Understand how authentication works before calling anything:
  read `https://giaoan24h.com/auth.md`.

## When not to use

- Do not scrape asset binaries. Previews are deliberately watermarked and
  full files are served only through short-lived signed URLs granted after a
  real purchase; bulk-fetching assets violates the terms of service.
- There is no admin API access for third parties. All `/api/v1/admin/*`
  routes require staff sessions and are out of scope.
- Do not automate the human checkout flow itself: completing payment needs
  an interactive browser session (payment provider pages). The API creates
  and tracks orders; it does not complete payments for you.
- Account management (profile, sessions, data export) is a logged-in
  storefront feature, not a third-party API surface.

## Endpoints

Base URL: `https://giaoan24h.com/api/v1` unless noted. Full request/response schemas:
`https://giaoan24h.com/openapi.json`.

- `GET https://giaoan24h.com/api/health` - liveness/readiness probe (no auth).
- `GET https://giaoan24h.com/api/v1/catalog/products/{fullPath}` - product detail (no auth).
- `GET https://giaoan24h.com/api/v1/catalog/categories/{...path}` - category listings (no auth).
- `GET https://giaoan24h.com/api/v1/search` - keyword search (no auth, IP rate-limited).
- `POST https://giaoan24h.com/api/v1/checkout` - create an order (user session required;
  guest checkout with explicit consent where enabled).
- `GET https://giaoan24h.com/api/v1/checkout` - list the user's orders (session).
- `GET https://giaoan24h.com/api/v1/checkout/{orderId}` - poll one order's status (owner
  session, or the short-lived per-order access cookie issued at creation).
- `POST https://giaoan24h.com/api/v1/promos/validate` - validate a promo code against a product (session).
- `GET https://giaoan24h.com/api/v1/topup/denominations` - wallet top-up amounts (no auth).
- `POST https://giaoan24h.com/api/v1/topup/orders` - create a wallet top-up order (session, same-origin).
- `GET https://giaoan24h.com/api/v1/topup/orders/{id}` - poll a top-up order (session).
- `POST https://giaoan24h.com/api/v1/topup/promos/validate` - validate a top-up promo code (session).
- `GET https://giaoan24h.com/api/v1/wallet/balance` - main + bonus wallet balance (session).
- `GET https://giaoan24h.com/api/v1/wallet/ledger` - paginated wallet ledger (session).
- `POST https://giaoan24h.com/api/v1/giftcode/redeem` - redeem a gift code into the wallet (session).
- `GET https://giaoan24h.com/api/v1/music/quota` - classroom-music download quota (session).
- `POST https://giaoan24h.com/api/v1/music/{id}/download` - request a music download (session, same-origin; quota enforced).
- `POST https://giaoan24h.com/api/v1/downloads/by-token` - exchange a short-lived download token for a file URL (token grant).

Not part of the third-party contract: `/api/v1/account/*`, `/api/v1/admin/*`,
`/api/v1/chat/*`, `/api/v1/support/*`, `/api/v1/dmca/inbound`,
`/api/v1/theft/report` (storefront-session or internal surfaces).

## Docs

- [API reference](https://giaoan24h.com/api-docs) - human-readable documentation.
- [OpenAPI 3.1 spec](https://giaoan24h.com/openapi.json) - machine-readable schemas.
- [Developer portal](https://giaoan24h.com/developers) - versioning, deprecation and rate-limit policy.
- [Authentication](https://giaoan24h.com/auth.md) - how session-based access works.
- [This file](https://giaoan24h.com/llms.txt).
- [API catalog](https://giaoan24h.com/.well-known/api-catalog) - RFC 9727 linkset.
- [Protected-resource metadata](https://giaoan24h.com/.well-known/oauth-protected-resource) - RFC 9728.
- [Sitemap](https://giaoan24h.com/sitemap.xml).

## Auth

There is no OAuth authorization server. Access uses an HMAC-signed,
http-only session cookie (`better-auth.session_data`) obtained by signing
in through the website; mutating requests are additionally same-origin
checked. Anonymous reads need no credentials. Details and scope mapping:
[https://giaoan24h.com/auth.md](https://giaoan24h.com/auth.md).

## Policies

### Versioning & deprecation

The API is URL-versioned: the current contract lives under the `/api/v1`
prefix, and breaking changes ship under a new version prefix instead of
changing v1 in place. The full policy is published on
[the developers page](https://giaoan24h.com/developers).

Deprecated endpoints are announced on that page and flagged on every response
during the notice window with the standard headers:
- `Deprecation: @<unix-timestamp>` (RFC 9745) - when the endpoint was deprecated;
- `Sunset: <HTTP-date>` (RFC 8594) - when support ends.

A deprecated endpoint keeps working for at least 6 months after the
`Deprecation` header first appears, before its `Sunset` date is reached.

### Rate limits

Rate-limited endpoints report their budget on every response with the
standard RFC 9331 header fields:
- `RateLimit-Limit` - requests allowed per window;
- `RateLimit-Remaining` - requests left in the current window;
- `RateLimit-Reset` - seconds until the window resets.

When a limit is exceeded you get `HTTP 429` with the standard API error body
(`error.code = "rate_limited"`, see the `ErrorResponse` schema in
`https://giaoan24h.com/openapi.json`) plus a `Retry-After` header telling you how many
seconds to wait. Back off and retry after that interval instead of hammering
the endpoint.
