Tmavý režim
Admin endpointy (/admin)
Endpointy pro administraci systému — dashboard, notifikační typy, šablony a brandy. Vyžadují SuperAdmin (nebo AppAdmin pro dashboard).
Dashboard (/admin/dashboard)
GET /admin/dashboard/stats
Vrátí KPI statistiky.
http
GET /api/admin/dashboard/stats?days=7&topN=6
Authorization: Bearer <admin-token>Auth:
- SuperAdmin — vidí data za všechny aplikace
- AppAdmin — vidí pouze data svých aplikací
Query parametry
| Parametr | Výchozí | Rozsah | Popis |
|---|---|---|---|
days | 7 | 1–90 | Počet dní pro notificationsByDay |
topN | 6 | ≥1 | Počet top aplikací v top-listech |
appCode | — | — | Volitelně zúžit na jednu aplikaci. Musí být v rozsahu administrátora (jinak 403). App-admin musí předat, aby viděl dashboard zúžený jen na jednu z více svých aplikací. |
Response
Vrací bohatou strukturu s totally, time-series a top-listy. Plný tvar je popsaný ve Swaggeru (#/components/schemas přibyly, viz OpenAPI sekce).
json
{
"code": "OK",
"response": {
"totals": { "applications": 3, "users": 142, "activeUsers": 128, "notifications": 1847, "notificationsSent": 1800, "notificationsFailed": 12, "notificationsSkipped": 35 },
"notificationsByDay": [
{ "date": "2026-05-06", "sent": 203, "failed": 1, "skipped": 4 }
],
"topApplicationsByNotifications": [
{ "code": "crm", "name": "CRM", "notifications": 892, "failed": 4 }
],
"topApplicationsByTemplates": [
{ "code": "crm", "name": "CRM", "templates": 12 }
],
"recentNotifications": [
{ "id": 421, "appCode": "kgb", "appName": "KGB", "recipient": "jan.novak@firma.cz", "type": "project_shared", "subject": "...", "status": "sent", "statusReason": null, "createdAt": "2026-05-12T09:14:00.000Z" }
],
"applications": [
{ "code": "kgb", "name": "KGB", "templates": 5, "roles": 3, "users": 24, "notifications": 412, "sent": 405, "failed": 2, "skipped": 5 }
]
}
}Notifikační typy (/admin/notifications/types)
Správa typů notifikací (které typy existují, zda jsou povoleny email/push, zda je může uživatel vypnout).
GET /admin/notifications/types/:appCode
http
GET /api/admin/notifications/types/crm
Authorization: Bearer <superadmin-token>Response
json
{
"success": true,
"data": [
{
"id": 1,
"appCode": "crm",
"code": "new_task",
"name": "Nový úkol",
"description": "Oznámení o přiřazení nového úkolu",
"emailEnabled": true,
"pushEnabled": true,
"userCanDisable": true,
"defaultEmail": true,
"defaultPush": false,
"createdAt": "2024-01-10T08:00:00.000Z"
}
]
}POST /admin/notifications/types/:appCode — vytvoření typu
http
POST /api/admin/notifications/types/crm
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"code": "deal_closed",
"name": "Obchod uzavřen",
"description": "Notifikace při uzavření obchodu",
"emailEnabled": true,
"pushEnabled": false,
"userCanDisable": true,
"defaultEmail": true,
"defaultPush": false
}| Pole | Typ | Výchozí | Popis |
|---|---|---|---|
code | string | — | Unikátní kód typu |
name | string | — | Zobrazovaný název |
description | string | null | Popis |
emailEnabled | boolean | true | Email notifikace povoleny |
pushEnabled | boolean | false | Push notifikace povoleny |
userCanDisable | boolean | true | Uživatel může typ vypnout |
defaultEmail | boolean | true | Výchozí stav email pro nové uživatele |
defaultPush | boolean | false | Výchozí stav push pro nové uživatele |
GET /admin/notifications/types/detail/:id
http
GET /api/admin/notifications/types/detail/1
Authorization: Bearer <superadmin-token>PUT /admin/notifications/types/detail/:id
http
PUT /api/admin/notifications/types/detail/1
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"name": "Nový název",
"emailEnabled": false
}DELETE /admin/notifications/types/detail/:id
Smaže typ i kaskádně všechny jeho šablony a jejich jazykové verze — žádné osiřelé řádky.
http
DELETE /api/admin/notifications/types/detail/1
Authorization: Bearer <superadmin-token>Pojmenované šablony (3 úrovně)
Model: typ (skupina) → pojmenovaná šablona (key) → jazyková verze (locale). Detaily viz Typy, šablony a jazykové verze.
GET /admin/notifications/types/:appCode/:type/templates — šablony pod typem
Vrátí typ a jeho pojmenované šablony (každá se seznamem locale).
json
{
"code": "OK",
"response": {
"type": { "id": 3, "code": "error", "name": "Chyby", "...": "..." },
"templates": [
{ "id": 10, "type": "error", "key": "disk_full", "name": "Disk je plný",
"description": null, "variables": [], "locales": ["cs", "en"] }
]
}
}POST /admin/notifications/types/:appCode/:type/templates — vytvoř šablonu
json
{
"key": "disk_full",
"name": "Disk je plný",
"description": "Upozornění na zaplněný disk",
"variables": [ { "key": "path", "required": true } ]
}type musí existovat (jinak 400 UNKNOWN_NOTIFICATION_TYPE); key je slug unikátní v (app, type).
PUT /admin/notifications/templates/:id — uprav šablonu
Mění name, description, variables. key i type jsou neměnné.
DELETE /admin/notifications/templates/:id — smaž šablonu
Kaskádně smaže i všechny jazykové verze šablony.
GET /admin/notifications/templates/:appCode — všechny šablony aplikace
Plochý seznam pojmenovaných šablon napříč typy.
GET /admin/notifications/templates/:id/locales — jazykové verze
PUT /admin/notifications/templates/:id/locales/:locale — upsert jazykové verze
Idempotentní upsert podle (templateId, locale): neexistující vytvoří (201), existující aktualizuje (200).
json
{
"subjectTemplate": "{{appName}}: disk je plný ({{path}})",
"bodyTemplate": "<p>Disk <strong>{{path}}</strong> je plný.</p>"
}locale musí být povolený jazyk aplikace (jinak 400 UNSUPPORTED_LOCALE).
DELETE /admin/notifications/templates/:id/locales/:locale — smaž jazykovou verzi
POST /admin/notifications/templates/preview — preview šablony
Vykreslí šablonu s testovacími daty pro náhled.
http
POST /api/admin/notifications/templates/preview
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"subjectTemplate": "Obchod uzavřen: {{dealName}}",
"bodyTemplate": "<h1>Uzavřeno!</h1><p>{{dealName}} — {{dealValue}} Kč</p>",
"data": {
"dealName": "Projekt Omega",
"dealValue": "250000"
},
"brand": "atrea"
}Response
json
{
"success": true,
"data": {
"subject": "Obchod uzavřen: Projekt Omega",
"htmlBody": "<h1>Uzavřeno!</h1><p>Projekt Omega — 250000 Kč</p>"
}
}GET /admin/notifications/log/:appCode — log notifikací
http
GET /api/admin/notifications/log/crm
Authorization: Bearer <superadmin-token>Broadcast (/admin/notifications/broadcast)
Rozeslání jednoho typu jednomu / poli / všem uživatelům, throttlovaně a na pozadí. Kompletní popis viz Broadcast.
POST /admin/notifications/broadcast/:appCode — spuštění (202)
http
POST /api/admin/notifications/broadcast/crm
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"type": "error",
"template": "maintenance_notice",
"recipients": "all",
"data": { "from": "22:00", "to": "02:00" },
"throttle": { "batchSize": 20, "delayMs": 1000 }
}| Pole | Typ | Povinné | Popis |
|---|---|---|---|
type | string | ✓ | Kód typu / skupiny (musí existovat; nebo generic) |
template | string | ✗* | Šablona pod typem; volitelná jen když má typ jedinou (jinak 400 TEMPLATE_REQUIRED) |
recipients | "all" | string[] | ✓ | "all" = aktivní uživatelé s rolí v aplikaci; jinak pole e-mailů |
data | object | ✗ | Data šablony (stejná pro všechny) |
locale / brand | string | ✗ | Vynutit locale / brand (jinak per-user) |
channels | ("email"|"push")[] | ✗ | Omezit kanály |
throttle | object | ✗ | { batchSize (1–100, def 10), delayMs (0–60000, def 1000) } |
GET /admin/notifications/broadcast/jobs — seznam jobů
GET /admin/notifications/broadcast/jobs/:jobId — stav / průběh jobu
POST /admin/notifications/broadcast/jobs/:jobId/cancel — zrušení běžícího jobu
Brandy (/admin/brands)
Správa brandů (vizuální identita pro emaily a aplikace).
GET /admin/brands — seznam brandů
http
GET /api/admin/brands
Authorization: Bearer <superadmin-token>Response
json
{
"success": true,
"data": [
{
"id": 1,
"slug": "atrea",
"name": "Atrea",
"primaryColor": "#1976D2",
"headerBackground": "#1565C0",
"footerBackground": "#f5f5f5",
"footerTextColor": "#888888",
"buttonTextColor": "#ffffff",
"headingColor": "#1a202c",
"logoMaxHeight": 36,
"pageBackground": "#F1F3F7",
"bodyBackground": "#FFFFFF",
"fontColor": "#212121",
"linkColor": "#1976D2",
"logoUrl": "/public/img/atrea/logo.svg",
"footerText": "© Atrea s.r.o.",
"emailFrom": "noreply@atrea.eu",
"isDefault": true
}
]
}GET /admin/brands/themes — pole témat
Breaking change (2026-05)
Endpoint dříve vracel Record<slug, BrandTheme> (mapu). Nyní vrací pole BrandTheme[], kde každá položka nese slug i isDefault. Důvod: konzistence s ostatními list endpointy (/applications, /roles, …) a odstranění FE-side flatování.
http
GET /api/admin/brands/themes
Authorization: Bearer <superadmin-token>Response
json
{
"code": "OK",
"response": [
{
"slug": "atrea",
"name": "Atrea",
"primaryColor": "#00418e",
"headerBackground": "#003070",
"footerBackground": "#f5f5f5",
"footerTextColor": "#888888",
"buttonTextColor": "#ffffff",
"headingColor": "#1a202c",
"logoMaxHeight": 36,
"pageBackground": "#f1f3f7",
"bodyBackground": "#ffffff",
"fontColor": "#0f172a",
"linkColor": "#00418e",
"logoUrl": "/public/img/atrea/logo.svg",
"footerText": "Atrea s.r.o.",
"emailFrom": "Atrea <noreply@atrea.eu>",
"isDefault": true
},
{ "slug": "vallox", "...": "..." }
]
}| Pole | Typ | Význam |
|---|---|---|
isDefault | boolean | True u brandu, který slouží jako fallback (registrační default, fallback themingu). |
POST /admin/brands — vytvoření brandu
http
POST /api/admin/brands
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"slug": "nova-znacka",
"name": "Nová Značka",
"primaryColor": "#E91E63",
"headerBackground": "#C2185B",
"footerBackground": "#f5f5f5",
"footerTextColor": "#888888",
"buttonTextColor": "#ffffff",
"headingColor": "#1a202c",
"logoMaxHeight": 36,
"pageBackground": "#FAFAFA",
"bodyBackground": "#FFFFFF",
"fontColor": "#212121",
"linkColor": "#E91E63",
"logoUrl": "/public/img/nova-znacka/logo.svg",
"footerText": "© Nová Značka s.r.o.",
"emailFrom": "noreply@nova-znacka.cz",
"isDefault": false
}PUT /admin/brands/:id — aktualizace brandu
http
PUT /api/admin/brands/3
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"primaryColor": "#F44336",
"emailFrom": "info@nova-znacka.cz"
}DELETE /admin/brands/:id — smazání brandu
http
DELETE /api/admin/brands/3
Authorization: Bearer <superadmin-token>DANGER
Výchozí brand nelze smazat. Nejdřív nastavte jiný brand jako výchozí.
POST /admin/brands/:id/default — nastavení výchozího brandu
http
POST /api/admin/brands/3/default
Authorization: Bearer <superadmin-token>Nastaví brand jako výchozí a odebere výchozí status ostatním brandům.
Zitadel Admin (/zitadel/admin)
Správa Zitadel organizací (vyžaduje SuperAdmin + platný Zitadel service account token).
GET /zitadel/admin/orgs
http
GET /api/zitadel/admin/orgs
Authorization: Bearer <superadmin-token>POST /zitadel/admin/orgs — vytvoření organizace
http
POST /api/zitadel/admin/orgs
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"name": "Nová Firma s.r.o.",
"domain": "nova-firma.cz"
}PUT /zitadel/admin/orgs/:orgId/branding — nastavení brandingu
http
PUT /api/zitadel/admin/orgs/org_abc123/branding
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"primaryColor": "#E91E63",
"logoUrl": "https://cdn.atrea.eu/logos/nova-firma.png"
}POST /zitadel/admin/orgs/:orgId/setup — kompletní brand setup
Automaticky vytvoří projekt, OIDC aplikaci a nakonfiguruje redirect URI v Zitadelu.
http
POST /api/zitadel/admin/orgs/org_abc123/setup
Authorization: Bearer <superadmin-token>
Content-Type: application/jsonjson
{
"projectName": "Nova Firma Portal",
"appName": "Portal App",
"redirectUris": ["https://portal.nova-firma.cz/callback"],
"postLogoutUris": ["https://portal.nova-firma.cz/logout"],
"userApiAppCode": "portal"
}