Autentifikácia
API kľúče vo formáte mk_<32 znakov>, scope-y a ich konfigurácia v UI.
Monivio API používa Bearer token autentifikáciu. Každú požiadavku označíš API kľúčom v Authorization hlavičke. Kľúče vytvoríš v aplikácii v Nastavenia → API kľúče.
Formát kľúča
API kľúč je 35-znakový string začínajúci prefixom mk_ (Monivio Key) nasledovaným 32 base64url znakmi:
mk_2Hf8Pq3RxN4mLkZyT9aBwVvE6sCrXjQyHlavička požiadavky
Authorization: Bearer mk_2Hf8Pq3RxN4mLkZyT9aBwVvE6sCrXjQyPríklad: overenie kľúča
Overenie kľúča urobíš zavolaním ľubovoľného authenticated endpointu - napríklad /contacts:
curl "https://monivio.sk/api/v1/contacts?limit=1" \
-H "Authorization: Bearer mk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"Typy kľúčov
Pri vytváraní kľúča volíš jeden z dvoch typov:
- •
read_only- kľúč sa vytvorí so scope-mi, ktoré obsahujú len:readakciu (žiadne:write). Akýkoľvek POST/PATCH/DELETE preto neprejde scope kontrolou a vráti 403INSUFFICIENT_SCOPE. Vhodné pre reportovacie integrácie a dashboards. - •
read_write- plný prístup. Konkrétne povolené operácie ďalej riadia scope-y (pozri nižšie).
Scopes
Každý kľúč má povolené operácie definované formátom {resource}:{action}. Napríklad kľúč ktorý môže čítať kontakty a vytvárať dokumenty:
{
"contacts": ["read"],
"documents": ["read", "write"]
}Pri každom requeste handler skontroluje scope vyžadovaný daným endpointom. Keď chýba, dostaneš 403:
{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "Insufficient permissions: documents:write"
}
}Kompletný zoznam scope-ov nájdeš v Reference → Scope-y.
Bezpečnosť kľúča
- • Plaintext kľúč uvidíš len raz - pri vytvorení. Po opustení dialógu sa už neobnoví.
- • Skladujte v secret store (env premenné, AWS SSM, Vault). Nikdy v gite, frontende ani mobilnej apke.
- • Rotácia: vytvorte nový kľúč, prepnite klienta, potom starý revoke-nite. Revoke je synchrónny - ďalší request po revoku dostane 401
API_KEY_REVOKED. - • last_used_at + last_used_ip sa logujú pri každom úspešnom request - v UI vidíš kedy a odkiaľ sa kľúč naposledy použil. Pomáha to detekovať leaky.
- • Expirácia: pri vytvorení môžeš nastaviť expiration date. Po expirácii dostaneš 401
API_KEY_EXPIRED.
Chyby autentifikácie
Auth handler vracia HTTP 401 s konkrétnym error.code podľa toho, kde request padol:
- •
UNAUTHORIZED- chýba alebo má nesprávny tvar Authorization hlavička - •
INVALID_API_KEY- kľúč nemá správny formát alebo neexistuje - •
API_KEY_REVOKED- kľúč bol manuálne odvolaný v UI - •
API_KEY_EXPIRED- kľúč prekročil svojexpires_at
Druhý faktor v natívnej aplikácii
Pri zapnutom native_client.enabled používa natívna aplikácia podpísanú hodnotu relácie v hlavičke Authorization: Bearer. Ak stav relácie vyžaduje druhý faktor, pošli POST na /api/v1/auth/two-factor/totp alebo /api/v1/auth/two-factor/recovery-code. Telo obsahuje iba code. Surový session token ani trustDevice sa neprijímajú.
POST /api/v1/auth/two-factor/totp
Authorization: Bearer <signed-session>
Content-Type: application/json
{"code":"123456"}Úspech vráti 204 bez tela. Pokračuj s rovnakým podpísaným Bearer tokenom. Chybný kód vráti 422 TWO_FACTOR_CODE_INVALID, už overená relácia 409 CONFLICT a neplatná alebo vypršaná relácia 401 UNAUTHORIZED. Kód treba overiť do 15 minút od prihlásenia. Limit piatich pokusov za minútu na jedno prihlásenie sa zdieľa s webom aj ostatnými faktormi; prekročenie vráti 429 RATE_LIMIT_EXCEEDED so scope session a zruší pending reláciu, takže treba sa prihlásiť znova. Nesprávne TOTP kódy sa navyše rátajú do limitu desiatich za hodinu na účet (správne nie); prekročenie vráti 429 so scope account a hlavičkou Retry-After, pending relácia ostáva a záložný kód funguje hneď. Natívne overenie nevytvára dôveryhodné zariadenie.
Push notifikácie v natívnej aplikácii
Natívna aplikácia zaregistruje token zariadenia cez POST na /api/v1/devices. Endpoint prijíma len podpísanú reláciu, API kľúč vráti 403 a hlavička x-org-slug sa neposiela. Pole platform určuje doručenie: ios (APNs, platí aj pri chýbajúcom poli) alebo android (Firebase Cloud Messaging). iOS posiela hexadecimálny APNs token a environment, Android posiela registračný token FCM bez environment. bundle_id sa musí zhodovať s povolenou aplikáciou, inak vráti 422. Nové zariadenie vráti 201, už známy token 200 a v oboch prípadoch sa priradí aktuálnej relácii.
POST /api/v1/devices
Authorization: Bearer <signed-session>
Content-Type: application/json
{"push_token":"a1b2...","environment":"production","bundle_id":"sk.monivio.app","app_version":"1.0","os_version":"26.0","device_model":"iPhone17,1"}POST /api/v1/devices
Authorization: Bearer <signed-session>
Content-Type: application/json
{"platform":"android","push_token":"dXk9...:APA91b...","bundle_id":"sk.monivio.app","app_version":"1.0","os_version":"16","device_model":"Pixel 9"}Zariadenie je viazané na reláciu. Odhlásenie alebo odvolanie relácie ho odpojí automaticky. DELETE na /api/v1/devices/{id} ho odpojí ručne a vráti 204; cudzie alebo neexistujúce zariadenie vráti 404. Notifikácia po spracovaní skenu nenesie sumu, dodávateľa ani číslo dokladu, len lokalizačné kľúče (push.scan.* na iOS, push_scan_* na Androide), expense_id a organization_slug.
Natívne prihlásenie cez Apple
Pri zapnutom native_client.enabled si appka bez autentifikácie vyžiada jednorazový nonce. Platí päť minút; limit je 10 požiadaviek za minútu na IP. Odpoveď nemá obálku data a nikdy sa necachuje.
POST /api/v1/auth/apple/nonce{ "nonce": "<32 náhodných bajtov vo formáte base64url>" }Apple dostane SHA-256 hash nonce v hex formáte. Do Monivia appka pošle identity token a pôvodný nonce; server overí podpis, issuer, audience sk.monivio.app, časovú platnosť a nonce. Každý nonce sa dá použiť len raz.
POST /api/auth/sign-in/social{ "provider": "apple", "idToken": { "token": "<Apple identity token>", "nonce": "<pôvodný nonce>" } }Prihlásenie funguje len pre existujúce účty. Appka prevezme podpísanú session hodnotu zo Set-Cookie a používa ju ako Bearer. Druhý faktor ostáva povinný. Neznámy e-mail ani relay adresa nevytvoria nový účet; server vráti 401 ACCOUNT_NOT_FOUND. Apple s iným e-mailom treba najprv prepojiť v nastaveniach profilu na webe.
Nonce endpoint vracia 401 UNAUTHORIZED pri vypnutom natívnom klientovi, 429 RATE_LIMIT_EXCEEDED s Retry-After pri prekročení limitu a 503 SERVICE_UNAVAILABLE pri nedostupnom úložisku alebo limite. Prihlásenie cez /api/auth používa vlastný formát chýb Better Auth; odmietnutý identity token má HTTP 401.
Natívne prihlásenie cez Google
Android appka si nonce vyžiada rovnako ako pri Apple. Platí päť minút a dá sa použiť len raz; limit je 10 požiadaviek za minútu na IP. Prostredie bez nastaveného Android klienta vráti 503 SERVICE_UNAVAILABLE.
POST /api/v1/auth/google/nonceCredential Manager dostane SHA-256 hash nonce v hex formáte a serverové (webové) client ID. Do Monivia appka pošle Google ID token a pôvodný nonce. Server overí podpis, issuer, audience webového klienta, azp Android klienta prostredia, vek tokenu najviac päť minút, overený e-mail a nonce.
POST /api/auth/sign-in/social{ "provider": "google", "idToken": { "token": "<Google ID token>", "nonce": "<pôvodný nonce>" } }Prihlásenie funguje len pre existujúce účty a druhý faktor ostáva povinný. Neznámy e-mail vráti 401 ACCOUNT_NOT_FOUND, neplatný token 401 INVALID_TOKEN. Zhodný e-mail sa k existujúcemu účtu pripojí len pri Gmaile alebo účte Google Workspace a vlastník o tom dostane e-mail; iný účet Google dostane tiež 401 ACCOUNT_NOT_FOUND a pripája sa v nastaveniach profilu. Server ID token neukladá.