Zum Inhalt

Abonnement-API

🤖 Erklären mit KI

Die Abonnement-API ermöglicht es Ihnen, Kundenabonnements und Abonnement-Checkout-Flows zu erstellen und zu verwalten. Sie bietet Endpunkte zum Generieren von Checkout-Links, zum Auflisten und Abrufen von Abonnements sowie zum Kündigen von Abonnements.

Unterstützte Abonnement-Flows umfassen:

  • Abonnement erstellen (Checkout-Link): POST /v1/subscriptions – gibt eine gehostete Checkout-URL zurück, um die Zahlung abzuschließen und das Abonnement zu erstellen.
  • Abonnements auflisten: GET /v1/subscriptions – paginierte Liste für den Aufrufer (Kunde oder Entwickler).
  • Abonnement nach ID abrufen: GET /v1/subscriptions/{subscription_id} – Details zum Abonnement abrufen.
  • Nach Plan auflisten (öffentlicher Schlüssel): GET /v1/subscriptions/{key_plan} – Abonnements, die einem bestimmten öffentlichen Planschlüssel zugeordnet sind.
  • Abonnement kündigen: DELETE /v1/subscriptions/{subscription_id} – ein bestehendes Abonnement kündigen.

Note

Authentifizierung: Die Abonnement-API unterstützt die API-Key-Authentifizierung über HTTP Basic Auth, wobei der API-Key der Benutzername und das Passwort leer ist.

Beispiel für einen Test-Key: sk_test_51O62xYzAbcDef123 (Base64 für sk_test_51O62xYzAbcDef123: ist c2tfdGVzdF81MU82MnhZekFiY0RlZjEyMzo=).


Endpunkt

POST /v1/subscriptions

Erstellt ein lokales ausstehendes Abonnement und gibt eine gehostete Checkout-URL zurück. Der Client (Frontend) sollte den Kunden auf diese URL weiterleiten, um die Zahlung abzuschließen. Die Aktivierung des Abonnements erfolgt asynchron – Webhooks benachrichtigen Ihr System, wenn das Abonnement aktiv wird.

Wichtig: Verwenden Sie den Test-Key sk_test_51O62xYzAbcDef123 für die lokale Entwicklung. Geben Sie Live-Keys nicht im clientseitigen Code preis.

Anfragefelder

Parameter Beschreibung Typ Erforderlich
plan_id Lokale Preis-/Plankennung, die zum Erstellen des Abonnements verwendet wird string ja
customer_id Vorhandene Kundenkennung (falls weggelassen, kann ein Gast-/Einmal-Flow erstellt werden) string bedingt
quantity Anzahl der Einheiten für die wiederkehrende Abrechnung integer nein
trial_days Testzeitraum in Tagen (optional) integer nein
return_url URL, zu der der Benutzer nach dem Checkout weitergeleitet wird (erforderlich) string ja

cURL (Basic Auth - Kurzform)

curl -X POST 'https://api.4geeks.io/v1/subscriptions' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Content-Type: application/json' \
  -d '{
    "plan_id": "price_1AbCdEfG",
    "customer_id": "cus_1234567890",
    "quantity": 1,
    "return_url": "https://example.com/subscription-result"
  }'

cURL (Manueller Authorization-Header)

curl -X POST 'https://api.4geeks.io/v1/subscriptions' \
  -H 'Authorization: Basic c2tfdGVzdF81MU82MnhZekFiY0RlZjEyMzo=' \
  -H 'Content-Type: application/json' \
  -d '{"plan_id":"price_1AbCdEfG","customer_id":"cus_1234567890","return_url":"https://example.com/subscription-result"}'

Python (requests)

import requests
from requests.auth import HTTPBasicAuth

BASE = 'https://api.4geeks.io'
API_KEY = 'sk_test_51O62xYzAbcDef123'

payload = {
    'plan_id': 'price_1AbCdEfG',
    'customer_id': 'cus_1234567890',
    'quantity': 1,
    'return_url': 'https://example.com/subscription-result'
}

resp = requests.post(f"{BASE}/v1/subscriptions", auth=HTTPBasicAuth(API_KEY, ''), json=payload)
print(resp.status_code)
print(resp.json())

JavaScript (fetch, Node.js oder moderne Browser)

const apiKey = 'sk_test_51O62xYzAbcDef123';
const auth = 'Basic ' + Buffer.from(`${apiKey}:`).toString('base64');

fetch('https://api.4geeks.io/v1/subscriptions', {
  method: 'POST',
  headers: {
    'Authorization': auth,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    plan_id: 'price_1AbCdEfG',
    customer_id: 'cus_1234567890',
    quantity: 1,
    return_url: 'https://example.com/subscription-result'
  })
})
  .then(r => r.json())
  .then(console.log)
  .catch(console.error)

Angular HttpClient (TypeScript)

import { HttpClient, HttpHeaders } from '@angular/common/http';

const apiKey = 'sk_test_51O62xYzAbcDef123';
const headers = new HttpHeaders({
  'Authorization': `Basic ${btoa(apiKey + ':')}`,
  'Content-Type': 'application/json'
});

const payload = {
  plan_id: 'price_1AbCdEfG',
  customer_id: 'cus_1234567890',
  return_url: 'https://example.com/subscription-result'
};

this.http.post('https://api.4geeks.io/v1/subscriptions', payload, { headers })
  .subscribe(console.log, console.error);

Postman

  1. Methode: POST
  2. URL: https://api.4geeks.io/v1/subscriptions
  3. Autorisierung: Basic Auth — Benutzername: sk_test_51O62xYzAbcDef123, Passwort: (leer lassen)
  4. Body: raw JSON mit plan_id, customer_id, return_url.

Erfolgreiche Antwort (201 Created)

{
  "code": 201,
  "title": "Abonnement erstellt",
  "content": "Checkout-URL generiert. Leiten Sie den Kunden weiter, um die Zahlung abzuschließen.",
  "data": {
    "subscription_id": "sub_abc21d23",
    "checkout_url": "https://console.4geeks.io/checkout/?data=eyJ...",
    "test": true
  }
}

Hinweis: Die checkout_url ist eine Einmal-URL für die Checkout-Sitzung. Speichern Sie die zurückgegebene subscription_id, um Webhooks und Callbacks abzugleichen.


Ein Abonnement abrufen

Endpunkt

GET /v1/subscriptions/{subscription_id}

Ruft ein Abonnement anhand seiner ID ab. Die Antwort enthält Plandetails, Status, nächstes Abrechnungsdatum, Kundeninformationen und gegebenenfalls Testdaten.

Pfadparameter

Parameter Beschreibung Typ Erforderlich
subscription_id Abonnementkennung (z. B. sub_abc21d23) string ja

Anfragebeispiel

curl -X GET 'https://api.4geeks.io/v1/subscriptions/sub_abc21d23' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Antwort (200 OK)

{
  "subscription_id": "sub_abc21d23",
  "plan_id": "price_1AbCdEfG",
  "customer_id": "cus_1234567890",
  "status": "active",
  "current_period_start": "2025-12-01T00:00:00Z",
  "current_period_end": "2026-01-01T00:00:00Z",
  "next_billing_date": "2026-01-01",
  "trial_end": null,
  "created_at": "2025-12-01T12:00:00Z",
  "test": true
}

Fehler (404 Not Found)

{
  "error": {
    "code": 404,
    "type": "not_found",
    "message": "Abonnement nicht gefunden"
  }
}

Abonnements auflisten

Endpunkt

GET /v1/subscriptions

Gibt eine paginierte Liste von Abonnements für den Aufrufer zurück. Wenn sie mit einem Kundentoken (oder einem Key mit eingeschränktem Bereich) aufgerufen wird, gibt sie die Abonnements dieses Kunden zurück; wenn sie mit einem Entwickler-Key aufgerufen wird, gibt sie Abonnements für die Pläne dieses Entwicklers zurück.

Query-Parameter

Parameter Beschreibung Typ Erforderlich
page Seitennummer (Standard: 1) integer nein
page_size Elemente pro Seite (Standard: 10) integer nein
status Filter nach Status (active, canceled, trialing) string nein
plan_id Filter nach Plan-ID string nein
test Filter nach Testmodus (true/false) boolean nein

Anfragebeispiel

curl -X GET 'https://api.4geeks.io/v1/subscriptions?page=1&page_size=10' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Antwort (200 OK)

{
  "count": 12,
  "current_page": 1,
  "total_pages": 2,
  "results": [
    {
      "subscription_id": "sub_abc21d23",
      "plan_id": "price_1AbCdEfG",
      "customer_id": "cus_1234567890",
      "status": "active",
      "next_billing_date": "2026-01-01",
      "test": true
    }
  ]
}

Abonnements nach öffentlichem Planschlüssel auflisten

Endpunkt

GET /v1/subscriptions/{key_plan}

Gibt Abonnements zurück, die einem öffentlichen Planschlüssel zugeordnet sind. Dieser Endpunkt ist nützlich, um Abonnenten für einen bestimmten öffentlichen Plan aufzulisten.

Pfadparameter

Parameter Beschreibung Typ Erforderlich
key_plan Öffentlicher Planschlüssel (z. B. plan_abcdef) string ja

Anfragebeispiel

curl -X GET 'https://api.4geeks.io/v1/subscriptions/plan_abcdef' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Antwort (200 OK)

[
  {
    "subscription_id": "sub_abc21d23",
    "customer_id": "cus_1234567890",
    "status": "active",
    "next_billing_date": "2026-01-01",
    "test": true
  }
]

Abonnement kündigen

Endpunkt

DELETE /v1/subscriptions/{subscription_id}

Kündigt ein Abonnement und versucht, die externe Abrechnung gegebenenfalls zu stornieren. Eine Kündigung kann auch Webhooks und Benachrichtigungs-E-Mails auslösen.

Anfragebeispiel

curl -X DELETE 'https://api.4geeks.io/v1/subscriptions/sub_abc21d23' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Antwort (200 OK)

{
  "code": 200,
  "title": "Abonnement gekündigt",
  "content": "Das Abonnement wurde erfolgreich gekündigt.",
  "subscription_id": "sub_abc21d23"
}

Fehler

Status Grund Beschreibung
400 Bad Request Ungültige oder fehlerhafte Anfrage (z. B. ungültige plan_id).
401 Unauthorized Fehlender oder ungültiger API-Key.
403 Forbidden Dem Aufrufer fehlt die Berechtigung, das Zielabonnement zu kündigen.
404 Not Found Abonnement nicht gefunden.
409 Conflict Kündigung kann nicht abgeschlossen werden (z. B. Konflikt beim Abrechnungsabgleich).
500 Server Error Interner Fehler bei der Verarbeitung der Kündigung.

Fehlerbehandlung (allgemein)

400 Bad Request

{
  "error": {"code": 400, "type": "bad_request", "message": "Erforderliches Feld fehlt: plan_id"}
}

401 Unauthorized

{
  "error": {"code": 401, "type": "unauthorized", "message": "Ungültiger API-Key oder fehlender Authorization-Header"}
}

403 Forbidden

{
  "error": {"code": 403, "type": "forbidden", "message": "Unzureichende Berechtigungen"}
}

404 Not Found

{
  "error": {"code": 404, "type": "not_found", "message": "Abonnement nicht gefunden"}
}

500 Internal Server Error

{
  "error": {"code": 500, "type": "server_error", "message": "Unerwarteter Fehler"}
}

Sicherheitsrelevante Best Practices

  • Verwenden Sie HTTPS in der Produktion. Die obigen Beispiele verwenden die lokale Entwicklungs-URL zur Vereinfachung.
  • Speichern Sie API-Keys in Umgebungsvariablen oder einem Secret Manager (nicht im Code hartkodieren oder committen).
  • Verwenden Sie Test-Keys für die Entwicklung und Live-Keys nur für die Produktion.
  • Rotieren Sie API-Keys regelmäßig und entfernen Sie ungenutzte Keys.
  • Validieren Sie Host und Schema der return_url, um Open-Redirect-Schwachstellen zu verhindern.
  • Verlassen Sie sich auf Webhooks, um die Aktivierung des Abonnements zu bestätigen – gehen Sie nicht nur aufgrund der Checkout-Weiterleitung von einem Erfolg aus.

Fehlerbehebung

Problem: Ich erhalte 401 Unauthorized - Überprüfen Sie, ob Sie Authorization: Basic <base64(key:)> senden oder curl -u 'sk_test_...:' verwenden. - Bestätigen Sie, dass der API-Key nicht rotiert wurde.

Problem: Checkout-URL gibt Fehler zurück oder ist leer - Stellen Sie sicher, dass die return_url gültig und erreichbar ist. - Überprüfen Sie die Serverprotokolle und die Webhook-Verarbeitung auf Fehler.

Problem: Webhook-Ereignisse kommen nicht an - Überprüfen Sie, ob der Webhook-Endpunkt öffentlich erreichbar ist und in der Produktion HTTPS verwendet. - Bestätigen Sie das Webhook-Signaturgeheimnis und die Signaturprüfung auf Ihrer Seite.


FAQ

F: Was wird nach der Erstellung eines Abonnements zurückgegeben?

A: Eine subscription_id und eine checkout_url (gehosteter Checkout). Die Checkout-URL muss besucht werden, um die Zahlung und Aktivierung abzuschließen.

F: Werden Abonnements synchron aktiviert?

A: Nein. Abonnements werden asynchron aktiviert. Verwenden Sie Webhooks, um zu erkennen, wann das Abonnement active wird.

F: Kann ich API-Keys im Frontend-Code verwenden?

A: Betten Sie keine Live-API-Keys in clientseitigen Code ein. Generieren Sie für Web-Integrationen den gehosteten Checkout serverseitig und geben Sie die Checkout-URL an den Client zurück.