- Add resolveAnalysisMode() to modes/index.ts for dynamic skill lookup - Extend structured-analysis.ts to use resolveAnalysisMode (supports custom skill prompts and skillId persistence) - Update structured analyses route to use resolveAnalysisMode instead of hardcoded VALID_MODES set - Add skills:read/create/edit/delete RBAC permissions to rbac.ts - Add docs/API_GUIDE.md with full endpoint reference Co-Authored-By: Paperclip <noreply@paperclip.ing>
15 KiB
StageAI API Usage Guide
This guide covers all API endpoints with practical examples for text and office document sources.
Base URL
http://localhost:3000/api
1. Authentication
Register a New Tenant
Creates a new tenant (law firm) and its first admin user.
curl -X POST http://localhost:3000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"name": "Dr. Müller",
"email": "mueller@kanzlei.de",
"password": "securepassword123",
"tenantName": "Kanzlei Müller"
}'
Response (201):
{
"user": {
"id": "uuid",
"email": "mueller@kanzlei.de",
"name": "Dr. Müller",
"role": "admin"
},
"tenant": {
"id": "uuid",
"name": "Kanzlei Müller",
"slug": "kanzlei-mueller"
}
}
Sign In (Get Session Cookie)
Authentication uses NextAuth.js with the Credentials provider. Sign in to get a session cookie:
curl -X POST http://localhost:3000/api/auth/callback/credentials \
-H "Content-Type: application/json" \
-d '{"email": "mueller@kanzlei.de", "password": "securepassword123"}' \
-c cookies.txt
Use -b cookies.txt on subsequent requests to send the session cookie.
Session Info
curl http://localhost:3000/api/auth/session -b cookies.txt
Returns the current user session including tenantId, userId, role, email, and name.
Note: Sessions expire after 8 hours. All protected endpoints require a valid session cookie. Tenant isolation is enforced at the database level via Row-Level Security.
2. Cases (Fälle)
Create a Case
curl -X POST http://localhost:3000/api/cases \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"caseNumber": "2024-BSchG-001",
"title": "Nichtverlängerung Solist",
"clientName": "Max Mustermann",
"opposingParty": "Staatstheater Berlin",
"venue": "Bühnenschiedsgericht Berlin",
"status": "active",
"domains": ["nv_buehne", "arbeitsrecht"]
}'
Response (201):
{
"id": "uuid",
"caseNumber": "2024-BSchG-001",
"title": "Nichtverlängerung Solist",
"clientName": "Max Mustermann",
"status": "active",
"createdAt": "2024-01-15T10:00:00Z"
}
List Cases
# All cases
curl http://localhost:3000/api/cases -b cookies.txt
# Search + filter
curl "http://localhost:3000/api/cases?q=Mustermann&status=active&limit=10&offset=0" \
-b cookies.txt
Get Case Details
curl http://localhost:3000/api/cases/{caseId} -b cookies.txt
Returns the case along with related analyses and proceedings.
Update / Delete a Case
# Update
curl -X PATCH http://localhost:3000/api/cases/{caseId} \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{"status": "closed"}'
# Delete
curl -X DELETE http://localhost:3000/api/cases/{caseId} -b cookies.txt
3. Document Upload (Text & Office Sources)
StageAI supports PDF and DOCX files (max 10 MB). Text is extracted automatically after upload.
Upload a Generic Document
curl -X POST http://localhost:3000/api/documents \
-b cookies.txt \
-F "file=@/path/to/urteil.pdf" \
-F "category=entscheidung" \
-F "sourceScope=global"
Parameters:
| Field | Required | Values |
|---|---|---|
file |
Yes | PDF or DOCX file |
category |
Yes | entscheidung, norm, falldokument, sonstiges |
sourceScope |
No | case (private to a case) or global |
caseId |
No | Link to a specific case |
decisionId |
No | Link to a specific decision |
normInstrumentId |
No | Link to a norm instrument |
Response (201):
{
"id": "uuid",
"filename": "urteil.pdf",
"mimeType": "application/pdf",
"category": "entscheidung",
"status": "uploaded",
"createdAt": "2024-01-15T10:30:00Z"
}
After upload, text extraction runs asynchronously. Status progresses: uploaded -> extracting -> extracted (or failed).
List Documents
# All documents
curl "http://localhost:3000/api/documents" -b cookies.txt
# Filter by category and scope
curl "http://localhost:3000/api/documents?category=entscheidung&sourceScope=global&limit=20&offset=0" \
-b cookies.txt
4. Contract Analysis (Vertragsanalyse)
Upload employment contracts (NV Bühne) for AI-powered clause analysis.
Upload a Contract
curl -X POST http://localhost:3000/api/contracts \
-b cookies.txt \
-F "file=@/path/to/arbeitsvertrag.pdf" \
-F "caseId=uuid-of-case"
Response (201):
{
"id": "uuid",
"filename": "arbeitsvertrag.pdf",
"mimeType": "application/pdf",
"status": "uploaded",
"caseId": "uuid-of-case"
}
Trigger Clause Analysis
After uploading, trigger the AI analysis:
curl -X POST http://localhost:3000/api/contracts/{contractId}/analyze \
-b cookies.txt
This extracts text from the document, identifies contract clauses, and compares them against NV Bühne standard clauses. The status progresses: uploaded -> extracting -> extracted -> analyzing -> completed.
Get Contract with Analysis Results
curl http://localhost:3000/api/contracts/{contractId} \
-H "x-tenant-id: your-tenant-id" \
-b cookies.txt
Response (200):
{
"document": {
"id": "uuid",
"filename": "arbeitsvertrag.pdf",
"status": "completed"
},
"clauses": [
{
"id": "uuid",
"category": "Vergütung",
"extractedText": "Die monatliche Gage beträgt...",
"rating": "standard",
"analysis": "Entspricht der Gagenklasse III NV Bühne.",
"riskScore": 5,
"deviations": []
},
{
"id": "uuid",
"category": "Nichtverlängerung",
"extractedText": "Der Vertrag kann mit einer Frist von...",
"rating": "kritisch",
"analysis": "Die Frist weicht von § 69 NV Bühne ab.",
"riskScore": 85,
"deviations": ["Frist kürzer als tariflich vorgesehen"]
}
]
}
Clause Categories: Vertragsparteien, Vertragsdauer, Nichtverlängerung, Vergütung, Arbeitszeit, Proben, Gastspiele, Urlaub, Krankheit, Kündigung, Nebentätigkeit, Geheimhaltung, Sonstiges
Ratings: standard (conforms to NV Bühne), abweichend (deviates), kritisch (critical deviation), unbekannt (unclassifiable)
List Contracts
curl "http://localhost:3000/api/contracts?limit=20&offset=0" -b cookies.txt
5. Legal Norms (Normen)
Create a Norm Instrument
curl -X POST http://localhost:3000/api/norms \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"type": "tarifvertrag",
"sourceRank": "tarifvertrag",
"abbreviation": "NV Bühne",
"fullTitle": "Normalvertrag Bühne",
"enactedAt": "2023-01-01",
"issuingBody": "GDBA / VdO / DBV"
}'
Import Norm Provisions (Bulk)
curl -X POST http://localhost:3000/api/norms/import \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"instrumentId": "uuid-of-instrument",
"provisions": [
{
"paragraph": "§ 1",
"title": "Geltungsbereich",
"body": "Dieser Normalvertrag gilt für alle Bühnenmitglieder...",
"validFrom": "2023-01-01",
"domains": ["nv_buehne"]
},
{
"paragraph": "§ 69",
"title": "Nichtverlängerungsmitteilung",
"body": "Die Nichtverlängerungsmitteilung muss bis zum 31. Oktober...",
"validFrom": "2023-01-01",
"domains": ["nv_buehne", "nichtverlängerung"]
}
]
}'
Query Norms (with Temporal Versioning)
Retrieve all paragraphs of an instrument valid on a specific date:
# Norms valid today (default)
curl http://localhost:3000/api/norms/{instrumentId} -b cookies.txt
# Norms valid on a specific date (Stichtag)
curl "http://localhost:3000/api/norms/{instrumentId}?date=2024-06-15" -b cookies.txt
Response (200):
{
"instrument": {
"id": "uuid",
"abbreviation": "NV Bühne",
"fullTitle": "Normalvertrag Bühne",
"type": "tarifvertrag"
},
"provisions": [
{
"id": "uuid",
"paragraph": "§ 1",
"title": "Geltungsbereich",
"body": "Dieser Normalvertrag gilt für alle Bühnenmitglieder...",
"validFrom": "2023-01-01",
"validTo": null
}
]
}
6. Decisions (Entscheidungen)
Create a Decision
curl -X POST http://localhost:3000/api/decisions \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"type": "schiedsspruch",
"caseReference": "BSchG Berlin 3/2024",
"decisionDate": "2024-03-15",
"court": "Bühnenschiedsgericht Berlin",
"headnote": "Zur Wirksamkeit einer Nichtverlängerungsmitteilung...",
"tenor": "Der Schiedsspruch wird aufgehoben...",
"facts": "Der Kläger ist seit 2018 als Solist...",
"reasoning": "Die Nichtverlängerungsmitteilung ist unwirksam, weil...",
"domains": ["nv_buehne", "nichtverlängerung"],
"keywords": ["Nichtverlängerung", "Solist", "Fristversäumnis"]
}'
Full-Text Search for Decisions
Uses PostgreSQL full-text search with German language support:
# Search by keyword
curl "http://localhost:3000/api/decisions?q=Vergütung" -b cookies.txt
# Combined filters
curl "http://localhost:3000/api/decisions?q=Nichtverlängerung&court=Bühnenschiedsgericht&type=schiedsspruch&dateFrom=2020-01-01&dateTo=2024-12-31" \
-b cookies.txt
Link Norms to a Decision
curl -X POST http://localhost:3000/api/decisions/{decisionId}/norms \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"normId": "uuid-of-norm-paragraph",
"applicationType": "angewendet",
"passage": "Rn. 15-18"
}'
Application types: angewendet (applied), zitiert (cited), ausgelegt (interpreted), verworfen (rejected)
7. AI-Powered Legal Analysis (Analysen)
Create a Streaming Analysis
curl -X POST http://localhost:3000/api/analyses \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"mode": "gutachten",
"title": "Wirksamkeit der Nichtverlängerung",
"query": "Ist die Nichtverlängerungsmitteilung vom 15.11.2024 wirksam, wenn der Solist seit 15 Jahren am Haus beschäftigt ist?",
"normIds": ["uuid-of-§69-nv-buehne"],
"decisionIds": ["uuid-of-relevant-decision"],
"documentIds": ["uuid-of-uploaded-document"],
"stichtag": "2024-11-15",
"caseId": "uuid-of-case"
}'
The response streams text (the AI-generated analysis). The X-Analysis-Id response header contains the analysis ID for later retrieval.
Analysis Modes:
| Mode | Purpose | Requires |
|---|---|---|
gutachten |
Expert legal opinion | Norms |
entscheidung |
Decision proposal based on precedent | Decisions |
vergleich |
Comparative analysis | Norms or decisions |
risiko |
Risk assessment with probability ratings | Any sources |
Create a Structured Analysis (JSON Output)
curl -X POST http://localhost:3000/api/analyses/structured \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"mode": "risiko",
"query": "Risikobewertung für die Kündigung eines Chormitglieds nach § 626 BGB",
"normIds": ["uuid1"],
"decisionIds": ["uuid2"]
}'
Returns typed JSON with structured fields depending on the mode.
List & Retrieve Analyses
# List (metadata only, DSGVO-compliant)
curl "http://localhost:3000/api/analyses?limit=20&offset=0" -b cookies.txt
# Get single analysis with full result and sources
curl http://localhost:3000/api/analyses/{analysisId} \
-H "x-tenant-id: your-tenant-id" \
-b cookies.txt
8. Proceedings (Verfahren)
Create a Proceeding
curl -X POST http://localhost:3000/api/proceedings \
-H "Content-Type: application/json" \
-d '{
"tenantId": "your-tenant-id",
"type": "bschgo_bezirk",
"caseId": "uuid-of-case",
"applicant": "Max Mustermann",
"respondent": "Staatstheater Berlin",
"subject": "Nichtverlängerung Spielzeit 2024/25"
}'
Proceeding types: bschgo_bezirk, bschgo_bund, arbgg_erste_instanz, arbgg_berufung, arbgg_revision
Workflow steps and initial deadlines are automatically created from templates.
Check Deadlines
# All deadlines
curl http://localhost:3000/api/proceedings/{proceedingId}/deadlines
# Only overdue deadlines
curl "http://localhost:3000/api/proceedings/{proceedingId}/deadlines?overdue=true"
# Upcoming in next 14 days
curl "http://localhost:3000/api/proceedings/{proceedingId}/deadlines?upcoming=14"
Advance Proceeding
curl -X POST http://localhost:3000/api/proceedings/{proceedingId}/advance \
-b cookies.txt
9. NV Bühne Utilities
These are public endpoints (no auth required) for quick calculations.
Calculate Compensation (Gage)
# GET (simple query)
curl "http://localhost:3000/api/nv-buehne/compensation?gagenklasse=III&yearsOfService=5&spielzeit=2024/25&fachgruppe=Solo"
# POST (with tenant-specific rules)
curl -X POST http://localhost:3000/api/nv-buehne/compensation \
-H "Content-Type: application/json" \
-d '{
"gagenklasse": "III",
"yearsOfService": 5,
"spielzeit": "2024/25",
"fachgruppe": "Solo",
"tenantId": "uuid",
"fachgruppeId": "uuid"
}'
Check Non-Renewal Deadline (Nichtverlängerungsfrist)
curl "http://localhost:3000/api/nv-buehne/deadline-check?yearsOfService=15&isOver55=false&spielzeit=2024/25&fachgruppe=Solo&referenceDate=2024-10-31"
Get Current Spielzeit (Season)
curl "http://localhost:3000/api/nv-buehne/spielzeit"
# or for a specific date:
curl "http://localhost:3000/api/nv-buehne/spielzeit?date=2024-09-01"
10. Settings
Manage AI Provider API Keys
# List keys (returns hints only, never full keys)
curl http://localhost:3000/api/settings/api-keys -b cookies.txt
# Add an API key
curl -X POST http://localhost:3000/api/settings/api-keys \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"provider": "anthropic",
"apiKey": "sk-ant-...",
"label": "Production Key"
}'
Keys are encrypted at rest with AES-256-GCM.
Pagination
All list endpoints support pagination:
?limit=20&offset=0
Response format:
{
"data": [...],
"pagination": {
"total": 100,
"limit": 20,
"offset": 0,
"hasMore": true
}
}
Error Handling
All errors return JSON:
{
"error": "Human-readable error message"
}
| Status | Meaning |
|---|---|
| 400 | Validation error (missing/invalid fields) |
| 401 | Not authenticated (missing or expired session) |
| 403 | Permission denied (role lacks required permission) |
| 404 | Resource not found |
| 409 | Conflict (duplicate entry) |
| 413 | File too large (max 10 MB) |
User Roles & Permissions
| Role | Permissions |
|---|---|
admin |
Full access, manage settings & users |
attorney |
Create/edit cases, analyses, norms, decisions |
paralegal |
Read access + limited write |
viewer |
Read-only |
Typical Workflow
- Register a tenant and admin user
- Configure AI provider API key in Settings
- Create norms (import NV Bühne provisions)
- Upload decisions (create + link applicable norms)
- Create a case for a client
- Upload documents (court rulings, contracts as PDF/DOCX)
- Upload & analyze a contract to identify clause deviations
- Run AI analyses referencing norms, decisions, and documents
- Create proceedings to track deadlines and workflow steps