diff --git a/docs.json b/docs.json index 729fb08..9ec56e2 100644 --- a/docs.json +++ b/docs.json @@ -142,6 +142,20 @@ "integrations/webhooks/event-types", "integrations/webhooks/retry-policies" ] + }, + { + "group": "Nyuchi API", + "icon": "globe", + "expanded": true, + "pages": [ + "integrations/nyuchi-api/overview", + "integrations/nyuchi-api/commerce", + "integrations/nyuchi-api/pay", + "integrations/nyuchi-api/logistics", + "integrations/nyuchi-api/lingo", + "integrations/nyuchi-api/news", + "integrations/nyuchi-api/weather" + ] } ] } diff --git a/integrations/nyuchi-api/commerce.mdx b/integrations/nyuchi-api/commerce.mdx new file mode 100644 index 0000000..d341b91 --- /dev/null +++ b/integrations/nyuchi-api/commerce.mdx @@ -0,0 +1,81 @@ +--- +title: Commerce API +description: Endpoints for BushTrade products, businesses, offers, inquiries, and scam reports. +--- + +The commerce namespace exposes the BushTrade product surface—local businesses, products and offers, buyer inquiries, and scam reports. It is backed by the `mukoko_bushtrade_db` Supabase project. + +Use these endpoints when building consumer or partner experiences that browse listings, accept inquiries, or surface trust signals. + +**Base path:** `/v1/commerce` + +## Endpoints + +| Method | Path | Auth | Purpose | +|--------|------|------|---------| +| `GET` | `/v1/commerce/products` | Optional | List products. Supports `business_id`, `limit`, `offset`. | +| `GET` | `/v1/commerce/products/{product_id}` | Optional | Fetch a single product. | +| `POST` | `/v1/commerce/products` | Required | Create a product owned by the caller. | +| `GET` | `/v1/commerce/businesses` | Optional | List local businesses. | +| `GET` | `/v1/commerce/businesses/{business_id}` | Optional | Fetch a single business. | +| `GET` | `/v1/commerce/offers` | Optional | List offers. Supports `product_id`. | +| `POST` | `/v1/commerce/inquiries` | Required | Send an inquiry against a product or business. | +| `POST` | `/v1/commerce/scam-reports` | Required | Report a product, business, or offer for review. | + +## List products + +```bash +curl "https://api.nyuchi.com/v1/commerce/products?limit=20" +``` + +```json +{ + "data": [ + { "id": "p_01", "name": "Honey 500g", "price": 4.5, "currency": "USD", "business_id": "b_42" } + ], + "count": 1 +} +``` + +## Create a product + +```bash +curl -X POST https://api.nyuchi.com/v1/commerce/products \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Honey 500g", + "description": "Wild forest honey, harvested in Mashonaland.", + "price": 4.5, + "currency": "USD", + "business_id": "b_42" + }' +``` + +The caller's identity is recorded as `created_by` automatically. + +## Submit an inquiry + +Inquiries always belong to the authenticated person. + +```bash +curl -X POST https://api.nyuchi.com/v1/commerce/inquiries \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ "product_id": "p_01", "message": "Do you ship to Bulawayo?" }' +``` + +## Report a scam + +`target_type` must be `product`, `business`, or `offer`. The reporter is recorded automatically. + +```bash +curl -X POST https://api.nyuchi.com/v1/commerce/scam-reports \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ "target_type": "product", "target_id": "p_01", "reason": "Listed at impossible price." }' +``` + + + Row-level security is currently disabled on `commerce.*` tables. The router enforces auth in code today; database policies will replace that enforcement before public release. Treat write endpoints as authenticated-only and do not expose service keys to clients. + diff --git a/integrations/nyuchi-api/lingo.mdx b/integrations/nyuchi-api/lingo.mdx new file mode 100644 index 0000000..f40ccff --- /dev/null +++ b/integrations/nyuchi-api/lingo.mdx @@ -0,0 +1,73 @@ +--- +title: Lingo API +description: Languages, phrases, study sessions, and learner progress for Mukoko Lingo. +--- + +The lingo namespace serves the Mukoko Lingo learning surface—languages, phrases and translations, learner progress, XP, and study session logging. It is backed by the `mukoko_lingo_db` Supabase project. + +Use these endpoints when building learner-facing experiences or analytics tools that read learner progress. + +**Base path:** `/v1/lingo` + +## Endpoints + +| Method | Path | Auth | Purpose | +|--------|------|------|---------| +| `GET` | `/v1/lingo/languages` | Optional | List supported languages. | +| `GET` | `/v1/lingo/phrases` | Optional | List phrases. Supports `language`, `limit`, `offset`. | +| `GET` | `/v1/lingo/phrases/{phrase_id}` | Optional | Fetch a phrase with its translations. | +| `GET` | `/v1/lingo/me/progress` | Required | Return phrase progress for the caller. | +| `GET` | `/v1/lingo/me/xp` | Required | Return XP and level for the caller. | +| `POST` | `/v1/lingo/me/study-sessions` | Required | Log a study session for the caller. | + +## Browse languages + +```bash +curl https://api.nyuchi.com/v1/lingo/languages +``` + +```json +{ + "data": [ + { "code": "sn", "name": "Shona" }, + { "code": "nd", "name": "Ndebele" } + ], + "count": 2 +} +``` + +## Read a phrase with translations + +```bash +curl https://api.nyuchi.com/v1/lingo/phrases/phr_01 +``` + +```json +{ + "id": "phr_01", + "text": "Mangwanani", + "translation": [ + { "language_code": "en", "text": "Good morning" } + ] +} +``` + +## Log a study session + +The session is recorded against the authenticated learner. + +```bash +curl -X POST https://api.nyuchi.com/v1/lingo/me/study-sessions \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "duration_seconds": 600, + "phrases_seen": 24, + "phrases_correct": 18, + "language_code": "sn" + }' +``` + + + Phrase analytics tables (views, engagement, recommendations, stats caches) are populated by the upstream streaming pipeline. The lingo router is read-only for those tables; submit study sessions through `POST /v1/lingo/me/study-sessions` instead of writing to analytics tables directly. + diff --git a/integrations/nyuchi-api/logistics.mdx b/integrations/nyuchi-api/logistics.mdx new file mode 100644 index 0000000..4d1befe --- /dev/null +++ b/integrations/nyuchi-api/logistics.mdx @@ -0,0 +1,63 @@ +--- +title: Logistics API +description: Vehicle, booking, driver, and location endpoints backed by nyuchi_logistics_db. +--- + +The logistics namespace serves the Nyuchi vehicle bookings backend. It exposes vehicles, bookings, drivers, and pickup or drop-off locations from the `nyuchi_logistics_db` Supabase project. + +Use these endpoints to power booking flows in consumer apps and partner integrations. + +**Base path:** `/v1/logistics` + +## Endpoints + +| Method | Path | Auth | Purpose | +|--------|------|------|---------| +| `GET` | `/v1/logistics/vehicles` | Optional | List vehicles. Supports `available`, `limit`, `offset`. | +| `GET` | `/v1/logistics/vehicles/{vehicle_id}` | Optional | Fetch a single vehicle. | +| `POST` | `/v1/logistics/bookings` | Required | Create a booking for the calling customer. | +| `GET` | `/v1/logistics/bookings` | Required | List bookings owned by the caller. | +| `GET` | `/v1/logistics/bookings/{booking_id}` | Required | Fetch a booking owned by the caller. | +| `GET` | `/v1/logistics/locations` | Optional | List pickup and drop-off locations. | + +## Find an available vehicle + +```bash +curl "https://api.nyuchi.com/v1/logistics/vehicles?available=true&limit=10" +``` + +```json +{ + "data": [ + { "id": "v_01", "make": "Toyota", "model": "Hilux", "is_available": true } + ], + "count": 1 +} +``` + +## Create a booking + +The booking is automatically scoped to the authenticated caller via `customer_id`. + +```bash +curl -X POST https://api.nyuchi.com/v1/logistics/bookings \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "vehicle_id": "v_01", + "pickup_location_id": "loc_jhb", + "dropoff_location_id": "loc_hre", + "pickup_at": "2026-06-01T08:00:00Z", + "return_at": "2026-06-05T18:00:00Z", + "notes": "Long-haul rental, second driver included." + }' +``` + +## List my bookings + +`GET /v1/logistics/bookings` only returns rows owned by the caller. Use `limit` and `offset` for pagination. + +```bash +curl "https://api.nyuchi.com/v1/logistics/bookings?limit=20" \ + -H "Authorization: Bearer $TOKEN" +``` diff --git a/integrations/nyuchi-api/news.mdx b/integrations/nyuchi-api/news.mdx new file mode 100644 index 0000000..39633d0 --- /dev/null +++ b/integrations/nyuchi-api/news.mdx @@ -0,0 +1,60 @@ +--- +title: News API +description: Articles, journalists, organisations, and engagement actions for the Mukoko news surface. +--- + +The news namespace exposes the Mukoko news read surface—articles, journalists, and media organisations—plus a small write surface for engagement actions (like, bookmark, comment, follow). It is backed by the `mukoko_news_db` Supabase project. + +Articles and metadata are scored and curated upstream. The router serves the curated read surface to consumer apps and accepts engagement events from authenticated readers. + +**Base path:** `/v1/news` + +## Endpoints + +| Method | Path | Auth | Purpose | +|--------|------|------|---------| +| `GET` | `/v1/news/articles` | Optional | List articles. Supports `organization_id`, `journalist_id`, `limit`, `offset`. | +| `GET` | `/v1/news/articles/{article_id}` | Optional | Fetch a single article. | +| `GET` | `/v1/news/organizations` | Optional | List media organisations. | +| `GET` | `/v1/news/journalists` | Optional | List journalists. Supports `organization_id`. | +| `POST` | `/v1/news/articles/{article_id}/like` | Required | Like an article (idempotent upsert). | +| `POST` | `/v1/news/articles/{article_id}/bookmark` | Required | Bookmark an article (idempotent upsert). | +| `POST` | `/v1/news/comments` | Required | Post a comment on an article. Supports threaded replies via `parent_id`. | +| `POST` | `/v1/news/journalists/{journalist_id}/follow` | Required | Follow a journalist. | +| `POST` | `/v1/news/organizations/{organization_id}/follow` | Required | Follow a media organisation. | + +## List recent articles + +Articles are ordered by `published_at` descending. + +```bash +curl "https://api.nyuchi.com/v1/news/articles?limit=10" +``` + +## Like an article + +Like, bookmark, and follow endpoints are idempotent—calling them twice is safe. The caller's identity is recorded automatically. + +```bash +curl -X POST https://api.nyuchi.com/v1/news/articles/art_01/like \ + -H "Authorization: Bearer $TOKEN" +``` + +## Post a comment + +```bash +curl -X POST https://api.nyuchi.com/v1/news/comments \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "article_id": "art_01", + "text": "Great reporting on this story.", + "parent_id": null + }' +``` + +Set `parent_id` to a comment ID to post a threaded reply. + + + Several `news.*` tables have row-level security disabled. The router enforces auth in code on engagement endpoints; database policies will replace that enforcement before public release. + diff --git a/integrations/nyuchi-api/overview.mdx b/integrations/nyuchi-api/overview.mdx new file mode 100644 index 0000000..a1cc650 --- /dev/null +++ b/integrations/nyuchi-api/overview.mdx @@ -0,0 +1,109 @@ +--- +title: Nyuchi API overview +description: Versioned multi-database gateway that fans out across product surfaces under /v1. +--- + +The Nyuchi API is a single FastAPI gateway hosted at `api.nyuchi.com`. Every product surface is mounted under `/v1//*` and is backed by its own Supabase project, so each product can scale, isolate, and meter independently. A single Stytch-derived platform JWT authorises requests across every namespace. + +Use this guide when you need to call a product surface from a frontend, a server-to-server integration, or a partner application. + +## Base URL and versioning + +| Environment | Base URL | +|-------------|----------| +| Production | `https://api.nyuchi.com` | +| Local development | `http://localhost:8080` | + +All product endpoints live under the `/v1` prefix. The API version is reported by `GET /` in the `api_version` field. Legacy `/api/*` paths from earlier releases no longer resolve—update existing clients to `/v1/*`. + +## Namespace map + +Each namespace maps to a dedicated Supabase project. + +| Namespace | Database | Purpose | +|-----------|----------|---------| +| `/v1/auth`, `/v1/identity`, `/v1/family`, `/v1/organization`, `/v1/api-keys`, `/v1/content`, `/v1/directory`, `/v1/places`, `/v1/travel`, `/v1/events`, `/v1/applications`, `/v1/ubuntu`, `/v1/pipeline`, `/v1/admin`, `/v1/search`, `/v1/media`, `/v1/couch`, `/v1/dashboard` | `nyuchi_platform_db` | Identity, multi-tenancy, places, events, content, business directory, admin | +| `/v1/commerce` | `mukoko_bushtrade_db` | Products, offers, businesses, inquiries, scam reports | +| `/v1/pay/wallet`, `/v1/pay/tokens`, `/v1/pay/gateway` | `nyuchi_pay_db` | Wallets, token lifecycle, fiat on/off-ramps | +| `/v1/logistics` | `nyuchi_logistics_db` | Vehicles, bookings, drivers, locations | +| `/v1/lingo` | `mukoko_lingo_db` | Phrases, languages, study sessions, XP, progress | +| `/v1/news` | `mukoko_news_db` | Articles, journalists, organisations, engagement | +| `/v1/weather` | _(reserved)_ | Placeholder until a weather backend is selected | + +## Authentication + +Every protected endpoint accepts the same platform JWT. Obtain a token from the Stytch-backed auth pipeline at `/v1/auth/*`, then send it on subsequent requests. + +```http +GET /v1/lingo/me/xp HTTP/1.1 +Host: api.nyuchi.com +Authorization: Bearer +``` + +The same token works across every namespace. Some read endpoints accept anonymous calls (`get_optional_user`) and return public data; mutating endpoints require an authenticated caller (`get_current_user`). + +## Configuration status + +`GET /` reports the gateway version and whether each product database is wired up. Use it to confirm what the deployed environment can serve. + +```bash +curl https://api.nyuchi.com/ +``` + +```json +{ + "name": "Nyuchi API", + "version": "4.1.0", + "api_version": "v1", + "namespaces": ["/v1/auth", "/v1/commerce", "/v1/pay", "..."], + "product_dbs": { + "commerce": true, + "pay": false, + "logistics": true, + "lingo": true, + "news": true + } +} +``` + +A `false` entry means the gateway has no credentials for that database. Routers in that namespace return **HTTP 503** at request time so the rest of the gateway keeps working. + + + The pay namespace is configured but its schema is not yet provisioned. Endpoints that read or write data return **HTTP 501** until the schema is deployed. Status endpoints under `/v1/pay/status` and the gateway root remain available. + + +## Configuring product databases + +The gateway reads one environment-variable triplet per database. Set them as Fly secrets before deploying. + +```bash +# Platform DB (legacy names retained for backward compatibility) +SUPABASE_URL=https://.supabase.co +SUPABASE_PUBLISHABLE_KEY=sb_publishable_... +SUPABASE_SECRET_KEY=sb_secret_... + +# Per-product DBs — substitute COMMERCE / PAY / LOGISTICS / LINGO / NEWS +COMMERCE_SUPABASE_URL=https://.supabase.co +COMMERCE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_... +COMMERCE_SUPABASE_SECRET_KEY=sb_secret_... +``` + +Routers depend on the secret key; the publishable key is optional and only used for RLS-scoped clients. + +## Error handling + +| Status | Meaning | +|--------|---------| +| `401 Unauthorized` | Missing or invalid platform JWT on a protected endpoint. | +| `404 Not Found` | Resource does not exist in the namespace's database. | +| `501 Not Implemented` | Endpoint exists but its underlying schema is not provisioned (currently `/v1/pay/*` and `/v1/weather/forecast`). | +| `503 Service Unavailable` | The product database for this namespace is not configured in the running environment. | + +## Next steps + +- [Commerce API](/integrations/nyuchi-api/commerce) — BushTrade product, business, and inquiry endpoints. +- [Pay API](/integrations/nyuchi-api/pay) — wallet, token, and gateway sub-namespaces. +- [Logistics API](/integrations/nyuchi-api/logistics) — vehicle bookings. +- [Lingo API](/integrations/nyuchi-api/lingo) — language learning surface. +- [News API](/integrations/nyuchi-api/news) — articles and engagement actions. +- [Weather API](/integrations/nyuchi-api/weather) — reserved namespace. diff --git a/integrations/nyuchi-api/pay.mdx b/integrations/nyuchi-api/pay.mdx new file mode 100644 index 0000000..18a3f5a --- /dev/null +++ b/integrations/nyuchi-api/pay.mdx @@ -0,0 +1,57 @@ +--- +title: Pay API +description: Wallet, token, and gateway sub-namespaces for the Nyuchi pay backend. +--- + +The pay namespace covers three sub-surfaces under `/v1/pay`. Each one is wired to the `nyuchi_pay_db` Supabase project, but the database schema is not yet provisioned—data endpoints currently return **HTTP 501**. Use the status endpoint to discover readiness without triggering a 501. + +| Sub-namespace | Purpose | +|---------------|---------| +| `/v1/pay/wallet` | User wallets, balances, and transaction history. | +| `/v1/pay/tokens` | Token types and lifecycle stage (MIT, MXT, NST). | +| `/v1/pay/gateway` | Fiat on/off-ramps, deposits, withdrawals, third-party processors. | + +## Check readiness + +`GET /v1/pay/status` is always available. It tells the caller whether the gateway has credentials for the pay database and whether the schema is ready. + +```bash +curl https://api.nyuchi.com/v1/pay/status +``` + +```json +{ + "configured": true, + "schema_ready": false, + "sections": ["wallet", "tokens", "gateway"] +} +``` + +When `configured` is `false`, the gateway has no pay-DB credentials in this environment. When `configured` is `true` but `schema_ready` is `false`, data endpoints return 501 until the schema lands. + +## Endpoints + +| Method | Path | Auth | Status today | +|--------|------|------|---------------| +| `GET` | `/v1/pay/status` | Public | Always live. | +| `GET` | `/v1/pay/wallet/` | Required | 501 — schema pending. | +| `GET` | `/v1/pay/wallet/transactions` | Required | 501 — schema pending. | +| `GET` | `/v1/pay/tokens/` | Required | 501 — schema pending. | +| `GET` | `/v1/pay/tokens/{token_symbol}` | Required | 501 — schema pending. | +| `GET` | `/v1/pay/gateway/providers` | Required | 501 — schema pending. | +| `POST` | `/v1/pay/gateway/deposit` | Required | 501 — schema pending. | +| `POST` | `/v1/pay/gateway/withdraw` | Required | 501 — schema pending. | + + + Build clients against the documented shapes today. When the schema is provisioned, endpoints will switch from 501 to live responses without route changes. + + +## Configuring the pay database + +```bash +PAY_SUPABASE_URL=https://.supabase.co +PAY_SUPABASE_PUBLISHABLE_KEY=sb_publishable_... +PAY_SUPABASE_SECRET_KEY=sb_secret_... +``` + +If these variables are unset, every pay endpoint—including `status`—reports `configured: false`. diff --git a/integrations/nyuchi-api/weather.mdx b/integrations/nyuchi-api/weather.mdx new file mode 100644 index 0000000..1e56c7f --- /dev/null +++ b/integrations/nyuchi-api/weather.mdx @@ -0,0 +1,33 @@ +--- +title: Weather API +description: Reserved namespace for the upcoming weather and forecast surface. +--- + +The `/v1/weather` namespace is reserved for the climate and forecast surface—per-location nowcast, alerts, and seasonal outlooks. The upstream provider has not yet been selected, so only a status endpoint is live today. + +**Base path:** `/v1/weather` + +## Endpoints + +| Method | Path | Auth | Status today | +|--------|------|------|---------------| +| `GET` | `/v1/weather/status` | Public | Always live. Reports `configured: false`. | +| `GET` | `/v1/weather/forecast` | Public | Returns **HTTP 501** until the backend is provisioned. | + +## Check namespace status + +```bash +curl https://api.nyuchi.com/v1/weather/status +``` + +```json +{ + "configured": false, + "namespace": "/v1/weather", + "detail": "weather backend not yet provisioned" +} +``` + + + Build clients against `/v1/weather/forecast` today and they will start returning data when the backend is wired up. No route changes are planned. +