Runbook: Integrace aplikace na BillIt API
⚠️ ZASTARALÉ (auth sekce) od CR-021 (RS256/JWKS), zjištěno 2026-07-04. Krok 1 (HS256 JWT se
SENTINEL_JWT_SECRET) NEFUNGUJE — billit.env.produž tento secret nemá, tokeny validuje přes S60Auth JWKS (RS256). Sentinel ops cesta pro správu API klíčů/webhooků je v řešení s billit agentem (T-20260704-003). ApiKey auth header jeAuthorization: ApiKey blt_...(ne X-Api-Key). Po zavedení ops cesty runbook přepsat.
Přehled
BillIt používá tenant-based model. Aplikace (Pulse, budoucí další) se integrují pod existující tenant (typicky studio-60), NETVOŘÍ vlastní tenant.
Prerekvizity
- Přístup na prod-alfa (SSH)
SENTINEL_JWT_SECRETz/root/secrets/billit/.env.prod- Python3 s PyJWT (
pip3 install pyjwt)
Krok 1: Vygenerovat JWT token
BillIt API akceptuje JWT signed s SENTINEL_JWT_SECRET. Potřebuješ user ID ownera cílového tenantu.
# Najdi owner user ID pro tenant
# (DB: s60_billit_prod, tabulka tenant_users)
psql "$DB_CONN" -t -c "SELECT tu.user_id, tu.role FROM tenants t JOIN tenant_users tu ON t.id = tu.tenant_id WHERE t.slug = 'studio-60' AND tu.role = 'owner';"
# Vygeneruj JWT
TOKEN=$(python3 -c "
import jwt, time
token = jwt.encode(
{'sub': '<USER_ID>', 'email': '<EMAIL>', 'roles': ['admin'],
'iat': int(time.time()), 'exp': int(time.time()) + 3600,
'iss': 'https://auth.studio60.cz'},
'<SENTINEL_JWT_SECRET>',
algorithm='HS256'
)
print(token)
")
Krok 2: Vytvořit API key
# Na prod-alfa přes SSH (token přes soubor kvůli quoting)
ssh root@100.78.87.88 "echo '$TOKEN' > /tmp/billit-jwt.txt && \
curl -s -X POST http://127.0.0.1:3200/v1/accounts/studio-60/api-keys \
-H 'Content-Type: application/json' \
-H \"Authorization: Bearer \$(cat /tmp/billit-jwt.txt)\" \
-d '{\"name\": \"<APP> Production\", \"scopes\": [\"write:orders\", \"read:orders\", \"read:invoices\"]}' && \
rm /tmp/billit-jwt.txt"
Odpověď obsahuje rawKey (blt_...) — uložit do /root/secrets/<app>/billit-api-key-prod.txt.
Dostupné scopes
| Scope | Popis |
|---|---|
| read:invoices | Čtení faktur |
| write:invoices | Vytváření/editace faktur |
| read:orders | Čtení objednávek |
| write:orders | Vytváření/editace objednávek |
| read:subjects | Čtení kontaktů |
| write:subjects | Vytváření/editace kontaktů |
| read:expenses | Čtení nákladů |
| write:expenses | Vytváření/editace nákladů |
| read:accounting | Čtení účetnictví |
| write:accounting | Zápis předkontace |
| export:accounting | Export do ABRA/Pohoda/Money |
| read:webhooks | Správa webhooků |
Krok 3: Vytvořit webhook (volitelné)
ssh root@100.78.87.88 "echo '$TOKEN' > /tmp/billit-jwt.txt && \
curl -s -X POST http://127.0.0.1:3200/v1/accounts/studio-60/webhooks \
-H 'Content-Type: application/json' \
-H \"Authorization: Bearer \$(cat /tmp/billit-jwt.txt)\" \
-d '{\"url\": \"https://<APP_DOMAIN>/webhooks/billit\", \"events\": [\"order.paid\", \"order.cancelled\"]}' && \
rm /tmp/billit-jwt.txt"
Odpověď obsahuje secret (whsec_...) — uložit jako BILLIT_WEBHOOK_SECRET.
Krok 4: Nastavit env vars v cílové aplikaci
# Na prod-alfa v /opt/<app>/.env:
BILLIT_API_URL=https://billit.cz/api
BILLIT_API_KEY=blt_<key>
BILLIT_WEBHOOK_SECRET=whsec_<secret>
Restart kontejneru + ověřit health.
Krok 5: Uložit credentials
# Na sentinelu
cat > /root/secrets/<app>/billit-integration-prod.env << EOF
BILLIT_API_URL=https://billit.cz/api
BILLIT_API_KEY=blt_<key>
BILLIT_WEBHOOK_SECRET=whsec_<secret>
BILLIT_WEBHOOK_URL=https://<APP_DOMAIN>/webhooks/billit
EOF
chmod 600 /root/secrets/<app>/billit-integration-prod.env
Důležité poznámky
- NIKDY nevytvářet vlastní tenant pro aplikaci — vše pod
studio-60 - ForwardAuth headers (
x-user-id,x-user-email) už NEFUNGUJÍ — použít JWT - BillIt API base na prod:
https://billit.cz/api(nginx/api/→127.0.0.1:3200/) - Interní cesta:
http://127.0.0.1:3200/v1/accounts/:slug/... - JWT token předávat přes dočasný soubor (quoting problém přes SSH)
- Hub URL:
https://billit.s60hub.cz/api
Aktuální integrace
| Aplikace | Tenant | API Key prefix | Webhook | Stav |
|---|---|---|---|---|
| Pulse | studio-60 | blt_6859 | pulselab.cz/webhooks/billit | ✅ prod (2026-03-30) |