# Boti Education app API protocol (Green Wood School variant) Reverse engineered statically from com.botieducation.greenwood 2.4.14 (Capacitor/Ionic/Angular bundle) and verified with one live login call on 2026-09-01. ## Base URL https://boti.education/p/greenwood/botiapi/ Pattern per school: https://boti.education/p//botiapi/ All Boti Education schools share one backend. Media host: media.boti.education (signed expiring URLs, token appended to path). ## Authentication ### Login POST {base}/login Content-Type: multipart/form-data Fields: - login phone number, e.g. 06xxxxxxxx - password plaintext - privacy bool ("true"/"false") - remembreMe bool Response (HTTP 200, application/json): { "status": 200, "msg": "Bienvenue !", "error": false, "keyToken": "<40 hex chars>", // session key "userId": "20887", "parentId": "1376", // when role=parent "eleveId": "1739", "_acces": "parent", "role": "parent", "eleves": [ { id, nomcomplet, prenom, nom, datenaissance, sexe, niveau, img, parent_nom, parent_image } ], "parent": { id, nomcomplet, tel, email, sexe, image }, "accessToken": "", // present on some accounts, may be empty "refreshToken": "" } Errors: {"error": true, "msg": "..."} with HTTP 200. ### Session use on every subsequent call - GET: query params, plus key= and user_id= - POST: multipart/form-data fields, plus key= - Optional modern path (supported by the ApiService, may be empty for parent accounts): headers Authorization: Bearer and X-refresh-token: Bearer ### Server-side session control - Any response containing "disconnect": true means the session was killed client-side (app navigates to login). - "redirect": "" makes the app navigate there. - "showSLides": "" pops a slider modal (onboarding/news screens). ## Request envelope GET params observed in the bundle (per feature, subset applies): user_id, key, acces, versionCode, versionNumber, paltform (sic, typo is in the app), eleveId, lang, date, startDate, endDate, classe, id, search, page POST FormData conventions: - flat fields appended as key=value - nested object -> key[subkey]=value - array -> key[0]=..., key[1]=... - File/Blob -> appended raw under the field name - key= auto-appended by the ApiService ## Push notifications POST {base}/device_token fields: token=, user_id, key, uid= ## Endpoint inventory See endpoints.md (100 app endpoints, get/post flags, source chunk per endpoint). Endpoint names are stable Pascal/snake identifiers appended to the base URL. ## Media / files - Files and images are fetched from media.boti.education with a signed, expiring path (base64url token + timestamp appended). - PDFs opened in-app via pdf.js (chunk 7482.js). - getBlob(path, params, absolute) downloads raw blobs for attachments. ## Quirks - The ApiService appends the endpoint as a raw string, so endpoint names in the table are the complete server route (no /api prefix, no .php). - Param typo "paltform" is sent by the app; server accepts it, do not "fix" it blindly. - Detailed console.log of params and headers ships in production.