/v2/auth/trainer-courseTrainer-Kursentwurf anlegen oder Datei hochladen
Verarbeitet action=create_course (Standard), prepare_title_image, upload_title_image oder upload_external_file. create_course erstellt einen unveröffentlichten Kurs status=0 mit optionalem Termin, Preis, Texten, interner Notiz und Titelbild. prepare_title_image registriert Titelbild-Metadaten und gibt eine signierte Upload-URL zurück. Multipart-Aktionen speichern eine Datei an einem eigenen noch unveröffentlichten Entwurf. Kategorien/Orte/Räume/Tags müssen zur Auswahl gehören, Titelbilder dem Trainer zugeordnet sein. Der persönliche Trainer-Bearer-Code ist erforderlich. Antworten und Upload-URLs sind vertraulich; fünf ungültige Codes innerhalb einer Stunde sperren die IP für eine Stunde. minimum darf maximum nicht übersteigen. Bei gesetztem start oder end sind beide gültigen lokalen Datumswerte erforderlich, end muss nach start liegen. Bei Multipart stehen action und offer direkt neben file, ohne data-JSON. Titelbilder erlauben JPEG/PNG bis 2 MiB und 40 Millionen Pixel, externe Dateien PDF/JPEG/PNG/WebP bis 20 MiB und höchstens zehn je Kurs. title muss nach der Textbereinigung einen nicht leeren Titel ergeben.
Operation-ID post_v2_auth_trainer_course
Vertrag & Verhalten
- Dokumentationsstand
- reviewed
- Ändert Zustand
- Ja
- Als readOnly markiert
- Nein
- Für Automation markiert
- Nein
Authentifizierung
Alle folgenden Security-Schemas werden gemeinsam benötigt (UND).
Erforderliche Schemas
trainerTokenhttp · bearerDedicated revocable trainer-course token; not a normal account JWT.
Security-Schema als JSON
{
"type": "http",
"scheme": "bearer",
"description": "Dedicated revocable trainer-course token; not a normal account JWT."
}Parameter
Header
languageoptionalAccount language code, where the resource supports setLanguage().
Schema-Beispiel
"de"Vollständiges Schema als JSON
{
"type": "string",
"examples": [
"de"
]
}AuthorizationerforderlichPersönlicher Trainer-Bearer-Code aus der administrativ verwalteten Freigabe; kein gewöhnlicher V2-Admin-Token.
- pattern
"^Bearer [A-Za-z0-9_-]{43}$"
Vollständiges Schema als JSON
{
"type": "string",
"pattern": "^Bearer [A-Za-z0-9_-]{43}$"
}Request Body
erforderlichapplication/json
data Typ nicht eingeschränkt erforderlich anyOf · Mindestens eine Variante muss passen
Variante 1 object action Typ nicht eingeschränkt Fester Wert: "create_course"
Standardwert: "create_course"
title string | number | boolean erforderlich Skalarer Text; vor Normalisierung höchstens 80 Zeichen. HTML/Leerzeichen werden bereinigt.
number string | number | boolean Skalarer Text; vor Normalisierung höchstens 120 Zeichen. HTML/Leerzeichen werden bereinigt.
category string erforderlich Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^category_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"category_012345abcdef_123456"description string | number | boolean Skalarer Text; vor Normalisierung höchstens 50000 Zeichen. HTML/Leerzeichen werden bereinigt.
description_html Typ nicht eingeschränkt PHP-empty/Wahrheitsvergleich steuert die HTML-Verarbeitung.
Schema-Beispiel
truebooking_message Typ nicht eingeschränkt Skalarer Text, auf 200000 Zeichen normalisiert; bei HTML-Flag String mit höchstens 50000 Zeichen.
Schema-Beispiel
"Bitte pünktlich erscheinen."booking_message_html Typ nicht eingeschränkt PHP-empty/Wahrheitsvergleich steuert die HTML-Verarbeitung.
Schema-Beispiel
trueinternal_note Typ nicht eingeschränkt Interne Notiz; skalarer Text wird auf 1000 Zeichen normalisiert.
minimum number | string | null | boolean Leertext/null/false gelten als nicht gesetzt; sonst per FILTER_VALIDATE_INT validierte Ganzzahl 0–99999.
maximum number | string | null | boolean Leertext/null/false gelten als nicht gesetzt; sonst per FILTER_VALIDATE_INT validierte Ganzzahl 0–99999.
price number | string | null | boolean Leer/null/false ohne Preis; sonst nichtnegative endliche Zahl bzw. numerischer Text bis 9999999.99, auf zwei Dezimalstellen gerundet.
start string | null | boolean YYYY-MM-DDTHH:mm in Kontozeitzone, ohne Sekunden/Offset. Leer/null/false ohne Termin; sobald ein Datum gesetzt ist, sind beide erforderlich.
end string | null | boolean YYYY-MM-DDTHH:mm in Kontozeitzone, ohne Sekunden/Offset. Leer/null/false ohne Termin; sobald ein Datum gesetzt ist, sind beide erforderlich.
place Typ nicht eingeschränkt anyOf · Mindestens eine Variante muss passen
Variante 1 string Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^place_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"place_012345abcdef_123456"Variante 2 Typ nicht eingeschränkt ""nullfalseroom Typ nicht eingeschränkt anyOf · Mindestens eine Variante muss passen
Variante 1 string Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^room_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"room_012345abcdef_123456"Variante 2 Typ nicht eingeschränkt ""nullfalsetags array - maxItems
50
Array-Elemente
Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^tag_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"tag_012345abcdef_123456"title_image Typ nicht eingeschränkt anyOf · Mindestens eine Variante muss passen
Variante 1 string Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^publicfile_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"publicfile_012345abcdef_123456"Variante 2 Typ nicht eingeschränkt ""nullfalseZusätzliche, hier nicht aufgeführte Felder sind erlaubt.
Variante 2 object action Typ nicht eingeschränkt erforderlich Fester Wert: "prepare_title_image"
file_name string | number | boolean erforderlich Dateiname mit jpg/jpeg/png-Endung; wird als Text auf 180 Zeichen normalisiert.
file_size number | string | boolean erforderlich Per FILTER_VALIDATE_INT geprüfte positive Ganzzahl bis 2097152 Bytes.
file_type string erforderlich Nach Kleinschreibung/Trimmen image/jpeg oder image/png; Endung muss dazu passen.
Schema-Beispiel
"image/png"Zusätzliche, hier nicht aufgeführte Felder sind erlaubt.
Zusätzliche, hier nicht aufgeführte Felder sind erlaubt.
Vollständiges Schema als JSON
{
"type": "object",
"properties": {
"data": {
"anyOf": [
{
"type": "object",
"properties": {
"action": {
"const": "create_course",
"default": "create_course"
},
"title": {
"type": [
"string",
"number",
"boolean"
],
"description": "Skalarer Text; vor Normalisierung höchstens 80 Zeichen. HTML/Leerzeichen werden bereinigt."
},
"number": {
"type": [
"string",
"number",
"boolean"
],
"description": "Skalarer Text; vor Normalisierung höchstens 120 Zeichen. HTML/Leerzeichen werden bereinigt."
},
"category": {
"type": "string",
"pattern": "^category_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"category_012345abcdef_123456"
]
},
"description": {
"type": [
"string",
"number",
"boolean"
],
"description": "Skalarer Text; vor Normalisierung höchstens 50000 Zeichen. HTML/Leerzeichen werden bereinigt."
},
"description_html": {
"description": "PHP-empty/Wahrheitsvergleich steuert die HTML-Verarbeitung.",
"examples": [
true
]
},
"booking_message": {
"description": "Skalarer Text, auf 200000 Zeichen normalisiert; bei HTML-Flag String mit höchstens 50000 Zeichen.",
"examples": [
"Bitte pünktlich erscheinen."
]
},
"booking_message_html": {
"description": "PHP-empty/Wahrheitsvergleich steuert die HTML-Verarbeitung.",
"examples": [
true
]
},
"internal_note": {
"description": "Interne Notiz; skalarer Text wird auf 1000 Zeichen normalisiert."
},
"minimum": {
"type": [
"number",
"string",
"null",
"boolean"
],
"description": "Leertext/null/false gelten als nicht gesetzt; sonst per FILTER_VALIDATE_INT validierte Ganzzahl 0–99999."
},
"maximum": {
"type": [
"number",
"string",
"null",
"boolean"
],
"description": "Leertext/null/false gelten als nicht gesetzt; sonst per FILTER_VALIDATE_INT validierte Ganzzahl 0–99999."
},
"price": {
"type": [
"number",
"string",
"null",
"boolean"
],
"description": "Leer/null/false ohne Preis; sonst nichtnegative endliche Zahl bzw. numerischer Text bis 9999999.99, auf zwei Dezimalstellen gerundet."
},
"start": {
"type": [
"string",
"null",
"boolean"
],
"description": "YYYY-MM-DDTHH:mm in Kontozeitzone, ohne Sekunden/Offset. Leer/null/false ohne Termin; sobald ein Datum gesetzt ist, sind beide erforderlich."
},
"end": {
"type": [
"string",
"null",
"boolean"
],
"description": "YYYY-MM-DDTHH:mm in Kontozeitzone, ohne Sekunden/Offset. Leer/null/false ohne Termin; sobald ein Datum gesetzt ist, sind beide erforderlich."
},
"place": {
"anyOf": [
{
"type": "string",
"pattern": "^place_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"place_012345abcdef_123456"
]
},
{
"enum": [
"",
null,
false
]
}
]
},
"room": {
"anyOf": [
{
"type": "string",
"pattern": "^room_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"room_012345abcdef_123456"
]
},
{
"enum": [
"",
null,
false
]
}
]
},
"tags": {
"type": "array",
"items": {
"type": "string",
"pattern": "^tag_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"tag_012345abcdef_123456"
]
},
"maxItems": 50
},
"title_image": {
"anyOf": [
{
"type": "string",
"pattern": "^publicfile_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"publicfile_012345abcdef_123456"
]
},
{
"enum": [
"",
null,
false
]
}
]
}
},
"additionalProperties": true,
"required": [
"title",
"category"
]
},
{
"type": "object",
"properties": {
"action": {
"const": "prepare_title_image"
},
"file_name": {
"type": [
"string",
"number",
"boolean"
],
"description": "Dateiname mit jpg/jpeg/png-Endung; wird als Text auf 180 Zeichen normalisiert."
},
"file_size": {
"type": [
"number",
"string",
"boolean"
],
"description": "Per FILTER_VALIDATE_INT geprüfte positive Ganzzahl bis 2097152 Bytes."
},
"file_type": {
"type": "string",
"description": "Nach Kleinschreibung/Trimmen image/jpeg oder image/png; Endung muss dazu passen.",
"examples": [
"image/png"
]
}
},
"additionalProperties": true,
"required": [
"action",
"file_name",
"file_size",
"file_type"
]
}
]
}
},
"additionalProperties": true,
"required": [
"data"
]
}create_course
{
"data": {
"action": "create_course",
"title": "Einführungskurs",
"category": "category_012345abcdef_123456",
"number": "K-2027-01",
"minimum": 1,
"maximum": 12,
"price": 120,
"start": "2027-04-01T09:00",
"end": "2027-04-01T12:00",
"tags": []
}
}prepare_title_image
{
"data": {
"action": "prepare_title_image",
"file_name": "titelbild.png",
"file_size": 1024,
"file_type": "image/png"
}
}multipart/form-data
action string erforderlich "upload_title_image""upload_external_file"offer string erforderlich Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^offer_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"offer_012345abcdef_123456"file string erforderlich Titelbild: JPEG/PNG bis 2 MiB und höchstens 40 Millionen Pixel. Externe Datei: PDF/JPEG/PNG/WebP bis 20 MiB, höchstens zehn je Kurs.
- format
"binary"
Zusätzliche, hier nicht aufgeführte Felder sind erlaubt.
Vollständiges Schema als JSON
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"upload_title_image",
"upload_external_file"
]
},
"offer": {
"type": "string",
"pattern": "^offer_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"offer_012345abcdef_123456"
]
},
"file": {
"type": "string",
"format": "binary",
"description": "Titelbild: JPEG/PNG bis 2 MiB und höchstens 40 Millionen Pixel. Externe Datei: PDF/JPEG/PNG/WebP bis 20 MiB, höchstens zehn je Kurs."
}
},
"additionalProperties": true,
"required": [
"action",
"offer",
"file"
]
}Antworten
9HTTP-Status und Antwortinhalt gemeinsam auswerten. In dieser API können auch Antworten mit HTTP 200 einen Fehler enthalten.
200application/json
create_course liefert offer-ID/created/status. prepare_title_image liefert publicfile-ID/insert/upload_url/cdn_url. upload_title_image liefert offer-ID/update/image/files/url; upload_external_file liefert files-ID/insert.
application/json
success boolean error boolean | string error_code string data Typ nicht eingeschränkt anyOf · Mindestens eine Variante muss passen
Variante 1 object id string erforderlich Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^offer_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"offer_012345abcdef_123456"created Typ nicht eingeschränkt erforderlich Fester Wert: true
status Typ nicht eingeschränkt erforderlich Fester Wert: 0
Zusätzliche, hier nicht aufgeführte Felder sind erlaubt.
Variante 2 object id string erforderlich Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^publicfile_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"publicfile_012345abcdef_123456"insert Typ nicht eingeschränkt erforderlich Fester Wert: true
upload_url string erforderlich Vertrauliche signierte Upload-URL.
- format
"uri"
cdn_url string erforderlich - format
"uri"
Zusätzliche, hier nicht aufgeführte Felder sind erlaubt.
Variante 3 object id string erforderlich Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^offer_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"offer_012345abcdef_123456"update Typ nicht eingeschränkt erforderlich Fester Wert: true
image string erforderlich files array erforderlich Array-Elemente
url string erforderlich Öffentliche Bild-URL.
Zusätzliche, hier nicht aufgeführte Felder sind erlaubt.
Variante 4 object id string erforderlich Öffentliche v2-ID; Beispiel ist synthetisch.
- pattern
"^files_[a-f0-9]{12}_-?[0-9]+$"
Schema-Beispiel
"files_012345abcdef_123456"insert Typ nicht eingeschränkt erforderlich Fester Wert: true
Zusätzliche, hier nicht aufgeführte Felder sind erlaubt.
type string Zusätzliche, hier nicht aufgeführte Felder sind erlaubt.
Vollständiges Schema als JSON
{
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"error": {
"type": [
"boolean",
"string"
]
},
"error_code": {
"type": "string"
},
"data": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^offer_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"offer_012345abcdef_123456"
]
},
"created": {
"const": true
},
"status": {
"const": 0
}
},
"additionalProperties": true,
"required": [
"id",
"created",
"status"
]
},
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^publicfile_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"publicfile_012345abcdef_123456"
]
},
"insert": {
"const": true
},
"upload_url": {
"type": "string",
"format": "uri",
"description": "Vertrauliche signierte Upload-URL."
},
"cdn_url": {
"type": "string",
"format": "uri"
}
},
"additionalProperties": true,
"required": [
"id",
"insert",
"upload_url",
"cdn_url"
]
},
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^offer_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"offer_012345abcdef_123456"
]
},
"update": {
"const": true
},
"image": {
"type": "string"
},
"files": {
"type": "array",
"items": {
"type": "string"
}
},
"url": {
"type": "string",
"description": "Öffentliche Bild-URL."
}
},
"additionalProperties": true,
"required": [
"id",
"update",
"image",
"files",
"url"
]
},
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^files_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"files_012345abcdef_123456"
]
},
"insert": {
"const": true
}
},
"additionalProperties": true,
"required": [
"id",
"insert"
]
}
]
},
"type": {
"type": "string"
}
},
"additionalProperties": true
}Beispiel
{
"success": true,
"error": false,
"data": {
"id": "offer_012345abcdef_123456",
"created": true,
"status": 0
}
}400application/json
Invalid request.
application/json
Kein Schema angegeben. Daraus lässt sich kein vollständiger Feldvertrag ableiten.
Beispiel
{
"success": false,
"error": "ED40006"
}401application/json
Missing/expired token, missing account context, account paused or model-specific authorization failure.
application/json
Kein Schema angegeben. Daraus lässt sich kein vollständiger Feldvertrag ableiten.
Beispiel
{
"success": false,
"error": "ED40103"
}402application/json
Missing/invalid action data or subscription/operation restriction.
application/json
Kein Schema angegeben. Daraus lässt sich kein vollständiger Feldvertrag ableiten.
Beispiel
{
"success": false,
"error": "ED80100"
}403application/json
Permission denied. Browser CORS rejection may have an empty body.
application/json
Kein Schema angegeben. Daraus lässt sich kein vollständiger Feldvertrag ableiten.
Beispiel
{
"success": false,
"error": "ED40340"
}404application/json
Unknown resource/action or unsupported method.
application/json
Kein Schema angegeben. Daraus lässt sich kein vollständiger Feldvertrag ableiten.
Beispiel
{
"success": false,
"error": "ED80019"
}422application/json
Validation failed.
application/json
Kein Schema angegeben. Daraus lässt sich kein vollständiger Feldvertrag ableiten.
Beispiel
{
"success": false,
"error": "ED80020"
}429application/json
Request/login rate limit exceeded. Honor Retry-After when supplied; legacy rate-limit paths may omit it. Retry only proven reads within a bounded deadline; a mutation is never automatically replayed after an ambiguous response.
Response Header
Retry-After
Optional server delay in whole seconds or an HTTP date. Absence is not permission for an immediate retry.
Schema-Beispiel
"30"Vollständiges Schema als JSON
{
"type": "string",
"examples": [
"30"
]
}application/json
Kein Schema angegeben. Daraus lässt sich kein vollständiger Feldvertrag ableiten.
Beispiel
{
"success": false,
"error": "ED42902"
}502application/json
Server-side operation failed.
application/json
Kein Schema angegeben. Daraus lässt sich kein vollständiger Feldvertrag ableiten.
Beispiel
{
"success": false,
"error": "ED50201"
}Quelle & Metadaten
application/models/v2/Trainercourse.php:88handlePublicRequest()Diese Angaben stammen unverändert aus der gelieferten OpenAPI-Datei. Zusätzliche Freigaben, Vorbedingungen, sensible Felder und Hinweise stehen in den Erweiterungen.
x-edoobox-mutates-state
truex-edoobox-authentication-lifecycle
truex-edoobox-runtimeMutationGuard
falsex-edoobox-documentationReview
{
"file": "docs/openapi/operation-contracts/10-other-resources.json",
"notes": []
}x-edoobox-source
{
"file": "application/models/v2/Trainercourse.php",
"method": "handlePublicRequest",
"line": 88
}x-edoobox-documentationStatus
"reviewed"x-edoobox-readOnly
falsex-edoobox-safeForAutomation
falsex-edoobox-permission
{
"resource": "trainer-course",
"short": null,
"checkedByDispatcher": false,
"levels": [],
"description": "No account-JWT resource permission levels are applied. Authentication requirements, if any, are defined by this route source-specific boundary and dedicated security scheme."
}Vollständige Operation als JSON
{
"operationId": "post_v2_auth_trainer_course",
"summary": "Trainer-Kursentwurf anlegen oder Datei hochladen",
"description": "Verarbeitet action=create_course (Standard), prepare_title_image, upload_title_image oder upload_external_file. create_course erstellt einen unveröffentlichten Kurs status=0 mit optionalem Termin, Preis, Texten, interner Notiz und Titelbild. prepare_title_image registriert Titelbild-Metadaten und gibt eine signierte Upload-URL zurück. Multipart-Aktionen speichern eine Datei an einem eigenen noch unveröffentlichten Entwurf. Kategorien/Orte/Räume/Tags müssen zur Auswahl gehören, Titelbilder dem Trainer zugeordnet sein. Der persönliche Trainer-Bearer-Code ist erforderlich. Antworten und Upload-URLs sind vertraulich; fünf ungültige Codes innerhalb einer Stunde sperren die IP für eine Stunde. minimum darf maximum nicht übersteigen. Bei gesetztem start oder end sind beide gültigen lokalen Datumswerte erforderlich, end muss nach start liegen. Bei Multipart stehen action und offer direkt neben file, ohne data-JSON. Titelbilder erlauben JPEG/PNG bis 2 MiB und 40 Millionen Pixel, externe Dateien PDF/JPEG/PNG/WebP bis 20 MiB und höchstens zehn je Kurs. title muss nach der Textbereinigung einen nicht leeren Titel ergeben.",
"tags": [
"trainer-course"
],
"security": [
{
"trainerToken": []
}
],
"parameters": [
{
"name": "language",
"in": "header",
"required": false,
"description": "Account language code, where the resource supports setLanguage().",
"schema": {
"type": "string",
"examples": [
"de"
]
}
},
{
"name": "Authorization",
"in": "header",
"required": true,
"schema": {
"type": "string",
"pattern": "^Bearer [A-Za-z0-9_-]{43}$"
},
"description": "Persönlicher Trainer-Bearer-Code aus der administrativ verwalteten Freigabe; kein gewöhnlicher V2-Admin-Token."
}
],
"responses": {
"200": {
"description": "create_course liefert offer-ID/created/status. prepare_title_image liefert publicfile-ID/insert/upload_url/cdn_url. upload_title_image liefert offer-ID/update/image/files/url; upload_external_file liefert files-ID/insert.",
"content": {
"application/json": {
"example": {
"success": true,
"error": false,
"data": {
"id": "offer_012345abcdef_123456",
"created": true,
"status": 0
}
},
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"error": {
"type": [
"boolean",
"string"
]
},
"error_code": {
"type": "string"
},
"data": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^offer_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"offer_012345abcdef_123456"
]
},
"created": {
"const": true
},
"status": {
"const": 0
}
},
"additionalProperties": true,
"required": [
"id",
"created",
"status"
]
},
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^publicfile_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"publicfile_012345abcdef_123456"
]
},
"insert": {
"const": true
},
"upload_url": {
"type": "string",
"format": "uri",
"description": "Vertrauliche signierte Upload-URL."
},
"cdn_url": {
"type": "string",
"format": "uri"
}
},
"additionalProperties": true,
"required": [
"id",
"insert",
"upload_url",
"cdn_url"
]
},
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^offer_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"offer_012345abcdef_123456"
]
},
"update": {
"const": true
},
"image": {
"type": "string"
},
"files": {
"type": "array",
"items": {
"type": "string"
}
},
"url": {
"type": "string",
"description": "Öffentliche Bild-URL."
}
},
"additionalProperties": true,
"required": [
"id",
"update",
"image",
"files",
"url"
]
},
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^files_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"files_012345abcdef_123456"
]
},
"insert": {
"const": true
}
},
"additionalProperties": true,
"required": [
"id",
"insert"
]
}
]
},
"type": {
"type": "string"
}
},
"additionalProperties": true
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"example": {
"success": false,
"error": "ED40006"
}
}
}
},
"401": {
"description": "Missing/expired token, missing account context, account paused or model-specific authorization failure.",
"content": {
"application/json": {
"example": {
"success": false,
"error": "ED40103"
}
}
}
},
"402": {
"description": "Missing/invalid action data or subscription/operation restriction.",
"content": {
"application/json": {
"example": {
"success": false,
"error": "ED80100"
}
}
}
},
"403": {
"description": "Permission denied. Browser CORS rejection may have an empty body.",
"content": {
"application/json": {
"example": {
"success": false,
"error": "ED40340"
}
}
}
},
"404": {
"description": "Unknown resource/action or unsupported method.",
"content": {
"application/json": {
"example": {
"success": false,
"error": "ED80019"
}
}
}
},
"422": {
"description": "Validation failed.",
"content": {
"application/json": {
"example": {
"success": false,
"error": "ED80020"
}
}
}
},
"429": {
"description": "Request/login rate limit exceeded. Honor Retry-After when supplied; legacy rate-limit paths may omit it. Retry only proven reads within a bounded deadline; a mutation is never automatically replayed after an ambiguous response.",
"content": {
"application/json": {
"example": {
"success": false,
"error": "ED42902"
}
}
},
"headers": {
"Retry-After": {
"description": "Optional server delay in whole seconds or an HTTP date. Absence is not permission for an immediate retry.",
"schema": {
"type": "string",
"examples": [
"30"
]
}
}
}
},
"502": {
"description": "Server-side operation failed.",
"content": {
"application/json": {
"example": {
"success": false,
"error": "ED50201"
}
}
}
}
},
"x-edoobox-mutates-state": true,
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"anyOf": [
{
"type": "object",
"properties": {
"action": {
"const": "create_course",
"default": "create_course"
},
"title": {
"type": [
"string",
"number",
"boolean"
],
"description": "Skalarer Text; vor Normalisierung höchstens 80 Zeichen. HTML/Leerzeichen werden bereinigt."
},
"number": {
"type": [
"string",
"number",
"boolean"
],
"description": "Skalarer Text; vor Normalisierung höchstens 120 Zeichen. HTML/Leerzeichen werden bereinigt."
},
"category": {
"type": "string",
"pattern": "^category_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"category_012345abcdef_123456"
]
},
"description": {
"type": [
"string",
"number",
"boolean"
],
"description": "Skalarer Text; vor Normalisierung höchstens 50000 Zeichen. HTML/Leerzeichen werden bereinigt."
},
"description_html": {
"description": "PHP-empty/Wahrheitsvergleich steuert die HTML-Verarbeitung.",
"examples": [
true
]
},
"booking_message": {
"description": "Skalarer Text, auf 200000 Zeichen normalisiert; bei HTML-Flag String mit höchstens 50000 Zeichen.",
"examples": [
"Bitte pünktlich erscheinen."
]
},
"booking_message_html": {
"description": "PHP-empty/Wahrheitsvergleich steuert die HTML-Verarbeitung.",
"examples": [
true
]
},
"internal_note": {
"description": "Interne Notiz; skalarer Text wird auf 1000 Zeichen normalisiert."
},
"minimum": {
"type": [
"number",
"string",
"null",
"boolean"
],
"description": "Leertext/null/false gelten als nicht gesetzt; sonst per FILTER_VALIDATE_INT validierte Ganzzahl 0–99999."
},
"maximum": {
"type": [
"number",
"string",
"null",
"boolean"
],
"description": "Leertext/null/false gelten als nicht gesetzt; sonst per FILTER_VALIDATE_INT validierte Ganzzahl 0–99999."
},
"price": {
"type": [
"number",
"string",
"null",
"boolean"
],
"description": "Leer/null/false ohne Preis; sonst nichtnegative endliche Zahl bzw. numerischer Text bis 9999999.99, auf zwei Dezimalstellen gerundet."
},
"start": {
"type": [
"string",
"null",
"boolean"
],
"description": "YYYY-MM-DDTHH:mm in Kontozeitzone, ohne Sekunden/Offset. Leer/null/false ohne Termin; sobald ein Datum gesetzt ist, sind beide erforderlich."
},
"end": {
"type": [
"string",
"null",
"boolean"
],
"description": "YYYY-MM-DDTHH:mm in Kontozeitzone, ohne Sekunden/Offset. Leer/null/false ohne Termin; sobald ein Datum gesetzt ist, sind beide erforderlich."
},
"place": {
"anyOf": [
{
"type": "string",
"pattern": "^place_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"place_012345abcdef_123456"
]
},
{
"enum": [
"",
null,
false
]
}
]
},
"room": {
"anyOf": [
{
"type": "string",
"pattern": "^room_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"room_012345abcdef_123456"
]
},
{
"enum": [
"",
null,
false
]
}
]
},
"tags": {
"type": "array",
"items": {
"type": "string",
"pattern": "^tag_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"tag_012345abcdef_123456"
]
},
"maxItems": 50
},
"title_image": {
"anyOf": [
{
"type": "string",
"pattern": "^publicfile_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"publicfile_012345abcdef_123456"
]
},
{
"enum": [
"",
null,
false
]
}
]
}
},
"additionalProperties": true,
"required": [
"title",
"category"
]
},
{
"type": "object",
"properties": {
"action": {
"const": "prepare_title_image"
},
"file_name": {
"type": [
"string",
"number",
"boolean"
],
"description": "Dateiname mit jpg/jpeg/png-Endung; wird als Text auf 180 Zeichen normalisiert."
},
"file_size": {
"type": [
"number",
"string",
"boolean"
],
"description": "Per FILTER_VALIDATE_INT geprüfte positive Ganzzahl bis 2097152 Bytes."
},
"file_type": {
"type": "string",
"description": "Nach Kleinschreibung/Trimmen image/jpeg oder image/png; Endung muss dazu passen.",
"examples": [
"image/png"
]
}
},
"additionalProperties": true,
"required": [
"action",
"file_name",
"file_size",
"file_type"
]
}
]
}
},
"additionalProperties": true,
"required": [
"data"
]
},
"examples": {
"create_course": {
"value": {
"data": {
"action": "create_course",
"title": "Einführungskurs",
"category": "category_012345abcdef_123456",
"number": "K-2027-01",
"minimum": 1,
"maximum": 12,
"price": 120,
"start": "2027-04-01T09:00",
"end": "2027-04-01T12:00",
"tags": []
}
}
},
"prepare_title_image": {
"value": {
"data": {
"action": "prepare_title_image",
"file_name": "titelbild.png",
"file_size": 1024,
"file_type": "image/png"
}
}
}
}
},
"multipart/form-data": {
"schema": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"upload_title_image",
"upload_external_file"
]
},
"offer": {
"type": "string",
"pattern": "^offer_[a-f0-9]{12}_-?[0-9]+$",
"description": "Öffentliche v2-ID; Beispiel ist synthetisch.",
"examples": [
"offer_012345abcdef_123456"
]
},
"file": {
"type": "string",
"format": "binary",
"description": "Titelbild: JPEG/PNG bis 2 MiB und höchstens 40 Millionen Pixel. Externe Datei: PDF/JPEG/PNG/WebP bis 20 MiB, höchstens zehn je Kurs."
}
},
"additionalProperties": true,
"required": [
"action",
"offer",
"file"
]
}
}
}
},
"x-edoobox-authentication-lifecycle": true,
"x-edoobox-runtimeMutationGuard": false,
"x-edoobox-documentationReview": {
"file": "docs/openapi/operation-contracts/10-other-resources.json",
"notes": []
},
"x-edoobox-source": {
"file": "application/models/v2/Trainercourse.php",
"method": "handlePublicRequest",
"line": 88
},
"x-edoobox-documentationStatus": "reviewed",
"x-edoobox-readOnly": false,
"x-edoobox-safeForAutomation": false,
"x-edoobox-permission": {
"resource": "trainer-course",
"short": null,
"checkedByDispatcher": false,
"levels": [],
"description": "No account-JWT resource permission levels are applied. Authentication requirements, if any, are defined by this route source-specific boundary and dedicated security scheme."
}
}