Zum Inhalt springen

Schnellstart in fünf Minuten

Erst ausprobieren, ohne Echtdaten? Die Sandbox bietet erfundene Musterdaten und eigene Test-Tokens (m2h_test_…) — nutzbar, solange der API-Zugang aktiv ist (auch in der kostenlosen Testzeit), samt Webhooks und Ereignis-Simulation per Beispielaufruf.

Voraussetzungen

  • Die API ist für Ihre Organisation freigeschaltet (Testzeit oder Buchung). Unter Administration → API-Zugänge sehen Sie den Stand; ohne Freischaltung lässt sich kein Token anlegen.
  • Sie haben in der Verwaltung das Recht API-Zugang mit Vollzugriff (nur damit lassen sich Tokens anlegen) und selbst alle Rechte, die das Token bekommen soll.
  • Ein Rechner oder Server mit Internetzugang, der https-Anfragen senden kann (curl genügt). Die API ist für Server-zu-Server-Aufrufe gedacht, nicht für Browser.

1. Token anlegen

In der Verwaltung: Administration → API-Zugänge → Neues Token. Name vergeben (z. B. „Schnellstart“), als Berechtigung genau einen Scope wählen — für diesen Schnellstart locations:read („Garagenparks lesen“; der Ersteller braucht dafür das Recht Standorte mit Lesezugriff) — und eine Laufzeit wählen. Weitere Scopes: Berechtigungen.

Das Token wird nur ein einziges Mal angezeigt. Kopieren Sie es sofort in einen Passwort-Manager oder den Secret-Speicher Ihres Programms.

2. Token bereitstellen

Legen Sie das Token als Umgebungsvariable M2H_API_TOKEN ab — nie direkt im Quelltext.

PowerShell
$env:M2H_API_TOKEN = "m2h_live_…"
Linux / macOS
export M2H_API_TOKEN="m2h_live_…"

3. Erster Aufruf: Ihre Garagenparks

Die curl-Beispiele sind in Bash-Schreibweise ($VARIABLE, \ am Zeilenende, $(uuidgen)): Sie laufen unter Linux, macOS und Git Bash. Unter Windows nehmen Sie das PowerShell-Beispiel direkt darunter.

curl (Bash: Linux, macOS, Git Bash)
curl -s "https://api.manage2hero.com/v1/locations" \
  -H "Authorization: Bearer $M2H_API_TOKEN"
PowerShell (Windows)
$kopf = @{ Authorization = "Bearer $env:M2H_API_TOKEN" }
Invoke-RestMethod -Uri "https://api.manage2hero.com/v1/locations" -Headers $kopf
JavaScript (Node.js 18+)
const res = await fetch('https://api.manage2hero.com/v1/locations', {
  headers: { Authorization: `Bearer ${process.env.M2H_API_TOKEN}` },
});
const body = await res.json();
if (!body.success) throw new Error(`${body.error.code}: ${body.error.message}`);
const daten = body.data; // hier weiterverarbeiten
Python (requests)
import os, requests

res = requests.get(
    "https://api.manage2hero.com/v1/locations",
    headers={"Authorization": f"Bearer {os.environ['M2H_API_TOKEN']}"},
    timeout=30,
)
body = res.json()
if not body["success"]:
    raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["data"])

Antwort (200, vollständig)

JSON
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "6a1f0c2e-4d7b-4b8e-9f10-2c3d4e5f6a7b",
        "code": "HH01",
        "name": "Garagenpark Hamburg Nord",
        "street": "Beispielweg",
        "house_number": "12",
        "postal_code": "22297",
        "city": "Hamburg",
        "country_code": "DE",
        "active": true
      }
    ],
    "next_cursor": null
  },
  "request_id": "req_4a2c9e1b7e84d2f9c0a6b3d5e7f1a2c9"
}

items enthält je Garagenpark ein Objekt; ohne Garagenpark ist die Liste leer ([]). next_cursor ist null, wenn es keine weitere Seite gibt. Mit der id eines Garagenparks rufen Sie anschließend z. B. die Vermietungsquote ab: GET /v1/locations/{id}/occupancy.

Typische Fehler beim ersten Aufruf

HTTPerror.codeUrsacheAbhilfe
401missing_tokenDer Kopf Authorization fehlt oder ist leer (häufig: die Umgebungsvariable ist nicht gesetzt).Kopf Authorization: Bearer <token> senden; Variable prüfen.
401invalid_tokenToken falsch kopiert (Leerzeichen, Anführungszeichen), widerrufen oder der Ersteller wurde deaktiviert.Token neu kopieren; sonst in der Verwaltung ein neues anlegen.
401token_expiredDie Laufzeit des Tokens ist vorbei.Neues Token anlegen und austauschen.
401wrong_environmentEin Token der Umgebung stg oder dev wurde gegen Produktion verwendet (oder umgekehrt).Token der passenden Umgebung (live, stg, dev) verwenden.
403insufficient_scopeDem Token fehlt der Scope des Endpunkts; error.required_scope nennt ihn.Neues Token mit diesem Scope anlegen — ein bestehendes lässt sich nicht erweitern.
403insufficient_permissionsDer Ersteller des Tokens hat das nötige Recht in der Verwaltung nicht (mehr).Recht ergänzen; das Token funktioniert danach ohne Änderung wieder.
429rate_limitedZu viele Aufrufe in kurzer Zeit.Retry-After abwarten, dann wiederholen (siehe Grenzen).
403: fehlender Scope
{
  "success": false,
  "error": {
    "code": "insufficient_scope",
    "message": "Das API-Token hat nicht die nötige Berechtigung (Scope).",
    "required_scope": "locations:read"
  },
  "request_id": "req_8c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f"
}

Alle Fehlercodes mit Handlungsanweisung: Fehlercodes; Mengengrenzen: Grenzen.

4. Optional: Ereignisse per Webhook empfangen

Statt regelmäßig abzufragen, meldet Manage²Hero Ereignisse (Zahlungseingang, Mahnung, Vertrag, Rechnung, Dokument, E-Mail, Schaden) per signiertem POST an Ihr System. Der kürzeste Weg:

  1. Webhook anlegen: neues Token mit webhooks:manage (Ersteller: API-Zugang mit Vollzugriff) und den Lese-Scopes der Ereignisse, die Sie abonnieren. Ihre Adresse muss eine öffentlich erreichbare https-Adresse auf Port 443 sein.
curl (Bash: Linux, macOS, Git Bash)
curl -s -X POST "https://api.manage2hero.com/v1/webhooks" \
  -H "Authorization: Bearer $M2H_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  --data '{"url":"https://erp.example.com/hooks/manage2hero","events":["payment.received","invoice.created"],"description":"ERP Buchhaltung"}'
PowerShell (Windows)
$kopf = @{
  Authorization     = "Bearer $env:M2H_API_TOKEN"
  "Idempotency-Key" = [guid]::NewGuid().ToString()
}
$body = '{"url":"https://erp.example.com/hooks/manage2hero","events":["payment.received","invoice.created"],"description":"ERP Buchhaltung"}'
Invoke-RestMethod -Method Post -Uri "https://api.manage2hero.com/v1/webhooks" -Headers $kopf -ContentType "application/json; charset=utf-8" -Body $body
JavaScript (Node.js 18+)
import { createHash, randomUUID } from 'node:crypto';
import { linkSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';

// Schlüssel EINMAL erzeugen und VOR dem Senden dauerhaft speichern (hier: Datei, eine je Vorgang). Nach einem
// Neustart wird derselbe Schlüssel gelesen. Für einen neuen, anderen Vorgang einen neuen Dateinamen wählen. Datei erst nach der endgültigen Antwort löschen.
const VORGANG = 'auftrag-2026/1001'; // EIGENE Kennung je Vorgang setzen (z. B. Auftrags-Id); nie für zwei Vorgänge wiederverwenden
const VORGANG_ID = createHash('sha256').update(VORGANG).digest('hex').slice(0, 16); // als Dateiname gehasht: beliebige Zeichen (/, \ …) in der Kennung sind unkritisch
const KEY_FILE = `idempotency-key-post-v1-webhooks-${VORGANG_ID}.txt`;
const neu = randomUUID();
const tmp = `${KEY_FILE}.${neu}`; // eindeutiger Name je Versuch, nie eine vorhandene Datei überschreiben
writeFileSync(tmp, neu, { flag: 'wx' }); // erst vollständig in eine temporäre Datei schreiben
try {
  linkSync(tmp, KEY_FILE); // veröffentlicht sie atomar, ohne eine vorhandene zu überschreiben
} catch (e) {
  if (e.code !== 'EEXIST') throw e; // vorhandener Schlüssel bleibt unverändert
} finally {
  unlinkSync(tmp);
}
const idempotencyKey = readFileSync(KEY_FILE, 'utf8').trim();

const res = await fetch('https://api.manage2hero.com/v1/webhooks', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.M2H_API_TOKEN}`,
    'Content-Type': 'application/json',
    // Bei jeder Wiederholung (z. B. nach einem Timeout) diesen gespeicherten Schlüssel erneut senden.
    'Idempotency-Key': idempotencyKey,
  },
  body: JSON.stringify({
    "url": "https://erp.example.com/hooks/manage2hero",
    "events": [
      "payment.received",
      "invoice.created"
    ],
    "description": "ERP Buchhaltung"
  }),
});
const body = await res.json();
if (!body.success) throw new Error(`${body.error.code}: ${body.error.message}`);
const daten = body.data; // hier weiterverarbeiten
Python (requests)
import hashlib, os, uuid, requests
from pathlib import Path

# Schlüssel EINMAL erzeugen und VOR dem Senden dauerhaft speichern (hier: Datei, eine je Vorgang). Nach einem
# Neustart wird derselbe Schlüssel gelesen. Für einen neuen, anderen Vorgang einen neuen Dateinamen wählen. Datei erst nach der endgültigen Antwort löschen.
VORGANG = "auftrag-2026/1001"  # EIGENE Kennung je Vorgang setzen (z. B. Auftrags-Id); nie für zwei Vorgänge wiederverwenden
VORGANG_ID = hashlib.sha256(VORGANG.encode()).hexdigest()[:16]  # als Dateiname gehasht: beliebige Zeichen (/, \ …) in der Kennung sind unkritisch
KEY_FILE = Path(f"idempotency-key-post-v1-webhooks-{VORGANG_ID}.txt")
neu = str(uuid.uuid4())
tmp = Path(f"{KEY_FILE}.{neu}")  # eindeutiger Name je Versuch, nie eine vorhandene Datei überschreiben
with tmp.open("x") as f:
    f.write(neu)  # erst vollständig in eine temporäre Datei schreiben
try:
    os.link(tmp, KEY_FILE)  # veröffentlicht sie atomar, ohne eine vorhandene zu überschreiben
except FileExistsError:
    pass  # vorhandener Schlüssel bleibt unverändert
finally:
    tmp.unlink()
idempotency_key = KEY_FILE.read_text().strip()

res = requests.post(
    "https://api.manage2hero.com/v1/webhooks",
    headers={
        "Authorization": f"Bearer {os.environ['M2H_API_TOKEN']}",
        "Idempotency-Key": idempotency_key,
    },
    json={"url":"https://erp.example.com/hooks/manage2hero","events":["payment.received","invoice.created"],"description":"ERP Buchhaltung"},
    timeout=30,
)
body = res.json()
if not body["success"]:
    raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["data"])
  1. Geheimnis speichern: Die Antwort (201) enthält einmalig das secret (whsec_…). Legen Sie es sofort im Secret-Speicher Ihres Empfängers ab. Verloren? Mit POST /v1/webhooks/{id}/rotate-secret erzeugen Sie ein neues.
  2. Testen: POST /v1/webhooks/{id}/test (mit Idempotency-Key) stellt ein Testereignis webhook.test ein; der Server sendet es innerhalb von etwa einer Minute.
curl
curl -s -X POST "https://api.manage2hero.com/v1/webhooks/3f6c1b52-8a47-4d09-9e1c-5b2a7d4e6f80/test" \
  -H "Authorization: Bearer $M2H_API_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
  1. Zustellstatus prüfen: GET /v1/webhooks/{id}/deliveries zeigt je Zustellung status (pending, succeeded, failed, abandoned, paused), response_status (Antwortcode Ihres Empfängers) und einen festen error-Code. succeeded mit response_status: 200 heißt: Ihr Empfänger funktioniert. Eine Nachricht wird bis zu 6 Mal versucht; scheitert der letzte Versuch, wird der Webhook abgeschaltet (active: false). Der Zustellverlauf wird 30 Tage aufbewahrt.
Gesendet wird nur aus der Produktion; in Entwicklung und Staging bleiben Zustellungen offen (pending). Signatur prüfen, Wiederholungen, Abschaltung und Betrieb: das Webhooks-Handbuch. Ein lauffähiges Empfänger-Projekt (Signaturprüfung, Eingangstabelle, Abgleich) gibt es als ZIP zum Herunterladen (ohne Anmeldung, Beispielcode unter MIT-Lizenz). Die Nachrichten sind in der openapi.json im Abschnitt webhooks beschrieben (nicht unter paths; wichtig für Codegeneratoren). Die wichtigsten Regeln für den Betrieb fasst die Integrations-Checkliste zusammen. Alle Aufrufe zum Ausprobieren gibt es als Postman-Sammlung.