Web-/Commerce-API (JuByteWeb)
Vollständige Referenz der JuByteWeb-Plattform — dem zentralen Portal für
Lizenzen, Store, Bezahlung, Releases/Downloads, Organisationen und das
Lizenz-Backend des Nexus Core. JuByteWeb ist eine Next.js-16-App (App Router);
alle Endpunkte liegen unter app/api/**/route.ts.
Diese Seite katalogisiert jeden Endpunkt nach Domäne, beschreibt das Datenmodell und zeigt Entwickler-Beispiele. Verwandt: Lizenz-API & Entitlement-Vertrag und Module lizenzieren & verkaufen.
Auth-Klassen in den Tabellen: Public (kein Login), Session (eingeloggter User via Cookie), Admin (Session + Permission-Key, z. B.
admin.licenses.view), Token (Shared-Secret/Signatur, für Core/CI/Webhooks).
1. Authentifizierung & Konto
Login, Registrierung, Session
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
POST | /api/auth/register | Public | Registrierung (Passwort ≥ 10 Zeichen, AGB/Datenschutz). Enqueued EMAIL_VERIFICATION_REQUESTED + Discord-Notify |
POST | /api/auth/login | Public | E-Mail/Passwort-Login; bei 2FA requires2fa: true + challengeToken (Rate-Limit 10/min) |
POST | /api/auth/logout | Session | Session-Cookie widerrufen, AUTH_LOGOUT auditieren |
GET | /api/auth/me | Session | Profil inkl. primärer Gruppe (nach Gewicht), Discord-Status |
POST | /api/auth/verify-email | Public | emailVerifiedAt setzen, Token löschen, Gruppe „user" zuweisen |
POST | /api/auth/resend-verification | Public | Verifikations-Mail erneut senden |
POST | /api/auth/change-password | Session | Passwort ändern (Rate-Limit 10/min) |
POST | /api/auth/forgot-password | Public | PASSWORD_RESET_REQUESTED enqueuen |
POST | /api/auth/reset-password | Public | Reset-Token prüfen, Passwort setzen |
2FA (TOTP)
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
POST | /api/auth/2fa/setup | Session | TOTP-Secret erzeugen → otpauthUrl + qrSvg |
POST | /api/auth/2fa/enable | Session | Aktivieren; gibt 10 Backup-Codes zurück |
POST | /api/auth/2fa/verify | Public | TOTP-Code zum challengeToken prüfen → Session |
POST | /api/auth/2fa/disable | Session | Deaktivieren nach Passwort-Bestätigung |
Passkeys (WebAuthn)
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
POST | /api/auth/passkey/register/start | Session | Registrierungs-Ceremony starten |
POST | /api/auth/passkey/register/complete | Session | Passkey speichern |
POST | /api/auth/passkey/authenticate/start | Public | Auth-Ceremony (optional email für non-discoverable) |
POST | /api/auth/passkey/authenticate/complete | Public | Auth abschließen → Session |
GET/DELETE | /api/auth/passkeys, /api/auth/passkeys/[id] | Session | Passkeys auflisten/Details/widerrufen |
Sessions & Discord
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/auth/sessions | Session | Aktive Sessions auflisten |
POST | /api/auth/sessions/revoke | Session | Bestimmte Session widerrufen |
POST | /api/auth/discord/start | Session | Discord-OAuth starten → authorizationUrl |
GET | /api/auth/discord/callback | Public | OAuth-Callback, Discord verknüpfen |
POST | /api/auth/discord/unlink | Session | Discord trennen |
POST | /api/auth/discord/sync | Session | DiscordSyncJob (Reason MANUAL) enqueuen |
Beispiel: Login mit fetch
const res = await fetch('/api/auth/login', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
const data = await res.json();
if (data.requires2fa) {
// → /api/auth/2fa/verify mit { challengeToken: data.challengeToken, code }
}
2. Store & Katalog
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/store/products | Public | Öffentlicher Katalog: Produkte mit priceTiers, releases, bundleItems |
GET | /api/admin/products | Admin admin.products.view | Alle Produkte (inkl. versteckter) |
POST | /api/admin/products | Admin admin.products.manage | Produkt anlegen (+ Gruppen-/Channel-Grants) |
GET/PATCH/DELETE | /api/admin/products/[id] | Admin | Produkt-Detail/ändern/löschen |
POST | /api/admin/products/[id]/media | Admin admin.products.manage | Logo/Banner hochladen (multipart) |
Preis-Tiers & Bundles
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET/POST | /api/admin/products/[id]/tiers | Admin | Preis-Tiers auflisten/anlegen (priceEur, durationDays?, featuresJson, maxServers?) |
PATCH/DELETE | /api/admin/products/[id]/tiers/[tierId] | Admin | Tier ändern/löschen |
GET/POST | /api/admin/products/[id]/bundle-items | Admin | Bundle-Mitglieder auflisten/hinzufügen |
DELETE | /api/admin/products/[id]/bundle-items/[memberId] | Admin | Mitglied entfernen |
Beispiel: öffentlicher Katalog
curl https://test.jubyte.com/api/store/products | jq '.products[] | {key, name, tiers: .priceTiers}'
3. Commerce / Checkout & Bezahlung
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
POST | /api/commerce/checkout | Session | Order(s) anlegen, aktive Sales anwenden, PayPal-/PayPal.me-URL zurückgeben (Status → PENDING, Rate-Limit 10/min) |
GET | /api/commerce/capture?token=<paypal> | Session | PayPal-Order capturen → Order ACTIVE, Lizenzen aktivieren, Download-Events |
POST | /api/webhooks/paypal | Token (Signatur) | PayPal-Events (PAYMENT.CAPTURE.COMPLETED/REFUNDED…); Signatur prüfen, dedupen, verarbeiten (Rate-Limit 60/min) |
Checkout-Request (gekürzt):
{
"items": [ { "product": "bansystem", "tier": "pro" } ],
"currency": "EUR",
"billingName": "Max Mustermann",
"billingCountry": "DE",
"withdrawalWaived": true,
"agreeTerms": true,
"agreePrivacy": true
}
Antwort: { "orderId": "…", "approvalUrl": "https://www.paypal.com/checkoutnow?token=…" }.
Pro Item entsteht eine Order; alle teilen sich die paypalOrderId.
Ablauf (PayPal): checkout (Order erstellen) → Kunde genehmigt → capture
(serverseitig) → Webhook (asynchrone Bestätigung + Buchung im Ledger).
4. Orders & Rechnungen
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/portal/orders | Session | Eigene Bestellungen inkl. Zahlungsinfo |
GET | /api/portal/invoices | Session | Eigene Rechnungen (ISSUED/REFUNDED/CANCELLED) |
GET | /api/portal/invoices/[id] | Session | Einzelne Rechnung |
GET | /api/admin/orders | Admin admin.orders.view | Order-Suche (id, product, paypalOrderId, User-E-Mail), paginiert |
5. Lizenzen
Portal (eigene/Org-Lizenzen)
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/portal/licenses | Session | Eigene + Org-Lizenzen (Status auto → EXPIRED bei Ablauf), Bindungszähler |
GET | /api/portal/licenses/[id] | Session | Lizenz-Detail inkl. Server-Bindungen |
DELETE | /api/portal/licenses/[id] | Session | Lizenz soft-löschen (REVOKED) |
GET/DELETE | /api/portal/licenses/[id]/bindings/[bindingId] | Session | Server-Bindung ansehen/widerrufen |
Admin
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/admin/licenses | Admin admin.licenses.view | Suche (Key, E-Mail, Produkt, Status, productId), paginiert |
POST | /api/admin/licenses | Admin admin.licenses.create | Lizenz manuell ausstellen (Key auto, sofern nicht angegeben) |
GET | /api/admin/licenses/[id] | Admin admin.licenses.view | Voll-Detail (User, Bindungen, Events, Module, Security-Flags) |
PATCH | /api/admin/licenses/[id] | Admin admin.licenses.manage | plan/maxServers/expiresAt/status ändern |
POST | /api/admin/licenses/[id]/assign | Admin admin.licenses.manage | Neuem User zuweisen (per userId oder email) |
POST | `/api/admin/licenses/[id]/revoke | suspend | unsuspend |
GET/POST | /api/admin/licenses/[id]/modules | Admin | Nexus-Modul-Grants lesen / `{action:'grant' |
GET | /api/admin/licenses/[id]/entitlement | Admin | Signiertes Entitlement-JWS mit modules[]-Claim erzeugen |
Lizenz-Server-API v1 (für den Core)
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
POST | /api/v1/license/verify | Rate-Limit 30/min | Heartbeat-Verify: Status, Bindungslimit, Cache; LICENSE_VERIFY-Event |
POST | /api/v1/license/activate | Rate-Limit 15/min | Server-Aktivierung; Plan-Limits (FREE=1, PRO=50, ENTERPRISE=∞) |
POST | /api/v1/license/issue | CI-Token | Lizenzen aus Release-Pipeline ausstellen |
POST | /api/v1/license/download | Lizenz-Key | Lizenz-authentifizierter Artefakt-Download |
POST | /api/v1/license/heartbeat | Rate-Limit | lastSeenAt der Bindung aktualisieren |
Der Entitlement-Vertrag (RS256-JWS, Claims
plan/status/expires/limits/features/ modules/grace_hours) ist in der Lizenz-API vollständig beschrieben. Der Core holt und aktiviert ihn automatisch.
Beispiel: Verify (Core → Web)
curl -X POST https://test.jubyte.com/api/v1/license/verify \
-H "Content-Type: application/json" \
-d '{"key":"NX-XXXX-XXXX","serverId":"srv-abc","version":"1.2.0","channel":"RELEASE"}'
# → { "allowed": true, "status": "ACTIVE", "license": {…}, "latestStableVersion": "1.2.0" }
6. Releases & Downloads
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/admin/releases | Admin admin.releases.view | Release-Suche (productKey, channel, status), paginiert |
POST | /api/admin/releases | Admin admin.releases.manage | Release im DRAFT anlegen (semver + sha256 validiert) |
POST | /api/admin/releases/[id]/publish | Admin admin.releases.publish | Veröffentlichen → PUBLISHED, Cache invalidieren |
POST | /api/admin/releases/[id]/deprecate | Admin admin.releases.manage | Als DEPRECATED markieren |
POST | /api/admin/releases/publish-ci | CI-Token | Release aus Build-Pipeline anlegen/veröffentlichen |
GET | /api/download/release/[releaseId]?licenseId= | Session | Signierten Download-Token (TTL 300 s); Channel-Grants für BETA/SNAPSHOT |
GET | /api/download/artifact?token=<signed> | Public | Artefakt streamen (Single-Use-Token) |
GET | /api/portal/downloads | Session | Erreichbare Downloads je Lizenz (Bundles aufgelöst, 60 s Cache) |
GET | /api/portal/releases | Session | Erreichbare Releases über alle Lizenzen |
Channels: RELEASE (alle), BETA/SNAPSHOT (nur mit Gruppen-Grant via
ProductChannelGrant). Release-Status: DRAFT/PUBLISHED/DEPRECATED.
7. Organisationen & Teams
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET/POST | /api/orgs | Session | Eigene Orgs / Org anlegen (Ersteller = OWNER) |
GET/PATCH | /api/orgs/[slug] | Session + Member/OWNER | Org-Detail / umbenennen, suspendieren |
GET | /api/orgs/[slug]/members | Session + Member | Mitglieder |
PATCH | /api/orgs/[slug]/members/[userId]/role | Session + ADMIN | Rolle ändern (OWNER/ADMIN/SUPPORT/BILLING) |
DELETE | /api/orgs/[slug]/members/[userId] | Session + OWNER | Mitglied entfernen |
POST | /api/orgs/[slug]/invite | Session + OWNER | Einladung (7-Tage-TTL), EMAIL_ORG_INVITE |
GET/POST | /api/org-invites/[token], /accept | Public/Session | Einladung ansehen/annehmen |
POST | `/api/orgs/[slug]/licenses/assign | unassign` | Session + ADMIN/OWNER |
GET/PATCH | /api/admin/orgs, /api/admin/orgs/[id] | Admin admin.orgs.* | Org-Suche/-Verwaltung |
8. Berechtigungen, Gruppen & Discord-Mapping
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET/POST | /api/admin/groups | Admin admin.groups.* | Gruppen auflisten/anlegen (inkl. System-Gruppen) |
GET/PATCH/DELETE | /api/admin/groups/[groupId] | Admin | Gruppen-Detail/ändern/löschen |
GET/POST/DELETE | /api/admin/groups/[groupId]/members[/userId] | Admin | Mitglieder verwalten |
GET/POST | /api/admin/permissions | Admin admin.permissions.* | Permissions auflisten/anlegen (Key z. B. admin.products.view) |
GET | /api/portal/permissions | Session | Eigene Permissions (aus Gruppenmitgliedschaft) |
GET/POST | /api/admin/discord/role-mappings | Admin admin.discord.manage | Mapping PLAN/PRODUCT/ORG_ROLE → Discord-Rolle |
GET/POST | /api/admin/discord/group-roles | Admin admin.discord.manage | Gruppe → Discord-Rolle |
Permission-Key-Muster:
admin.{resource}.{action}(z. B.admin.licenses.manage). Store-Sichtbarkeit überstore.product.<key>.
9. Nexus-Modul-Registry & Entitlements
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/admin/modules | Admin admin.licenses.view | Lizenzierbare Module (kind CORE/MODULE, premium, active) |
POST | /api/admin/modules | Admin admin.modules.manage | Modul registrieren — ohne Java-Codeänderung (data-driven) |
PATCH/DELETE | /api/admin/modules/[id] | Admin admin.modules.manage | Modul ändern/deaktivieren |
GET/POST | /api/admin/licenses/[id]/modules | Admin | Modul-Grants einer Lizenz lesen/grant/revoke |
Dieses datengetriebene Registry ist das Herzstück der Lizenzintegration: Das ACP
selbst ist als kind=CORE modelliert, jedes Plugin als kind=MODULE; beliebig
viele Module lassen sich hinzufügen. Die aufgelöste Modul-Liste wird als
modules[]-Claim ins signierte Entitlement geschrieben. Siehe
Module lizenzieren & verkaufen.
10. Buchhaltung, Sales, Metriken & Admin
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/admin/accounting | Admin admin.accounting.view | Doppelte Buchführung: Salden, Transaktionen, Umsatz/Deferred/Refunds |
GET/POST | /api/admin/sales | Admin admin.products.* | Rabatte (PERCENTAGE/FIXED_AMOUNT), global oder produktspezifisch |
GET/PATCH/DELETE | /api/admin/sales/[id] | Admin | Sale-Detail/ändern/löschen |
GET | /api/admin/metrics/revenue | Admin admin.metrics.view | Umsatz über Zeit |
GET | /api/admin/metrics/usage | Admin admin.metrics.view | Nutzung (aktive User/Lizenzen, Downloads) |
POST | /api/admin/metrics/recompute | Admin admin.metrics.manage | Metriken neu berechnen |
GET/PATCH | /api/admin/users, /api/admin/users/[id] | Admin admin.users.* | User-Suche / Rolle ändern |
POST | `/api/admin/users/[id]/suspend | unsuspend | delete |
GET | /api/admin/audit | Admin admin.audit.view | Audit-Log aller Admin-Aktionen |
GET/POST | /api/admin/security-flags, /[id]/resolve | Admin admin.licenses.* | Verdächtige Lizenz-Aktivität |
Support, Notifications, DSGVO
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
GET | /api/notifications | Session | Benachrichtigungen (LICENSE_EXPIRING_SOON, TICKET_REPLY…) |
GET/POST | /api/portal/support/tickets[/id] | Session | Tickets auflisten/erstellen/antworten |
GET/POST | /api/admin/support/tickets… | Admin admin.support.* | Tickets verwalten/beantworten |
POST | /api/portal/account-deletion | Session | Kontolöschung beantragen |
GET | /api/portal/data-export | Session | DSGVO-Datenexport |
POST | /api/cron/data-retention | CRON_SECRET | Abgelaufene Sessions/Tokens/Logs aufräumen |
11. Datenmodell (Prisma)
Zentrale Entitäten und Relationen (Auszug):
Identität: User (email unique, role, emailVerifiedAt) ─ Session,
UserTwoFactor, UserDiscord, Passkey, EmailVerificationToken,
PasswordResetToken, AuditLog.
Lizenzierung: License (key unique, product?/productId?, plan,
status ∈ ACTIVE/SUSPENDED/EXPIRED/REVOKED, expiresAt?, maxServers?) ─
LicenseBinding (serverId, lastSeenAt), LicenseEvent, LicenseOwnership
(USER/ORG), LicenseModuleGrant → NexusModule (moduleId unique, kind
CORE/MODULE, premium).
Katalog: Product (key/slug unique, category, productType, status) ─
ProductPriceTier (priceEur, durationDays?, featuresJson, maxServers?),
ProductBundleItem, ProductGroupGrant, ProductChannelGrant, Release
(version, channel, status, artifactKey, sha256), ProductDefault,
DownloadLog.
Commerce: Order (status ∈ CREATED/PENDING/ACTIVE/FAILED/CANCELLED/ REFUNDED, paypalOrderId?) ─ Payment (provider PAYPAL, status,
amount), Invoice (invoiceNumber unique), WebhookEvent (eventId unique).
Buchhaltung: LedgerAccount (code, type ASSET/LIABILITY/REVENUE/ EXPENSE) ─ LedgerTransaction (referenceType ORDER/PAYMENT/REFUND/MANUAL) ─
LedgerEntry (debit/credit, doppelte Buchung: Soll = Haben). Sale
(saleType PERCENTAGE/FIXED_AMOUNT).
Organisationen: Organization (slug unique) ─ OrgMember (role
OWNER/ADMIN/SUPPORT/BILLING), OrgGroup, OrgGroupMember,
OrgGroupPermission, OrgInvite (7-Tage-TTL), OrgApiKey.
Rechte: Group (name/slug unique, weight, isSystem) ─ Permission
(key unique), GroupPermission, UserGroup, GroupDiscordRole.
DiscordRoleMapping (type PLAN/PRODUCT/ORG_ROLE), DiscordSyncJob.
Sonstiges: OutboxEvent (transaktionaler Outbox-Pattern), UserNotification,
SupportTicket/Reply, AccountDeletionRequest, SecurityFlag, SiteSetting,
StoreItem/StoreItemPermission.
12. Konventionen
| Aspekt | Wert |
|---|---|
| Validierung | Zod (E-Mail lowercased, Passwort 10–128, semver-/sha256-/uuid-/slug-Regex) |
| Pagination | ?page= (1-indexiert), ?limit= (1–200); Antwort { items, pagination } |
| Rate-Limits | Login/Register 10/min, Activate 15/min, Verify 30/min, Webhook 60/min, Download 5/s |
| Fehlercodes | 400 Validation, 401 Auth, 403 Forbidden/Channel/Plan-Limit, 404 Not-Found, 409 Konflikt, 500 Config/Intern |
| Audit | Admin-Aktionen → AuditLog; Lizenz-Statuswechsel → LicenseEvent |
| Patterns | Transaktionaler Outbox, doppelte Buchführung, Single-Use-Download-Tokens, Permission-RBAC |
Beispiel: Admin-Aufruf mit Permission
# Session-Cookie + Permission admin.licenses.view erforderlich
curl https://test.jubyte.com/api/admin/[email protected] \
-H "Cookie: $SESSION_COOKIE" | jq '.licenses[] | {key, status, plan}'
Siehe auch
- Lizenz-API & Entitlement-Vertrag – RS256-JWS-Details
- Module lizenzieren & verkaufen
- Core-API – Gegenstück im Nexus Core