Entwickler-API apps
Hinter den Datenquellen, dem Handler-Kontext und dem SDK steht eine gewöhnliche REST-API: die Sektion apps der Methacore-Entwickler-API. Brauchst du sie direkt – etwa aus einem eigenen Backend, das mit dem Token einer externen App arbeitet –, findest du hier jeden Endpunkt.
https://apps.api.methacore.de/v1
Authentifizierung
Jeder Aufruf braucht ein Bearer-Token, das ein Mitglied deiner App über OAuth (PKCE) ausgestellt hat – wie bei allen Produkt-APIs, nur dass der Client zur API „Methacore Apps“ gehört:
curl https://apps.api.methacore.de/v1/me/profile \
-H "Authorization: Bearer mcapi_9f3c…c41a"
Ein Token trägt:
| Angabe | Wirkung |
|---|---|
Mitglied (sub) | alle me/*-Endpunkte antworten nur mit Daten dieses Mitglieds |
Verein (organisation) | der Verein, für den das Mitglied zugestimmt hat |
| Client | bestimmt die App – und damit, welchen Speicher storage/* sieht |
| Scopes | was das Mitglied erlaubt hat |
API-Keys und Sandbox-Keys funktionieren hier nicht: Ohne Mitglied gibt es kein „ich“.
Überblick
| Methode | Pfad | Scope | Antwort |
|---|---|---|---|
GET | / | – | Kennung der API und Verein des Tokens |
GET | /me/profile | mc.me.profile:read | Profil |
GET | /me/groups | mc.me.groups:read | Gruppen mit Rolle |
GET | /me/events | mc.me.events:read | Termine im Zeitraum |
GET | /me/trainingplans | mc.me.trainingplans:read | Trainingspläne der eigenen Gruppen |
GET | /me/competitions | mc.me.competitions:read | eigene Turnierergebnisse |
GET | /me/membercard | mc.me.membercard:read | Mitgliedsausweis |
GET | /storage/{collection} | mc.apps.storage:read | Einträge einer Sammlung |
GET | /storage/{collection}/{key} | mc.apps.storage:read | ein Eintrag |
PUT | /storage/{collection}/{key} | mc.apps.storage:write | Eintrag anlegen oder ersetzen |
DELETE | /storage/{collection}/{key} | mc.apps.storage:write | Eintrag löschen |
GET /
{ "api": "methacore-apps", "organisation": "66bcfadc2f1e4a0012ab0001" }
GET /me/profile
{
"id": "665f1c2a9b1e4a0012ab34cd",
"firstName": "Anna",
"lastName": "Schneider",
"email": "[email protected]",
"birthday": "1988-04-12",
"image": "https://images.methacore.de/beispiel/anna.jpg"
}
birthday ist null, wenn nichts hinterlegt ist, image ein leerer Text ohne Bild.
GET /me/groups
Gruppen, in denen das Mitglied ist oder die es trainiert.
{
"items": [
{ "id": "g1", "name": "Voltigieren Kinder", "role": "member" },
{ "id": "g2", "name": "Dressur Fortgeschrittene", "role": "trainer" }
]
}
GET /me/events
Der Kalender des Mitglieds mit derselben Sichtbarkeit wie in der Mitglieder-App: Vereinstermine, sichtbare Kalender und Termine der eigenen Gruppen.
| Parameter | Ort | Typ | Bedeutung |
|---|---|---|---|
start | query | integer | Beginn als Unix-Zeitstempel in Sekunden. Standard: jetzt. |
end | query | integer | Ende als Unix-Zeitstempel. Standard: start + 90 Tage. Höchstens ein Jahr nach start. |
curl "https://apps.api.methacore.de/v1/me/events?start=1790805600&end=1793484000" \
-H "Authorization: Bearer $TOKEN"
{
"items": [
{ "id": "e1", "title": "Training Voltigieren", "start": 1790960400, "end": 1790965800, "location": "Reithalle" }
]
}
start und end der Einträge sind Unix-Zeitstempel in Sekunden. Ein Zeitraum über ein Jahr antwortet mit 400.
GET /me/trainingplans
Trainingspläne, die den Gruppen des Mitglieds zugeordnet sind.
{
"items": [
{ "id": "t1", "name": "Grundlagen Pflicht", "category": "Voltigieren", "description": "Pflichtübungen für Einsteiger",
"exerciseCount": 7, "group": "g1" }
]
}
group ist die Kennung der Gruppe, über die der Plan zugeordnet ist.
GET /me/competitions
Eigene Ergebnisse in Turnieren, die der Verein ausrichtet oder an denen er teilnimmt.
{
"items": [
{ "id": "r1", "competitionId": "c1", "competition": "Frühjahrsturnier Weeze", "disciplineId": "d1",
"place": 2, "score": 7.4, "timestamp": 1776514800 }
]
}
GET /me/membercard
Der gespeicherte Ausweis, wie das Mitglied ihn sieht. Lesen stellt nie einen neuen Ausweis aus.
{
"card": {
"serial": "MC-2026-0042",
"status": "valid",
"valid": true,
"name": "Anna Schneider",
"memberNumber": "1042",
"departments": ["Voltigieren", "Dressur"],
"validUntil": "2026-12-31"
}
}
Ohne Ausweis: { "card": null }.
Speicher
Alle storage-Endpunkte kennen den Parameter scope:
| Parameter | Ort | Werte | Bedeutung |
|---|---|---|---|
collection | path | 1–64 Zeichen A–Z a–z 0–9 _ - | Sammlung |
key | path | 1–64 Zeichen A–Z a–z 0–9 _ - | Schlüssel |
scope | query | org (Standard), user | geteilt im Verein oder nur für das Mitglied |
GET /storage/{collection}
| Parameter | Ort | Bedeutung |
|---|---|---|
limit | query | 1–200, Standard 50 |
offset | query | Standard 0 |
curl "https://apps.api.methacore.de/v1/storage/notizen?scope=org&limit=2" \
-H "Authorization: Bearer $TOKEN"
{
"items": [
{ "key": "n-1", "value": { "text": "Sattel zur Reparatur" }, "updatedAt": 1790582100 },
{ "key": "n-2", "value": "Hallenplan aushängen", "updatedAt": 1790664000 }
],
"total": 14
}
Sortiert nach Schlüssel, aufsteigend.
GET /storage/{collection}/{key}
{ "key": "n-1", "value": { "text": "Sattel zur Reparatur" }, "updatedAt": 1790582100 }
404 This key does not exist., wenn es den Schlüssel nicht gibt.
PUT /storage/{collection}/{key}
curl -X PUT "https://apps.api.methacore.de/v1/storage/notizen/n-3?scope=user" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "value": { "text": "Meine private Notiz" } }'
Der Körper ist ein Objekt mit genau einem Feld value – beliebiges JSON. Die Antwort ist der gespeicherte Eintrag:
{ "key": "n-3", "value": { "text": "Meine private Notiz" }, "updatedAt": 1790700000 }
DELETE /storage/{collection}/{key}
Antwortet mit 204 ohne Körper, oder mit 404, wenn es den Schlüssel nicht gab.
Fehler
Fehler der API selbst kommen als { "detail": "<Meldung>" }. Fehler, die schon das Gateway abfängt (Token fehlt oder abgelaufen, Kontingent, Produkt nicht erreichbar), kommen im gemeinsamen Format aller Produkt-APIs: { "error": { "code", "message", "request_id" } }.
| Status | Meldung | Ursache |
|---|---|---|
400 | value is missing. | PUT ohne { "value": … } |
400 | Send start and end as a range of at most a year. | me/events mit zu großem Zeitraum |
401 | This token is not valid. / This token has expired. … | Token fehlt, ist unbekannt oder abgelaufen – erneuern über POST /v1/oauth/token |
403 | This token does not carry the <scope> scope. | dem Token fehlt der Scope des Endpunkts. Den Scope nachfordern: siehe Berechtigungen. |
403 | This client is not a Methacore app. | der Client des Tokens gehört zu keiner App – storage/* braucht einen Client der API „Methacore Apps“ |
404 | This member does not exist in this club. | das Mitglied ist nicht (mehr) im Verein des Tokens |
404 | This key does not exist. | Schlüssel unbekannt |
404 | This API answers at apps.api.methacore.de. | falsche Subdomain |
413 | App storage quota exceeded. | die 10 MB je App und Verein sind voll; nichts wurde gespeichert |
422 | scope is org or user. | anderer Wert für scope |
422 | Names use 1 to 64 letters, digits, '_' or '-'. | ungültiger Name für Sammlung oder Schlüssel |
429 | rate_limited | Kontingent der Anfragen erschöpft, siehe Retry-After |
Die SDKs erkennen den 403 für fehlende Scopes an der Meldung does not carry the <scope> scope – ändere sie nicht, wenn du einen eigenen Proxy davor setzt.