Skip to content

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

ParametrVýchozíRozsahPopis
days71–90Počet dní pro notificationsByDay
topN6≥1Počet top aplikací v top-listech
appCodeVolitelně 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/json
json
{
  "code": "deal_closed",
  "name": "Obchod uzavřen",
  "description": "Notifikace při uzavření obchodu",
  "emailEnabled": true,
  "pushEnabled": false,
  "userCanDisable": true,
  "defaultEmail": true,
  "defaultPush": false
}
PoleTypVýchozíPopis
codestringUnikátní kód typu
namestringZobrazovaný název
descriptionstringnullPopis
emailEnabledbooleantrueEmail notifikace povoleny
pushEnabledbooleanfalsePush notifikace povoleny
userCanDisablebooleantrueUživatel může typ vypnout
defaultEmailbooleantrueVýchozí stav email pro nové uživatele
defaultPushbooleanfalseVý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/json
json
{
  "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/json
json
{
  "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/json
json
{
  "type": "error",
  "template": "maintenance_notice",
  "recipients": "all",
  "data": { "from": "22:00", "to": "02:00" },
  "throttle": { "batchSize": 20, "delayMs": 1000 }
}
PoleTypPovinnéPopis
typestringKód typu / skupiny (musí existovat; nebo generic)
templatestring✗*Š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ů
dataobjectData šablony (stejná pro všechny)
locale / brandstringVynutit locale / brand (jinak per-user)
channels("email"|"push")[]Omezit kanály
throttleobject{ 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", "...": "..." }
  ]
}
PoleTypVýznam
isDefaultbooleanTrue 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/json
json
{
  "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/json
json
{
  "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/json
json
{
  "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/json
json
{
  "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/json
json
{
  "projectName": "Nova Firma Portal",
  "appName": "Portal App",
  "redirectUris": ["https://portal.nova-firma.cz/callback"],
  "postLogoutUris": ["https://portal.nova-firma.cz/logout"],
  "userApiAppCode": "portal"
}

Atrea User API — interní dokumentace