Kit stellt 34 REST-API-Endpunkte in 11 Kategorien bereit. Jeder Endpunkt verwendet Next.js App-Router-Route-Handler — es gibt keine Server Actions. Alle Requests und Responses verwenden JSON, sofern nicht anders angegeben (Datei-Uploads verwenden Raw-Streams).
Diese Seite ist eine Nachschlagereferenz. Für den architektonischen Kontext siehe Sicherheitsübersicht. Für endpunkt-spezifische Anleitungen folge den Links in den jeweiligen Abschnitten.
Schnellübersicht
Alle Endpunkte auf einen Blick. Klicke auf einen Pfad, um zum detaillierten Abschnitt zu springen.
| Pfad | Methode(n) | Auth | Rate-Limit | Beschreibung |
|---|---|---|---|---|
/api/user/status | GET | Clerk | api | Aktueller Abonnementstatus des Nutzers |
/api/checkout/create-url | POST | Clerk | payments | Lemon Squeezy Checkout-URL erstellen |
/api/payments/create-checkout | POST, GET | Clerk | payments | Checkout-Session mit Optionen erstellen |
/api/payments/cancel-subscription | POST | Clerk | payments | Aktives Abonnement kündigen |
/api/payments/change-plan | POST | Clerk | payments | Plan upgraden oder downgraden |
/api/payments/create-portal-session | POST | Clerk | — | Kundenportal-URL generieren |
/api/payments/customer-portal | POST | Clerk | payments | Kundenportal-Weiterleitung |
/api/payments/subscription | GET | Clerk | — | Aktuelle Abonnementdetails |
/api/credits/bonus-packages | GET | Clerk | api | Verfügbare Bonus-Credit-Pakete |
/api/credits/checkout | POST | Clerk | payments | Bonus-Credit-Checkout-URL erstellen |
/api/credits/history | GET | Clerk | api | Paginierte Credit-Transaktionshistorie |
/api/credits/preferences | GET | Clerk | api | Bonus-Credit-Einstellung abrufen |
/api/credits/preferences | PATCH | Clerk | api | Bonus-Credit-Einstellung aktualisieren |
/api/config/public | GET | — | — | Öffentliche Preiskonfiguration |
/api/pricing/config | GET | — | — | Vollständige Preiskonfiguration mit Validierung |
/api/ai/chat | POST | Clerk | credits | Synchrone KI-Vervollständigung |
/api/ai/stream | POST | Clerk | credits | Streaming-KI-Vervollständigung (SSE) |
/api/ai/usage | GET | Clerk | — | KI-Nutzungsstatistiken und Limits |
/api/ai/speech-to-text | POST | Clerk | credits | Audio-Transkription (Whisper STT) |
/api/ai/image-gen | POST | Clerk | credits | KI-Bildgenerierung (GPT Image) |
/api/ai/generate-content | POST | Clerk | credits | Template-basierte Content-Generierung (SSE) |
/api/ai/rag/ask | POST | Clerk | credits | RAG-gestützte Frage & Antwort |
/api/ai/rag/conversations | GET, DELETE | Clerk | — | Konversationen auflisten oder löschen |
/api/ai/rag/conversations/[id] | GET | Clerk | — | Einzelne Konversation mit Nachrichten |
/api/upload | POST | Clerk | upload | Datei in Vercel Blob hochladen |
/api/files/[id] | GET, DELETE | Clerk | — | Hochgeladene Datei abrufen oder löschen |
/api/email/send | POST | Clerk | Transaktionale E-Mail senden | |
/api/email/test | POST | Clerk | — | Test-E-Mail senden (nur Dev) |
/api/webhooks/clerk | POST | Svix | webhooks | Clerk-Nutzer-Lifecycle-Events |
/api/webhooks/lemonsqueezy | POST | HMAC | webhooks | Zahlungs- und Abonnement-Events |
/api/webhooks/resend | POST | HMAC | webhooks | E-Mail-Zustellungsstatus-Events |
/api/cron/check-trials | POST, GET | Bearer | — | Abgelaufene Trial-Abonnements beenden |
/api/cron/expire-bonus-credits | POST, GET | Bearer | — | Bonus-Credit-Käufe ablaufen lassen |
/api/health | GET | — | — | Anwendungs-Health-Check |
Rate-Limit-Kategorien
Jeder Rate-limitierte Endpunkt gehört einer von sechs Kategorien an. Rate-Limits werden pro Nutzer und/oder pro IP mithilfe von Upstash Redis durchgesetzt:
Rate-Limit-Konfiguration pro Kategorie
const API_LIMITS: Record<
APICategory,
{ user?: RateLimitConfig; ip?: RateLimitConfig }
> = {
upload: {
user: { requests: 10, window: '1 h', identifier: 'user' },
ip: { requests: 20, window: '1 h', identifier: 'ip' },
},
email: {
user: { requests: 5, window: '1 h', identifier: 'user' },
ip: { requests: 10, window: '1 h', identifier: 'ip' },
},
contact: {
ip: { requests: 3, window: '1 h', identifier: 'ip' },
},
payments: {
user: { requests: 20, window: '1 h', identifier: 'user' },
},
webhooks: {
ip: { requests: 100, window: '1 h', identifier: 'ip' },
},
api: {
user: { requests: 100, window: '1 h', identifier: 'user' },
ip: { requests: 200, window: '1 h', identifier: 'ip' },
},
}
Wenn Redis nicht verfügbar ist, wird Rate-Limiting umgangen und Anfragen werden durchgelassen. Dadurch wird verhindert, dass Infrastrukturprobleme legitime Nutzer blockieren. Überwache in Produktions-Logs auf
"Rate limiting disabled"-Warnungen.KI-Endpunkte verwenden ein separates Credit-basiertes Rate-Limiting-System — siehe Kostenmanagement für Details.
Authentifizierung & Nutzer
Nutzerstatus abrufen {#get-user-status}
GET
/api/user/statusGibt den Abonnementstatus des authentifizierten Nutzers für die personalisierte UI-Anzeige zurück (z.B. dynamische CTA-Buttons auf der Preisseite).
- Auth: Clerk (erforderlich)
- Rate-Limit:
api— 100 Anfragen/Stunde pro Nutzer - Cache: 5 Minuten (
private, max-age=300)
Response (200):
json
{
"status": "active_subscriber",
"tier": "pro",
"billingPeriod": "monthly",
"isTrial": false,
"needsAction": false,
"isLocked": false
}
Fehlercodes:
401 Unauthorized, 429 Rate-limitiert, 500 ServerfehlerZahlungen
Acht Endpunkte verwalten den vollständigen Zahlungslebenszyklus — von der Checkout-Erstellung bis zur Abonnementverwaltung.
Alle Zahlungsendpunkte verwenden die
payments-Rate-Limit-Kategorie (20 Anfragen/Stunde pro Nutzer). Für Details zur Zahlungsarchitektur siehe Zahlungsübersicht.Checkout-URL erstellen {#create-checkout-url}
POST
/api/checkout/create-urlErstellt eine Lemon Squeezy Checkout-URL für eine bestimmte Plan-Variante.
- Auth: Clerk (erforderlich)
- Rate-Limit:
payments
Request-Body:
json
{
"variantId": "123456",
"tier": "pro"
}
Response (200):
json
{
"checkoutUrl": "https://nextsaas.lemonsqueezy.com/checkout/..."
}
Fehlercodes:
400 Ungültige Variante/Stufe, 401 Unauthorized, 429 Rate-limitiert, 500 ServerfehlerCheckout-Session erstellen {#create-checkout-session}
POSTGET
/api/payments/create-checkoutErstellt eine Checkout-Session mit erweiterten Optionen, einschließlich Weiterleitungs-URLs und Rabattcodes.
- Auth: Clerk (erforderlich)
- Rate-Limit:
payments
Request-Body:
json
{
"variantId": "123456",
"productId": "789",
"redirectUrl": "https://yourapp.com/success",
"cancelUrl": "https://yourapp.com/cancel",
"discountCode": "LAUNCH20"
}
Nur
variantId ist erforderlich. Alle anderen Felder sind optional.Response (200):
json
{
"checkoutUrl": "https://nextsaas.lemonsqueezy.com/checkout/..."
}
Dieser Endpunkt unterstützt auch GET-Anfragen mit den Query-Parametern
tier und billing für den Registrierungs-First-Checkout-Flow:GET /api/payments/create-checkout?tier=pro&billing=annual
→ 302 Weiterleitung zu Lemon Squeezy Checkout
Fehlercodes:
400 Validierung fehlgeschlagen, 401 Unauthorized, 404 Nutzer nicht gefunden, 500 ServerfehlerAbonnement kündigen {#cancel-subscription}
POST
/api/payments/cancel-subscriptionKündigt das aktive Abonnement des Nutzers. Das Abonnement bleibt bis zum Ende des aktuellen Abrechnungszeitraums aktiv.
- Auth: Clerk (erforderlich)
- Rate-Limit:
payments
Request-Body: Keiner erforderlich.
Response (200):
json
{
"message": "Subscription cancelled successfully",
"endsAt": "2026-03-14T00:00:00.000Z"
}
Fehlercodes:
401 Unauthorized, 404 Kein aktives Abonnement, 500 ServerfehlerAbonnementplan wechseln {#change-subscription-plan}
POST
/api/payments/change-planUpgradet oder downgradet das Abonnement des Nutzers auf eine andere Plan-Variante.
- Auth: Clerk (erforderlich)
- Rate-Limit:
payments
Request-Body:
json
{
"newVariantId": "654321"
}
Response (200):
json
{
"success": true,
"message": "Plan changed successfully",
"newVariantId": "654321",
"subscription": {
"status": "active",
"currentPeriodEnd": "2026-03-14T00:00:00.000Z"
}
}
Während einer Testphase können Nutzer maximal 2 Mal downgraden. Der
downgradeCount wird im Nutzereintrag verfolgt. Nach 2 Downgrades werden weitere Downgrade-Versuche blockiert, bis die Testphase endet.Fehlercodes:
400 Ungültige Variante oder Downgrade-Limit erreicht, 401 Unauthorized, 404 Kein Abonnement, 500 ServerfehlerPortal-Session erstellen {#create-portal-session}
POST
/api/payments/create-portal-sessionGeneriert eine Lemon Squeezy Kundenportal-URL, über die Nutzer die Abrechnung verwalten, Zahlungsmethoden aktualisieren und Rechnungen einsehen können.
- Auth: Clerk (erforderlich)
- Rate-Limit: —
Response (200):
json
{
"url": "https://nextsaas.lemonsqueezy.com/billing/..."
}
Die Portal-URL ist 24 Stunden gültig.
Fehlercodes:
401 Unauthorized, 404 Kein Abonnement, 500 ServerfehlerKundenportal-Zugang {#customer-portal-access}
POST
/api/payments/customer-portalAlternativer Endpunkt für den Kundenportal-Zugang. Gibt die Portal-URL in einem
portalUrl-Feld zurück.- Auth: Clerk (erforderlich)
- Rate-Limit:
payments
Response (200):
json
{
"portalUrl": "https://nextsaas.lemonsqueezy.com/billing/..."
}
Fehlercodes:
401 Unauthorized, 404 Kein Abonnement, 500 ServerfehlerAbonnementdetails abrufen {#get-subscription-details}
GET
/api/payments/subscriptionGibt die aktuellen Abonnementdetails des Nutzers zurück, einschließlich Plan-Stufe, Abrechnungszeitraum, Feature-Limits und Teststatus.
- Auth: Clerk (erforderlich)
- Rate-Limit: —
- Cache: 60 Sekunden
Response (200):
json
{
"subscription": {
"id": "sub_123",
"status": "active",
"variantId": "123456",
"currentPeriodEnd": "2026-03-14T00:00:00.000Z"
},
"hasActiveSubscription": true,
"tier": "pro",
"billingPeriod": "monthly",
"planName": "Pro",
"isFreePlan": false,
"user": {
"downgradeCount": 0,
"hasUsedTrial": true
},
"limits": {}
}
Gibt
subscription: null und isFreePlan: true für Nutzer ohne aktives Abonnement zurück.Fehlercodes:
401 Unauthorized, 404 Nutzer nicht gefunden, 500 ServerfehlerZahlungsstatus debuggen {#debug-payment-status}
GET
/api/payments/debugNur-Entwicklungs-Endpunkt, der detaillierte Debug-Informationen über den Zahlungsstatus des Nutzers zurückgibt.
- Auth: Clerk (erforderlich) oder
?key=debug-Query-Parameter in der Entwicklung - Rate-Limit: —
Dieser Endpunkt ist ausschließlich für das Debugging in der Entwicklung gedacht. Er legt internen Abonnementstatus und Umgebungskonfiguration offen. Mache ihn in der Produktion niemals für Endnutzer zugänglich.
Fehlercodes:
401 Unauthorized, 500 ServerfehlerCredits
Vier Endpunkte verwalten Bonus-Credit-Pakete und Einstellungen — das Auflisten verfügbarer Pakete, das Erstellen von Checkout-Sessions, das Anzeigen der Transaktionshistorie und die Verwaltung nutzerspezifischer Bonus-Credit-Einstellungen. Diese sind nur im Credit-basierten Preismodus verfügbar.
Diese Endpunkte erfordern
NEXT_PUBLIC_PRICING_MODEL=credit_based und NEXT_PUBLIC_BONUS_CREDITS_ENABLED=true. Wenn eine der Bedingungen falsch ist, geben sie 404 zurück. Für die Credit-System-Architektur siehe Credit-System.Bonus-Pakete auflisten {#list-bonus-packages}
GET
/api/credits/bonus-packagesGibt die für die Abonnement-Stufe des authentifizierten Nutzers verfügbaren Bonus-Credit-Pakete zurück, zusammen mit monatlichen Kauflimits und der aktuellen Nutzung.
- Auth: Clerk (erforderlich)
- Rate-Limit:
api— 100 Anfragen/Stunde pro Nutzer
Response (200):
json
{
"enabled": true,
"packages": [
{
"credits": 500,
"price": 9.99,
"variantId": "334455"
},
{
"credits": 1000,
"price": 19.99,
"variantId": "334456"
}
],
"monthlyLimit": 2000,
"monthlyPurchasedCredits": 500,
"canPurchaseMore": true,
"tier": "pro"
}
| Feld | Typ | Beschreibung |
|---|---|---|
enabled | boolean | Immer true, wenn der Endpunkt 200 zurückgibt |
packages | array | Verfügbare Pakete für die Stufe des Nutzers (bis zu 2 pro Stufe) |
monthlyLimit | number | Maximal pro Kalendermonat kaufbare Bonus-Credits |
monthlyPurchasedCredits | number | In diesem Monat bereits gekaufte Bonus-Credits |
canPurchaseMore | boolean | Ob der Nutzer unter dem monatlichen Kauflimit liegt |
tier | string | Aktuelle Abonnement-Stufe des Nutzers |
Free-Tier-Nutzer können keine Bonus-Credits kaufen — sie erhalten ein leeres
packages-Array mit monthlyLimit: 0.Fehlercodes:
401 Unauthorized, 404 Feature deaktiviert oder nicht Credit-basiert, 429 Rate-limitiert, 500 ServerfehlerCredit-Checkout erstellen {#create-credit-checkout}
POST
/api/credits/checkoutErstellt eine Lemon Squeezy Checkout-URL für den Kauf eines Bonus-Credit-Pakets. Validiert die Variant-ID gegen die Stufenpakete des Nutzers und setzt monatliche Kauflimits durch.
- Auth: Clerk (erforderlich)
- Rate-Limit:
payments— 20 Anfragen/Stunde pro Nutzer
Request-Body (Zod-validiert):
json
{
"variantId": "334455"
}
Response (200):
json
{
"checkoutUrl": "https://nextsaas.lemonsqueezy.com/checkout/..."
}
Nach erfolgreicher Zahlung wird der Nutzer zu
/dashboard/credits?purchase=success weitergeleitet. Der order_created-Webhook verarbeitet den Kauf asynchron.Fehlercodes:
400 Ungültige Variant-ID oder nicht in Stufenpaketen, 401 Unauthorized, 403 Monatliches Kauflimit erreicht, 404 Feature deaktiviert oder nicht Credit-basiert, 429 Rate-limitiert, 500 ServerfehlerCredit-Verlauf abrufen {#get-credit-history}
GET
/api/credits/historyGibt eine paginierte Liste der Credit-Transaktionen für den authentifizierten Nutzer zurück, gefiltert nach Jahr.
- Auth: Clerk (erforderlich)
- Rate-Limit:
api— 100 Anfragen/Stunde pro Nutzer - Cache: 60 Sekunden (
private, max-age=60)
Query-Parameter:
| Parameter | Typ | Standard | Einschränkungen | Beschreibung |
|---|---|---|---|---|
limit | number | 50 | 1–100 | Anzahl der Transaktionen pro Seite |
offset | number | 0 | >= 0 | Paginierungs-Offset |
year | number | Aktuelles Jahr | 2000–aktuell+1 | Nach Kalenderjahr filtern |
Response (200):
json
{
"transactions": [
{
"id": "tx_abc123",
"amount": -1.5,
"balanceAfter": 848.5,
"type": "usage",
"operation": "chat_streaming",
"metadata": { "model": "gpt-5-nano" },
"createdAt": "2026-02-14T10:30:00.000Z"
}
],
"totalCount": 153,
"availableYears": [2025, 2026]
}
| Feld | Typ | Beschreibung |
|---|---|---|
transactions | array | Credit-Transaktionseinträge, neueste zuerst |
totalCount | number | Gesamtanzahl der Transaktionen, die dem Jahresfilter entsprechen |
availableYears | number[] | Jahre mit mindestens einer Transaktion (aufsteigend) |
Der
amount einer Transaktion ist negativ bei Abbuchungen und positiv bei Credits (Käufe, Erstattungen, Resets). Das type-Feld identifiziert die Kategorie: usage, purchase, refund, monthly_reset oder adjustment.Fehlercodes:
401 Unauthorized, 429 Rate-limitiert, 500 ServerfehlerCredit-Einstellungen abrufen {#get-credit-preferences}
GET
/api/credits/preferencesGibt die Bonus-Credit-Automatiknutzungs-Einstellung des Nutzers und den Feature-Toggle-Status zurück. Nur verfügbar, wenn Credit-basierte Preisgestaltung aktiv ist.
- Auth: Clerk (erforderlich)
- Rate-Limit:
api— 100 Anfragen/Stunde pro Nutzer - Guard: Gibt
404zurück, wenn nicht im Credit-basierten Preismodus
Response (200):
json
{
"bonusCreditsAutoUse": false,
"userToggleEnabled": true
}
| Feld | Typ | Beschreibung |
|---|---|---|
bonusCreditsAutoUse | boolean | Ob der Nutzer den automatischen Bonus-Credit-Verbrauch aktiviert hat |
userToggleEnabled | boolean | Ob der nutzerspezifische Toggle systemweit aktiviert ist |
Fehlercodes:
401 Unauthorized, 404 Nicht Credit-basiert, 429 Rate-limitiert, 500 ServerfehlerCredit-Einstellungen aktualisieren {#update-credit-preferences}
PATCH
/api/credits/preferencesAktualisiert die Bonus-Credit-Automatiknutzungs-Einstellung des Nutzers. Nur verfügbar, wenn sowohl Credit-basierte Preisgestaltung als auch der Nutzer-Toggle aktiviert sind.
- Auth: Clerk (erforderlich)
- Rate-Limit:
api— 100 Anfragen/Stunde pro Nutzer - Guard: Gibt
404zurück, wenn nicht Credit-basiert,403wenn Nutzer-Toggle-Feature deaktiviert ist - Validierung:
bonusPreferencesSchema
Request-Body:
json
{
"bonusCreditsAutoUse": true
}
Response (200):
json
{
"success": true,
"bonusCreditsAutoUse": true
}
Fehlercodes:
400 Ungültiger Request-Body, 401 Unauthorized, 403 Nutzer-Toggle nicht aktiviert, 404 Nicht Credit-basiert, 429 Rate-limitiert, 500 ServerfehlerKonfiguration
Öffentliche Konfiguration abrufen {#get-public-config}
GET
/api/config/publicGibt die öffentliche Preiskonfiguration zurück. Wird von der Preisseite und den Checkout-Flows verwendet, um aktuelle Pläne, Preise und Features anzuzeigen.
- Auth: Keine
- Rate-Limit: Keines
- Cache: 1 Stunde (
public, max-age=3600) - Runtime: Edge
Response (200):
json
{
"model": "credit_based",
"currency": "EUR",
"tiers": [
{ "key": "basic", "name": "Basic", "monthlyPrice": 9.90 },
{ "key": "pro", "name": "Pro", "monthlyPrice": 19.90 },
{ "key": "enterprise", "name": "Enterprise", "monthlyPrice": 39.90 }
],
"features": { "freeTierEnabled": true },
"tierVisibility": {}
}
Die Response-Struktur variiert je nach aktivem Preismodell (
credit_based oder classic_saas). Credit-basierte Responses enthalten creditBased-Felder; Classic-SaaS-Responses enthalten classicSaas-Felder.Preiskonfiguration abrufen {#get-pricing-config}
GET
/api/pricing/configGibt die vollständige Preiskonfiguration mit serverseitiger Validierung zurück. Stellt sicher, dass alle erforderlichen Umgebungsvariablen gesetzt sind, bevor eine Antwort zurückgegeben wird.
- Auth: Keine
- Rate-Limit: Keines
- Cache: 60 Sekunden (
must-revalidate)
Fehlercodes:
500 Unvollständige Konfiguration (fehlende Umgebungsvariablen)KI-Chat
Sechs Endpunkte betreiben das Standard-KI-System (ohne RAG): synchrone Vervollständigungen, Streaming, Sprache-zu-Text, Nutzungsverfolgung, Bildgenerierung und Content-Generierung.
KI-Chat-Vervollständigung {#ai-chat-completion}
POST
/api/ai/chatGeneriert KI-Vervollständigungen synchron. Unterstützt einzelne Anfragen und Batch-Modus (bis zu 10 gleichzeitige Anfragen).
- Auth: Clerk (erforderlich)
- Rate-Limit: Credit-basiert (15 Credits pro Anfrage)
- Feature-Guard: Gibt
404zurück, wennNEXT_PUBLIC_AI_LLM_CHAT_ENABLEDfalseist
Request-Body (Zod-validiert):
ChatRequestSchema — Request-Validierung
const ChatRequestSchema = z.object({
messages: z.array(
z.object({
role: z.enum(['system', 'user', 'assistant', 'function', 'tool']),
content: z.string(),
name: z.string().optional(),
})
),
model: z.string().optional(),
temperature: z.number().min(0).max(2).optional(),
maxTokens: z.number().positive().optional(),
systemPrompt: z.string().optional(),
context: z.string().optional(),
// Optional caching control
cache: z.boolean().optional(),
cacheTTL: z.number().positive().optional(),
})
Response (200):
json
{
"text": "The AI response content...",
"model": "gpt-5-nano",
"usage": { "promptTokens": 150, "completionTokens": 80 },
"cost": 15
}
Fehlercodes:
400 Validierung fehlgeschlagen, 401 Unauthorized, 402 Nicht genügend Credits, 429 Rate-limitiert, 500 ServerfehlerKI-Streaming-Vervollständigung {#ai-streaming-completion}
POST
/api/ai/streamGeneriert KI-Vervollständigungen mit Server-Sent Events (SSE) Streaming. Unterstützt reine Text- und multimodale (Vision) Anfragen über das
ContentPart[]-Nachrichtenformat.- Auth: Clerk (erforderlich)
- Rate-Limit: Credit-basiert (20 Credits für Text, 30 Credits für Bildanalyse — automatisch erkannt)
- Response-Typ:
text/event-stream
Request-Body (nur Text):
json
{
"messages": [{ "role": "user", "content": "Hello" }],
"model": "gpt-5-nano",
"temperature": 0.7,
"maxTokens": 1000,
"systemPrompt": "You are a helpful assistant."
}
Request-Body (multimodal mit Bildern):
json
{
"messages": [{
"role": "user",
"content": [
{ "type": "image", "image": "data:image/png;base64,..." },
{ "type": "text", "text": "Describe this image" }
]
}]
}
Response: SSE-Stream mit
X-RateLimit-*-Headern.Fehlercodes:
400 Validierung fehlgeschlagen, 401 Unauthorized, 402 Nicht genügend Credits, 429 Rate-limitiert, 500 ServerfehlerKI-Nutzungsstatistiken abrufen {#get-ai-usage-stats}
GET
/api/ai/usageGibt KI-Nutzungsstatistiken und verbleibende Limits für den authentifizierten Nutzer zurück.
- Auth: Clerk (erforderlich)
- Rate-Limit: —
Response (200) — Credit-System aktiviert:
json
{
"unlimited": false,
"tier": "pro",
"monthlyLimit": 5000,
"remaining": 4847,
"bonusCredits": 50,
"used": 153,
"resetAt": "2026-02-01T00:00:00.000Z"
}
Response (200) — Credit-System deaktiviert (Classic SaaS):
json
{
"unlimited": true,
"tier": "unlimited",
"monthlyLimit": 999999,
"remaining": 999999,
"bonusCredits": 0,
"used": 0
}
| Feld | Typ | Beschreibung |
|---|---|---|
unlimited | boolean | true, wenn das Credit-System deaktiviert ist (Classic-SaaS-Modus) |
tier | string | Abonnement-Stufe (free, basic, pro, enterprise) oder "unlimited" |
monthlyLimit | number | Monatliche Credit-Zuteilung für die Stufe des Nutzers |
remaining | number | Verfügbare Abonnement-Credits in diesem Abrechnungszeitraum |
bonusCredits | number | Gekaufte Bonus-Credits (getrennt von der Abonnement-Zuteilung) |
used | number | In diesem Abrechnungszeitraum verbrauchte Credits (monthlyLimit - remaining) |
resetAt | string? | ISO-8601-Zeitstempel des letzten Credit-Resets (fehlt, wenn Credit-System deaktiviert) |
Fehlercodes:
401 Unauthorized, 404 Nutzer nicht gefunden, 500 ServerfehlerSprache zu Text {#speech-to-text}
POST
/api/ai/speech-to-textTranskribiert Audioaufnahmen mithilfe der OpenAI-Whisper-API. Wird vom Audio-Eingabe-Feature im LLM-Chat verwendet.
- Auth: Clerk (erforderlich)
- Rate-Limit: Credit-basiert (20 Credits pro Transkription)
- Content-Typ:
multipart/form-data - Feature-Guard: Gibt
404zurück, wennNEXT_PUBLIC_AI_AUDIO_INPUT_ENABLEDfalseist
Request-Body:
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
audio | File | Ja | Audiodatei (WebM, WAV, MP3, M4A, OGG, FLAC — max. 25 MB) |
Response (200):
json
{
"text": "The transcribed text content...",
"language": "en",
"duration": 5.2
}
| Feld | Typ | Beschreibung |
|---|---|---|
text | string | Aus dem Audio transkribierter Text |
language | string | Erkannter Sprachcode (ISO 639-1) |
duration | number | Audiodauer in Sekunden |
Fehlercodes:
400 Keine Audiodatei angegeben oder ungültiges Format, 401 Unauthorized, 402 Nicht genügend Credits, 404 Feature deaktiviert, 413 Datei zu groß (> 25 MB), 500 ServerfehlerKI-Bildgenerierung {#ai-image-generation}
POST
/api/ai/image-genGeneriert Bilder mithilfe der OpenAI-GPT-Image-API. Unterstützt mehrere Modelle, Größen, Qualitätsstufen und Ausgabeformate.
- Auth: Clerk (erforderlich)
- Rate-Limit: Credit-basiert (80 Credits pro Generierung)
- Feature-Guard: Gibt
404zurück, wennNEXT_PUBLIC_AI_IMAGE_GEN_ENABLEDfalseist - Maximale Dauer: 60 Sekunden
Request-Body (Zod-validiert):
json
{
"prompt": "A mountain landscape at sunset",
"model": "gpt-image-1",
"size": "1024x1024",
"quality": "auto",
"output_format": "png",
"background": "opaque"
}
| Feld | Typ | Pflicht | Standard | Optionen |
|---|---|---|---|---|
prompt | string | Ja | — | 1–4000 Zeichen |
model | string | Nein | gpt-image-1 | gpt-image-1, gpt-image-1.5, gpt-image-1-mini |
size | string | Nein | 1024x1024 | 1024x1024, 1536x1024, 1024x1536, auto |
quality | string | Nein | auto | low, medium, high, auto |
output_format | string | Nein | png | png, jpeg, webp |
background | string | Nein | opaque | opaque, transparent |
Transparenter Hintergrund wird nur mit den Formaten PNG und WebP unterstützt. Das Anfordern von
background: "transparent" mit output_format: "jpeg" gibt einen 400-Fehler zurück.Response (200):
json
{
"image": "data:image/png;base64,...",
"model": "gpt-image-1",
"size": "1024x1024",
"quality": "auto",
"format": "png",
"revised_prompt": "A detailed mountain landscape...",
"credits_used": 80,
"credits_remaining": 4920
}
Fehlercodes:
400 Validierung fehlgeschlagen oder Verletzung der Content-Richtlinien, 401 Unauthorized, 402 Nicht genügend Credits, 404 Feature deaktiviert, 429 Rate-limitiert, 500 ServerfehlerKI-Content-Generierung {#ai-content-generation}
POST
/api/ai/generate-contentGeneriert Template-basierten Textinhalt mit Server-Sent Events (SSE) Streaming. Unterstützt fünf Content-Templates mit konfigurierbarem Ton, Sprache und Länge.
- Auth: Clerk (erforderlich)
- Rate-Limit: Credit-basiert (25 Credits pro Generierung)
- Response-Typ:
text/event-stream - Feature-Guard: Gibt
404zurück, wennNEXT_PUBLIC_AI_CONTENT_GEN_ENABLEDfalseist - Maximale Dauer: 60 Sekunden
Request-Body (Zod-validiert):
json
{
"template": "email",
"fields": {
"recipient": "Customer",
"subject": "Welcome to our platform",
"key_points": "Introduction, features overview"
},
"tone": "professional",
"language": "en",
"length": "medium"
}
| Feld | Typ | Pflicht | Standard | Optionen |
|---|---|---|---|---|
template | string | Ja | — | email, product_description, blog_outline, social_media, marketing_copy |
fields | object | Ja | — | Template-spezifische Key-Value-Paare |
tone | string | Nein | professional | professional, friendly, persuasive, neutral |
language | string | Nein | en | de, en, fr, es |
length | string | Nein | medium | short, medium, long |
Response: SSE-Stream mit Content-Chunks, gefolgt von einem Meta-Event mit Credit-Informationen, dann
[DONE].Fehlercodes:
400 Validierung fehlgeschlagen oder fehlende erforderliche Template-Felder, 401 Unauthorized, 402 Nicht genügend Credits, 404 Feature deaktiviert, 429 Rate-limitiert, 500 ServerfehlerKI-RAG — Authentifiziert
Drei Endpunkte für das authentifizierte RAG-Chat-System (Retrieval-Augmented Generation) mit Konversationspersistenz.
RAG-Frage stellen {#ask-rag-question}
POST
/api/ai/rag/askStellt eine Frage an das RAG-System. Ruft relevante Dokumentfragmente ab, generiert eine kontextbewusste Antwort und persistiert die Konversation.
- Auth: Clerk (erforderlich)
- Rate-Limit: Credit-basiert (variiert je nach Anfragekomplexität)
- Feature-Guard: Gibt
404zurück, wennNEXT_PUBLIC_AI_RAG_CHAT_ENABLEDfalseist
Request-Body:
json
{
"question": "How do I configure authentication?",
"conversationId": "conv_abc123",
"stream": true
}
Akzeptiert entweder
question (String) oder messages (Vercel AI SDK-Format). Die conversationId ist optional — lass sie weg, um eine neue Konversation zu starten.Streaming-Response-Header:
X-RAG-Sources— Base64-kodierter JSON-String mit Quelldokument-ReferenzenX-RAG-Chunks-Used— Anzahl der abgerufenen ChunksX-RAG-Tokens-Estimated— Geschätzte Token-Anzahl
Fehlercodes:
400 Frage fehlt, 401 Unauthorized, 402 Nicht genügend Credits, 500 ServerfehlerRAG-Konversationen auflisten {#list-rag-conversations}
GETDELETE
/api/ai/rag/conversationsListet die RAG-Konversationen des Nutzers mit Paginierung auf.
- Auth: Clerk (erforderlich)
- Rate-Limit: —
Query-Parameter:
limit— Anzahl der Konversationen (Standard:20)offset— Paginierungs-Offset (Standard:0)
Response (200):
json
{
"conversations": [
{
"id": "conv_abc123",
"title": "Authentication Setup",
"messageCount": 5,
"lastMessage": "You can configure...",
"createdAt": "2026-02-14T10:00:00.000Z"
}
],
"pagination": { "total": 12, "limit": 20, "offset": 0, "hasMore": false }
}
Die DELETE-Methode auf demselben Pfad löscht eine Konversation:
DELETE /api/ai/rag/conversations?id=conv_abc123
→ { "success": true, "deleted": 1 }
Fehlercodes:
400 ID fehlt (DELETE), 401 Unauthorized, 404 Nicht gefunden, 500 ServerfehlerRAG-Konversation abrufen {#get-rag-conversation}
GET
/api/ai/rag/conversations/[id]Gibt eine einzelne Konversation mit allen ihren Nachrichten zurück.
- Auth: Clerk (erforderlich)
- Rate-Limit: —
Response (200):
json
{
"id": "conv_abc123",
"title": "Authentication Setup",
"tier": "pro",
"messages": [
{
"id": "msg_1",
"role": "user",
"content": "How do I configure authentication?",
"tokens": 8,
"model": "gpt-5-nano",
"createdAt": "2026-02-14T10:00:00.000Z"
}
]
}
Fehlercodes:
401 Unauthorized, 404 Konversation nicht gefunden, 500 ServerfehlerDateispeicherung
Datei hochladen {#upload-file}
POST
/api/uploadLädt eine Datei in Vercel Blob Storage hoch. Der Dateiinhalt wird direkt aus dem Request-Body gestreamt — keine Multipart-Formulardaten.
- Auth: Clerk (erforderlich)
- Rate-Limit:
upload— 10 Anfragen/Stunde pro Nutzer, 20 Anfragen/Stunde pro IP
Query-Parameter (erforderlich):
filename— Originaler Dateinamefilesize— Dateigröße in Bytesfiletype— MIME-Typ (z.B.image/png)
Request-Body: Roher Dateiinhalt als
ReadableStream.Response (200):
json
{
"id": "file_abc123",
"url": "https://blob.vercel-storage.com/...",
"originalName": "document.pdf",
"size": 245760,
"contentType": "application/pdf",
"createdAt": "2026-02-14T10:00:00.000Z"
}
Fehlercodes:
400 Fehlende Parameter oder ungültiger Dateityp, 401 Unauthorized, 409 Doppelte Datei, 503 Datenbankfehler, 500 ServerfehlerDatei abrufen oder löschen {#get-or-delete-file}
GETDELETE
/api/files/[id]Gibt Metadaten für eine bestimmte hochgeladene Datei zurück. Nur der Dateibesitzer kann darauf zugreifen.
- Auth: Clerk (erforderlich)
- Rate-Limit: —
Response (200):
json
{
"id": "file_abc123",
"url": "https://blob.vercel-storage.com/...",
"originalName": "document.pdf",
"size": 245760,
"contentType": "application/pdf",
"createdAt": "2026-02-14T10:00:00.000Z"
}
Die DELETE-Methode auf demselben Pfad entfernt die Datei sowohl aus Vercel Blob als auch aus der Datenbank:
DELETE /api/files/file_abc123
→ { "success": true, "message": "File deleted successfully" }
Fehlercodes:
401 Unauthorized, 404 Datei nicht gefunden, 500 ServerfehlerE-Mail senden {#send-email}
POST
/api/email/sendSendet eine transaktionale E-Mail über Resend. Erfordert entweder HTML- oder Klartext-Inhalt.
- Auth: Clerk (erforderlich)
- Rate-Limit:
email— 5 Anfragen/Stunde pro Nutzer, 10 Anfragen/Stunde pro IP
Request-Body:
json
{
"to": "user@example.com",
"subject": "Welcome to our platform",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
"type": "welcome"
}
Entweder
html oder text muss angegeben werden.Response (200):
json
{
"success": true,
"messageId": "msg_resend_123",
"emailLogId": "log_abc123"
}
Fehlercodes:
400 Validierung fehlgeschlagen, 401 Unauthorized, 404 Nutzer nicht gefunden, 500 ServerfehlerTest-E-Mail senden {#send-test-email}
POST
/api/email/testSendet eine Test-E-Mail für Entwicklung und Debugging. Nur in Nicht-Produktionsumgebungen verfügbar.
- Auth: Clerk (optional)
- Rate-Limit: —
Request-Body:
json
{
"email": "dev@example.com"
}
Fehlercodes:
400 E-Mail fehlt, 403 Nicht in der Entwicklung, 500 ServerfehlerWebhooks
Alle drei Webhook-Endpunkte verifizieren eingehende Signaturen, bevor Events verarbeitet werden. Sie verwenden die
webhooks-Rate-Limit-Kategorie (100 Anfragen/Stunde pro IP).Webhook-Secrets (
CLERK_WEBHOOK_SECRET, LEMONSQUEEZY_WEBHOOK_SECRET, RESEND_WEBHOOK_SECRET) müssen ausschließlich serverseitig bleiben. Versehe sie niemals mit dem NEXT_PUBLIC_-Präfix.Clerk-Webhook {#clerk-webhook}
POST
/api/webhooks/clerkVerarbeitet Clerk-Nutzer-Lifecycle-Events. Erstellt, aktualisiert oder löscht Nutzer in der Datenbank.
- Auth: Svix-Signaturverifizierung (
CLERK_WEBHOOK_SECRET) - Rate-Limit:
webhooks
Verarbeitete Events:
| Event | Aktion |
|---|---|
user.created | Nutzer mit Free-Tier-Credits erstellen |
user.updated | E-Mail und Name aktualisieren |
user.deleted | Nutzer aus der Datenbank löschen |
Response:
200 bei Erfolg, 400 wenn Svix-Header fehlen, 401 wenn Signaturverifizierung fehlschlägt.Lemon Squeezy-Webhook {#lemon-squeezy-webhook}
POST
/api/webhooks/lemonsqueezyVerarbeitet Lemon Squeezy-Zahlungs- und Abonnement-Events. Dies ist der komplexeste Webhook-Handler, der 11 Event-Typen unterstützt.
- Auth: HMAC-Signaturverifizierung (
LEMONSQUEEZY_WEBHOOK_SECRET) - Rate-Limit:
webhooks
Verarbeitete Events:
| Event | Aktion |
|---|---|
subscription_created | Abonnementeintrag erstellen |
subscription_updated | Plan/Status aktualisieren |
subscription_cancelled | Zur Kündigung am Periodenende vormerken |
subscription_resumed | Gekündigtes Abonnement reaktivieren |
subscription_expired | Auf Free-Tier downgraden |
subscription_paused | Abonnement pausieren |
subscription_unpaused | Pausiertes Abonnement fortsetzen |
subscription_payment_failed | Fehler protokollieren, Nutzer benachrichtigen |
subscription_payment_success | Zahlung bestätigen |
subscription_payment_recovered | Fehlerstatus beheben |
order_created | Einmaligen Kauf verarbeiten (Bonus-Credits) |
Der Lemon Squeezy-Webhook-Handler gibt
200 zurück, auch wenn ein einzelner Event-Handler fehlschlägt. Dadurch wird verhindert, dass Lemon Squeezy Events erneut sendet, die erneut fehlschlagen würden. Handler-Fehler werden für das Debugging protokolliert.Resend-Webhook {#resend-webhook}
POST
/api/webhooks/resendVerarbeitet Resend-E-Mail-Zustellungsstatus-Events (zugestellt, zurückgesendet, als Spam markiert).
- Auth: HMAC-Signaturverifizierung (
RESEND_WEBHOOK_SECRET) - Rate-Limit:
webhooks
Response:
{ "success": true, "processed": "email.delivered" }Fehlercodes:
400 Ungültige Payload, 401 Signaturverifizierung fehlgeschlagen, 500 ServerfehlerCron-Jobs
Automatisierte Wartungsaufgaben, die durch Vercel Cron ausgelöst werden. Beide Endpunkte erfordern in der Produktion einen
CRON_SECRET-Bearer-Token.Jeder Cron-Endpunkt unterstützt auch eine GET-Anfrage, die seinen Konfigurationsstatus (aktiv/inaktiv, Zeitplan, Modell) zurückgibt, ohne Authentifizierung zu erfordern. Nützlich für Monitoring-Dashboards.
Trial-Ablaufen prüfen {#check-trial-expirations}
POSTGET
/api/cron/check-trialsBeendet Trial-Abonnements, die ihr Enddatum erreicht haben. Läuft täglich um 2:00 Uhr UTC.
- Auth: Bearer-Token (
CRON_SECRET) in der Produktion - Zeitplan:
0 2 * * *(täglich) - Preismodell: Nur Classic SaaS (No-Op für Credit-basiert)
Response (200):
json
{
"success": true,
"message": "Trial check completed",
"expiredCount": 3,
"timestamp": "2026-02-14T02:00:00.000Z"
}
Bonus-Credits ablaufen lassen {#expire-bonus-credits}
POSTGET
/api/cron/expire-bonus-creditsLässt Bonus-Credit-Käufe ablaufen, die ihr Ablaufdatum überschritten haben. Läuft täglich um 3:00 Uhr UTC.
- Auth: Bearer-Token (
CRON_SECRET) in der Produktion - Zeitplan:
0 3 * * *(täglich) - Preismodell: Nur Credit-basiert
Response (200):
json
{
"success": true,
"message": "Bonus credit expiry check completed",
"expiredCount": 1,
"timestamp": "2026-02-14T03:00:00.000Z"
}
Health
Health-Check {#health-check}
GET
/api/healthGibt den Anwendungs-Health-Status zurück, einschließlich Datenbankverbindung und Speicherauslastung.
- Auth: Keine
- Rate-Limit: Keines
- Cache: Keines (
no-cache, no-store, must-revalidate)
Response (200 gesund / 503 nicht gesund):
json
{
"status": "healthy",
"timestamp": "2026-02-14T10:00:00.000Z",
"version": "1.0.0",
"environment": "production",
"checks": {
"database": "connected",
"memory": "ok"
},
"responseTime": "12ms"
}