REST API für deine JoinOurServer-Community. JSON in / JSON out. Bearer-Authentifizierung per API-Key.
https://api.joinourserver.com/v1
Keine harten Limits im Dev-Modus. In Production: 1000 requests/hour pro API-Key.
Jede Anfrage muss deinen API-Key als Bearer-Token im Authorization-Header mitschicken:
Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx
Dein API-Key findest du im Partner-Dashboard unter Einstellungen → API & Webhooks. Du kannst den Schlüssel dort auch regenerieren.
Jede Subscription erhält optional einen eindeutigen License-Key
(Format: PH-XXXX-XXXX-XXXX-XXXX), wenn der zugehörige Plan die Option
„Seriennummer generieren" aktiviert hat (Standard: an).
Deine eigene Software (z.B. ein Minecraft-Plugin, Trading-Tool, Desktop-App…) kann diesen Key gegen die API verifizieren, um zu prüfen ob der User eine gültige, bezahlte Subscription hat — und dabei zusätzliche Daten pro Subscription auslesen.
/licenses/verify
Prüft einen License-Key gegen deine Community. Der Call ist auf deinen Partner-Account
geschränkt — Keys anderer Partner werden mit not_found beantwortet.
{
"license_key": "PH-ABCD-EF01-2345-6789"
}
curl -X POST https://api.joinourserver.com/v1/licenses/verify \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"license_key":"PH-ABCD-EF01-2345-6789"}'
{
"valid": true,
"status": "active",
"license_key": "PH-ABCD-EF01-2345-6789",
"custom_data": "user_42/level_gold",
"subscription": {
"id": "sub_xxx",
"status": "active",
"billing_type": "recurring",
"created_at": "2026-04-14 11:30:00",
"next_payment_date": "2026-05-14",
"access_expires_at": null,
"canceled_at": null
},
"plan": {
"id": "plan_premium",
"name": "Premium",
"price": 29.99,
"interval": "1 month",
"billing_type": "recurring"
},
"member": {
"id": "mem_xxx",
"discord_id": "322101351830126594",
"discord_username": "Chacky",
"discord_email": "user@example.com",
"discord_avatar": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"discord_avatar_url": "https://cdn.discordapp.com/avatars/322101351830126594/a1b2c3d4e5f60718293a4b5c6d7e8f90.png",
"name": "Chacky",
"status": "active"
}
}
discord_avatar ist der rohe Avatar-Hash, den Discord für den User vergeben hat.
discord_avatar_url liefert die fertige CDN-URL als <img src="…">-tauglichen
Link — animierte Avatare (Hash beginnt mit a_) werden als .gif ausgeliefert,
alle anderen als .png. Hat der User keinen eigenen Avatar gesetzt, zeigt die URL auf eines der
6 Discord-Default-Avatare.
{
"valid": false,
"status": "canceled", // or "expired" / "past_due" / "refunded"
"license_key": "PH-ABCD-EF01-2345-6789",
... (same sub/plan/member structure)
}
HTTP/1.1 404 Not Found
{"valid": false, "error": "not_found"}
valid === true. Der
status gibt dir zusätzlich Kontext warum ein Key eventuell ungültig ist
(expired, canceled, past_due, refunded).
/licenses/{license_key}
Identische Response wie POST /licenses/verify — praktisch wenn du einen
GET-basierten Check brauchst (z.B. Browser-Extension).
curl https://api.joinourserver.com/v1/licenses/PH-ABCD-EF01-2345-6789 \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx"
/subscriptions/{subscription_id}
Pro Subscription kannst du ein freies Text-Feld setzen, das bei jeder License-Verify-Anfrage zurückgegeben wird. Perfekt für User-spezifische Daten wie Level, Permissions, Feature-Flags.
Limit: Max 100 Zeichen pro Subscription. Werte länger als 100 Zeichen werden mit HTTP 400 abgelehnt.
{
"custom_data": "tier=gold;seats=5;feature_ai=1"
}
{
"id": "sub_xxx",
"custom_data": "tier=gold;seats=5;feature_ai=1",
"status": "active",
"license_key": "PH-ABCD-EF01-2345-6789",
...
}
/members
| Parameter | Typ | Beschreibung |
|---|---|---|
page | integer | Seite (Default 1) |
limit | integer | Pro Seite (Default 20, max 100) |
status | string | active, trial, waitlisted, canceled, expired, past_due, pending, rejected |
plan_id | string | Filter nach Plan |
curl "https://api.joinourserver.com/v1/members?status=active&limit=50" \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx"
{
"members": [
{
"id": "mem_1234567890abcdef",
"discord_id": "322101351830126594",
"discord_username": "Chacky",
"discord_email": "user@example.com",
"discord_avatar": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"discord_avatar_url": "https://cdn.discordapp.com/avatars/322101351830126594/a1b2c3d4e5f60718293a4b5c6d7e8f90.png",
"name": "Chacky",
"status": "active",
"plan_id": "plan_premium",
"access_expires_at": null,
"created_at": "2026-04-14 11:30:00",
"metadata": {}
}
],
"pagination": {
"total": 156,
"page": 1,
"per_page": 50,
"total_pages": 4
}
}
discord_access_token und
discord_refresh_token werden nie in Responses zurückgegeben.
/members/{id}
curl https://api.joinourserver.com/v1/members/mem_xxx \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx"
/members/{id}
Erlaubte Felder: name, status, email, metadata.
{
"status": "active",
"metadata": {"notes": "VIP customer"}
}
Ein Member kann mehrere Subscriptions parallel haben (z.B. verschiedene Pläne oder denselben Plan mehrfach). Jede Subscription hat einen eigenen License-Key, Status und Access-Expiry.
/subscriptions
status | string | active, trial, past_due, canceled, expired |
member_id | string | Alle Subs eines Members |
plan_id | string | Alle Subs eines Plans |
limit | integer | Default 50, max 100 |
offset | integer | Pagination |
curl "https://api.joinourserver.com/v1/subscriptions?status=active" \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx"
/subscriptions/{id}
/subscriptions/{id}
Erlaubte Felder:
custom_data (string, max 100 Zeichen) — frei nutzbares Text-Feld, wird bei License-Verify zurückgegeben/payments
curl https://api.joinourserver.com/v1/payments \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx"
Hinweis: Beträge werden in Cent zurückgegeben. 2999 = 29,99 €.
/plans
curl https://api.joinourserver.com/v1/plans \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx"
/stats
{
"monthly_revenue_cents": 125000,
"monthly_revenue": 1250.00,
"active_members": 42,
"platform_fee": 31.25,
"platform_fee_percentage": 2.5,
"conversion_rate": 68.5
}
JoinOurServer POSTet Events an deine konfigurierte Webhook-URL
(Settings → API). Jede Payload ist mit HMAC-SHA256 über deinen API-Key signiert
(Header X-JoinOurServer-Signature: sha256=<hex>).
member.created | Neuer Member angelegt |
member.updated | Member-Daten aktualisiert |
member.deleted | Member deaktiviert |
subscription.canceled | Subscription gekündigt |
payment.refunded | Zahlung erstattet |
function verifyWebhookSignature(payload, signature, apiKey) {
const expected = 'sha256=' + crypto
.createHmac('sha256', apiKey)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
HMAC-Schlüssel = der API-Key, mit dem die ursprüngliche Aktion ausgelöst wurde
(z.B. wenn dein Webhook-Backend einen POST /members macht, signieren wir
den daraus resultierenden member.created-Webhook mit demselben Key).
Bei systeminternen Events fällt die Signatur auf den ältesten nicht-widerrufenen
Key des Partners zurück.
{
"error": {
"type": "validation_error",
"code": "invalid_api_key",
"message": "Invalid or missing API key"
}
}
200 | OK |
201 | Created |
204 | No Content (z.B. bei DELETE) |
400 | Bad Request — Validierung fehlgeschlagen |
401 | Unauthorized — API-Key fehlt oder ungültig |
404 | Nicht gefunden |
405 | Methode nicht erlaubt |
500 | Interner Serverfehler |
Wir verwenden Cookies und ähnliche Technologien, um die Plattform betreiben und ihre Nutzung analysieren zu können. „Notwendige" Cookies sind technisch erforderlich (Login, Session, CSRF). Statistik- und Marketing-Cookies sind nur aktiv, wenn du zustimmst. Mehr Infos: Datenschutzerklärung.
Session, Login, CSRF-Schutz. Diese Cookies sind für den Betrieb der Seite zwingend nötig und können nicht deaktiviert werden.
Anonymisierte Nutzungsdaten (Seitenaufrufe, Browser, ungefährer Standort) zur Verbesserung der Plattform. ID: G-K1B9Z8G1ZC.
Tag Manager zur dynamischen Einbindung von Werbe-Pixeln und Conversion-Tracking. ID: GTM-54M9WF9Z.