# Hinabi Developer & Platform Reference > Full system reference for AI coding assistants, LLMs, and third-party developers integrating with Hinabi. ## Overview Hinabi (https://hinabi.app) is a methodology-agnostic study tracker and analytics platform for language learners. It provides a distraction-free flow-state UI for tracking active and passive immersion time, spaced repetition (SRS) reviews, and skill balancing across six core competencies: Reading, Listening, Speaking, Writing, Grammar, and Vocabulary. Hinabi provides an official Public Ingestion & Developer REST API enabling browser extensions (e.g. Yomitan), e-readers, video watchers, podcast trackers, and SRS tools (e.g. Anki) to automatically log study activity into learner profiles and streak dashboards. - **Developer Documentation (Scalar)**: https://hinabi.app/docs - **Interactive OpenAPI 3.1 Spec**: https://api.hinabi.app/v3/api-docs/public - **API Key Management**: https://hinabi.app/settings?tab=api - **Official Anki Add-on (Hinabi Aniki)**: https://ankiweb.net/shared/info/169626114 (GitHub: https://github.com/DennySesay/Hinabi-Aniki) --- ## Authentication & Headers Authenticate all requests to `https://api.hinabi.app` using an API key generated in Hinabi Settings. Keys can be supplied via either header: ```http X-API-Key: hn_live_abc123... ``` or ```http Authorization: Bearer hn_live_abc123... ``` ### Key Security & Expiration - **HMAC-SHA256 Hashing**: API keys are hashed and peppered on the server; the raw key is only shown once at creation time. - **Sliding Inactivity Expiration**: Keys can be configured with an inactivity window (e.g. 90 days) that automatically extends on active use, or set to never expire (recommended for personal plugins). --- ## Scopes Architecture Hinabi enforces a strict least-privilege permissions model: | Scope | Type | Description | |---|---|---| | `LOGS_WRITE` | Public (Default) | **Write-only default**. Can submit log entries, study time, and SRS review cards. Has zero read access to past history—if a key leaks from local configuration, an attacker cannot scrape personal study history. | | `META_READ` | Public (Optional) | Read list of configured language names and active goal titles to populate dropdown selectors in extension configuration UIs. | | `LOGS_READ` | Restricted | Full read access to historical study logs and streaks. Reserved for official Hinabi apps and enterprise partners. | | `ANALYTICS_READ` | Strictly Private | Proprietary mental model analytics, retention forecasts, heatmaps, and streak matrices. Reserved for Hinabi Web. | Self-service API keys only permit `LOGS_WRITE` and `META_READ`. Requests for restricted scopes are rejected with HTTP 400. --- ## Rate Limiting The API uses a token bucket rate limiter (Bucket4j) keyed by API key: - **Free Tier**: 60 requests/minute + 10 burst capacity. - **Pro Tier**: 300 requests/minute + 30 burst capacity. Response headers returned with every API call: - `X-RateLimit-Limit`: Maximum tokens in the bucket. - `X-RateLimit-Remaining`: Remaining available tokens. - `X-RateLimit-Reset`: Milliseconds until the bucket refills. When exhausted, the server responds with `HTTP 429 Too Many Requests` and a `Retry-After: ` header. --- ## Endpoints Reference ### 1. Log Study Activities (Single or Batch) **`POST /api/v1/public/ingest/logs`** *Requires scope: `LOGS_WRITE`* The standard endpoint for logging reading, listening, video immersion, speaking, or custom study sessions. #### Request Body (`application/json`): ```json { "logs": [ { "date": "2026-09-06", "timeSpentMinutes": 35, "activityName": "Reading Light Novel", "languageName": "Japanese", "materialName": "Ascendance of a Bookworm Vol. 1", "startTime": "14:30", "notes": "Finished chapter 4; 8 vocabulary lookups", "externalId": "reader_session_unique_id_101" } ] } ``` #### Fields Description: - `date` *(string, required)*: Study date in ISO format (`YYYY-MM-DD`). - `timeSpentMinutes` *(integer, required)*: Active study duration in minutes (minimum 1). - `activityName` *(string, required)*: Human-readable name of the activity (e.g. `"Reading Light Novel"`, `"Anime Immersion"`, `"Podcast Listening"`). - `languageName` *(string, optional)*: Target language. Defaults to the user's primary language if omitted. - `materialName` *(string, optional)*: Title of book, show, podcast, or deck studied. Automatically linked or created. - `startTime` *(string, optional)*: Time of day in `HH:mm` format for time-of-day heatmap distribution. - `notes` *(string, optional)*: Study notes, reflection, page counts, or chapter numbers. - `externalId` *(string, optional)*: Client-side unique ID for automatic deduplication. If a request is retried, duplicate logs are safely ignored. #### Response (`HTTP 200 OK`): ```json { "status": "success", "syncedCount": 1, "ignoredDuplicates": 0, "todayLoggedMinutes": 35, "currentStreakDays": 14, "viewUrl": "https://hinabi.app/home" } ``` --- ### 2. Timed Session Ingestion **`POST /api/v1/public/ingest/sessions`** *Requires scope: `LOGS_WRITE`* Records timed study sessions with start/end timestamps and language skills. #### Request Body: ```json { "startedAt": "2026-09-06T14:00:00Z", "endedAt": "2026-09-06T14:30:00Z", "durationSeconds": 1800, "tool": "Yomitan", "skills": ["READING", "VOCABULARY"], "externalId": "sess_89a3c_20260906" } ``` #### SRS / Flashcard Fields (Optional): For spaced repetition flashcard tools (like Anki), these optional fields can be included: - `totalReviews` *(integer, optional)*: Total cards reviewed. - `newCards` *(integer, optional)*: Brand new cards learned. - `lapses` *(integer, optional)*: Forgotten cards (graded "Again"). *For general immersion, reading, or video watching, leave these fields `null` or omit them.* --- ### 3. Read User Languages **`GET /api/v1/public/meta/languages`** *Requires scope: `META_READ`* Returns the user's active configured target languages to populate extension dropdowns. #### Response: ```json [ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "Japanese", "archived": false } ] ``` --- ### 4. Read User Goals **`GET /api/v1/public/meta/goals`** *Requires scope: `META_READ`* Returns the user's active study goals. #### Response: ```json [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "title": "Daily Immersion", "targetMinutes": 60 } ] ``` --- ## Code Examples ### Python (using `requests`) ```python import requests API_KEY = "hn_live_your_secret_key_here" BASE_URL = "https://api.hinabi.app" payload = { "logs": [ { "date": "2026-09-06", "timeSpentMinutes": 45, "activityName": "Podcast Immersion", "languageName": "Japanese", "materialName": "Nihongo con Teppei", "notes": "Episodes 15-18", "externalId": "podcast_sync_20260906_1" } ] } response = requests.post( f"{BASE_URL}/api/v1/public/ingest/logs", headers={ "X-API-Key": API_KEY, "Content-Type": "application/json" }, json=payload ) if response.status_code == 200: data = response.json() print(f"Logged! Today's total: {data['todayLoggedMinutes']}m | Streak: {data['currentStreakDays']} days") else: print(f"Failed ({response.status_code}):", response.text) ``` ### JavaScript / TypeScript (`fetch`) ```typescript const API_KEY = "hn_live_your_secret_key_here"; async function logStudyTime(minutes: number, activity: string, material?: string) { const today = new Date().toISOString().slice(0, 10); const res = await fetch("https://api.hinabi.app/api/v1/public/ingest/logs", { method: "POST", headers: { "X-API-Key": API_KEY, "Content-Type": "application/json", }, body: JSON.stringify({ logs: [ { date: today, timeSpentMinutes: minutes, activityName: activity, materialName: material, externalId: `client_log_${Date.now()}`, }, ], }), }); if (!res.ok) { throw new Error(`Hinabi API error: ${res.statusText}`); } const result = await res.json(); console.log(`Synced with Hinabi! Streak: ${result.currentStreakDays} days 🔥`); return result; } ``` ### cURL ```bash curl -X POST https://api.hinabi.app/api/v1/public/ingest/logs \ -H "X-API-Key: hn_live_your_secret_key_here" \ -H "Content-Type: application/json" \ -d '{ "logs": [ { "date": "2026-09-06", "timeSpentMinutes": 30, "activityName": "Reading Light Novel", "languageName": "Japanese" } ] }' ```