Zum Inhalt
Für Entwickler

Integration in Minuten

Ein einziges PHP-SDK ohne Abhängigkeiten: Rechnungen erstellen, zur gehosteten Bezahlseite weiterleiten und signierte Webhooks prüfen. Für jede andere Sprache gibt es REST.

API auf einen Blick
  • Basis-URLapi.payora.money
  • AuthentifizierungHMAC-SHA256
  • FormatJSON · HTTPS
  • SDKsPHP · Node.js · Python
  • SpezifikationOpenAPI 3.0
schnellstart

Von der Rechnung zum Webhook

  1. 01

    Rechnung erstellen

    Ein API-Aufruf mit Bestell-ID und einem Betrag in Fiat oder Krypto liefert eine gehostete Zahlungs-URL.

  2. 02

    Kunde zahlt

    Er wählt einen Coin, scannt den QR-Code oder öffnet seine Wallet — der Checkout bestätigt live bei Finalität.

  3. 03

    Du erhältst einen signierten Webhook

    HMAC-Signatur prüfen, Bestellung einmal gutschreiben — und die Zahlung landet auf Ihrem Guthaben.

PHP-SDK

Eine Datei, keine Abhängigkeiten. createInvoice(), getInvoice() und verifyWebhook() — einfach in jedes Projekt legen.

HMAC-Authentifizierung

Anfragen und Webhooks sind mit HMAC-SHA256 signiert, mit Zeitfenster und Idempotenzschlüsseln.

REST-API

Schlichtes JSON über HTTPS — Integration aus jedem Stack, nicht nur aus PHP.

checkout
<?php
require 'Payora.php';
$payora = new Payora('https://api.payora.money', getenv('PAYORA_KEY'), getenv('PAYORA_SECRET'));

// 1 — create an invoice (fiat-priced; the payer picks a coin)
$inv = $payora->createInvoice([
  'order_id'   => 'ORDER-42',
  'mode'       => 'fiat',
  'amount'     => '9.99',
  'return_url' => 'https://shop.example/thanks',
  'lang'       => 'en',
], 'ORDER-42'); // Idempotency-Key: a retry never creates a second invoice
header('Location: ' . $inv['pay_url']);

// 2 — webhook endpoint: ALWAYS verify the signature first
$event = $payora->verifyWebhook(file_get_contents('php://input'), getallheaders());
if ($event === null) { http_response_code(400); exit; }
if ($event['status'] === 'paid') {
  creditOrderOnce($event['id'], $event['order_id'], $event['amount'], $event['currency']);
}
http_response_code(200); // 2xx stops retries

Erhalten Sie Ihren API key und Secret, indem Sie ein Konto erstellen. Das vollständige SDK finden Sie in Ihrem Dashboard.

Authentifizierung

Authentifizierung

Jeder Aufruf außer /v1/health trägt drei signierte Header. Die Signatur belegt, dass die Anfrage vom Inhaber Ihres api_secret stammt und unterwegs nicht verändert wurde.

HeaderWertBeschreibung
X-Payora-Keypk_…Ihr öffentlicher api_key. Identifiziert den Shop.
X-Payora-Timestampunix secondsDer Zeitpunkt der Signatur, in Unix-Sekunden.
X-Payora-Signaturehex · 64HMAC-SHA256 über timestamp + "." + Rohbody mit Ihrem api_secret als Schlüssel, als Hex in Kleinbuchstaben.
X-Payora-Test1Markiert eine Rechnung als Test Ihrer Integration: sie ist echt und kann Münzen empfangen, zählt aber nicht in Nachfrage- und Conversion-Berichten.
Idempotency-KeystringOptional bei POST /v1/invoice und POST /v1/payout. Eine Wiederholung mit demselben Schlüssel liefert das erste Ergebnis statt eines Duplikats; derselbe Schlüssel mit anderem Body ergibt 409.
Content-Typeapplication/jsonPflicht bei Anfragen mit Body.
X-Payora-Signature=hex( HMAC-SHA256( api_secret, timestamp + "." + raw_body ) )

Signieren Sie genau die Bytes, die Sie senden. Wird das JSON nach dem Signieren neu kodiert – selbst mit anderer Schlüsselreihenfolge oder einem zusätzlichen Leerzeichen –, ist die Signatur ungültig.

Bei einer GET-Anfrage ist der Body leer, signiert wird also der Timestamp gefolgt von einem Punkt.

Die API lehnt Timestamps ab, die mehr als 120 Sekunden von ihrer Uhr abweichen. Halten Sie Ihren Server per NTP synchron.

Bewahren Sie api_secret auf Ihrem Server auf. Er signiert Anfragen und Webhooks gleichermaßen: Wer ihn besitzt, kann in Ihrem Namen Rechnungen erstellen und Callbacks fälschen.

sign-request
<?php
$body = json_encode(['order_id' => 'ORDER-42', 'mode' => 'fiat', 'amount' => '9.99'], JSON_UNESCAPED_SLASHES);
$ts   = (string) time();
$sig  = hash_hmac('sha256', $ts . '.' . $body, $apiSecret); // lowercase hex

$ch = curl_init('https://api.payora.money/v1/invoice');
curl_setopt_array($ch, [
  CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'X-Payora-Key: ' . $apiKey,
    'X-Payora-Timestamp: ' . $ts,
    'X-Payora-Signature: ' . $sig,
    'Idempotency-Key: ORDER-42',
    'Content-Type: application/json',
  ],
]);
$invoice = json_decode(curl_exec($ch), true);
POST /v1/invoice

Parameter der Rechnung

Alles optional außer order_id und amount. Im fiat-Modus kann der Zahler jeden in Ihrem Konto aktivierten Coin wählen; der crypto-Modus benötigt zusätzlich currency.

ParameterTypBeschreibung
order_idstring · requiredIhre eindeutige Bestellreferenz (≤190 Zeichen). Eine Wiederholung wird mit 409 abgelehnt — sicher gegen Doppel-Übermittlungen.
amountstring · requiredFiat-Betrag (mode=fiat) oder exakter Krypto-Betrag (mode=crypto).
modefiat | cryptoStandard fiat: Der Kurs wird pro Coin beim Checkout festgeschrieben. crypto legt Coin und Betrag vorab fest.
fiat_currencystringISO-Fiat-Code für den fiat-Modus (default USD).
currencystringCoin für den crypto-Modus (z. B. TON, TRX, USDT_TRON).
return_urlhttps URLWohin die Schaltfläche „Zurück zum Shop“ im Checkout den Kunden zurückschickt — auf Ihre Website. Nur absolute http(s).
langen·ru·uk·es·deCheckout-Sprache, damit ein Kunde aus Ihrem russischen Shop den Checkout auf Russisch sieht — nicht auf Englisch. Auch als ?lang=ru in der Zahlungs-URL setzbar.
ttlsecondsWie lange die Rechnung bezahlbar bleibt (120–86400 Sekunden, Standard 1800).
customer_emailemailOptional — erscheint auf dem Beleg und wird dem Zahler per E-Mail gesendet.
notesstringFreitextnotiz, die in der Rechnung gespeichert wird.

return_url und lang funktionieren auch als Query-Parameter, die an die von der API zurückgegebene pay_url angehängt werden — <pay_url>&lang=ru&return_url=https://shop.example/thanks. Schicken Sie den Käufer immer an die von der API zurückgegebene pay_url: Sie trägt ein einmaliges Zugriffstoken pro Rechnung, sodass eine Checkout-Seite nicht durch Raten von Rechnungsnummern erreichbar ist. Bauen Sie den Link nicht aus der Rechnungs-ID neu zusammen.

Request-Builder

Signierte Rechnungsanfrage erstellen

Felder ausfüllen und den fertigen cURL-Befehl kopieren. Er signiert sich in Ihrer Shell mit $PAYORA_KEY und $PAYORA_SECRET – diese Seite sieht Ihre Schlüssel nie und sendet nichts.

mode
POST /v1/invoice
BODY='{"order_id":"ORDER-42","mode":"fiat","amount":"9.99","fiat_currency":"USD","return_url":"https://shop.example/thanks","lang":"de","ttl":1800}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$PAYORA_SECRET" | cut -d' ' -f2)

curl -X POST https://api.payora.money/v1/invoice \
  -H "X-Payora-Key: $PAYORA_KEY" \
  -H "X-Payora-Timestamp: $TS" \
  -H "X-Payora-Signature: $SIG" \
  -H 'Idempotency-Key: ORDER-42' \
  -H 'Content-Type: application/json' \
  -d "$BODY"

Von dieser Seite wird nichts gesendet.

Webhooks

Webhooks

Ändert eine Rechnung oder Auszahlung ihren Status, sendet Payora per POST ein signiertes JSON-Ereignis an Ihre Callback-URL. Zuerst Signatur prüfen, Bestellung einmal gutschreiben, mit 2xx antworten.

EreignisstatusWann es ausgelöst wird
invoice.paidpaidDie Zahlung ist on-chain bestätigt. Enthält Betrag, Coin und tx_hash.
invoice.underpaidunderpaidDie Rechnung ist abgelaufen, nachdem weniger als der erwartete Betrag eingegangen ist.
invoice.expiredexpiredDie Rechnung ist ohne Zahlungseingang abgelaufen.
invoice.cancelledcancelledDie Rechnung wurde storniert. Bereits eingegangenes Geld ist im Ereignis beschrieben.
invoice.cancel_settled—Geld, das auf eine stornierte Rechnung eingegangen ist, wurde erledigt: gutgeschrieben oder zurückgesendet.
invoice.late_payment—Auf eine Rechnung ist nach ihrer Stornierung Geld eingegangen. Wird für jeden solchen Eingang einmal gesendet; result sagt, ob es gutgeschrieben wurde oder zurückgeht.
payout.sentsentEin Auszahlungsbatch wurde signiert und gesendet. Enthält jede Position mit ihrem tx_hash.

Header jeder Zustellung

HeaderWertBeschreibung
X-Payora-IduuidEindeutige Ereignis-ID, identisch mit id im Body. Speichern Sie sie, um Wiederholungen zu ignorieren.
X-Payora-Eventinvoice.paidName des Ereignisses.
X-Payora-Timestampunix secondsWann dieser Versuch signiert wurde.
X-Payora-Signaturehex · 64Dasselbe Schema wie bei Anfragen: HMAC-SHA256 über timestamp + "." + Rohbody mit Ihrem api_secret.

Payload von invoice.paid

FeldTypBeschreibung
iduuidEreignis-ID zur Deduplizierung.
eventstringName des Ereignisses.
invoice_idintPayora-Rechnungsnummer.
order_idstringIhre Bestellreferenz, wie beim Erstellen der Rechnung gesendet.
statusstringpaid bei invoice.paid.
currencystringVom Zahler genutzte Coin, z. B. USDT_TRON.
amountdecimal stringErhaltener Betrag.
amount_unitsinteger stringDerselbe Betrag in den kleinsten Einheiten der Coin – für exakte Vergleiche.
expecteddecimal stringVon der Rechnung geforderter Betrag.
fiat_amountdecimal string | nullFiat-Preis der Rechnung, wie Sie sie erstellt haben; null bei Rechnungen im Krypto-Modus.
fiat_currencystring | nullISO-Code von fiat_amount; null bei Rechnungen im Krypto-Modus.
tx_hashstringOn-chain-Transaktionshash.
paid_atunix secondsWann das Ereignis erstellt wurde.
testbooltrue bei Sandbox-Rechnungen.
invoice.paid
{
    "id": "6f1c2a4e-8b0d-4c1e-9a57-2f3d9e1b7c40",
    "event": "invoice.paid",
    "invoice_id": 1042,
    "order_id": "ORDER-42",
    "status": "paid",
    "currency": "USDT_TRON",
    "amount": "9.99",
    "amount_units": "9990000",
    "expected": "9.99",
    "fiat_amount": "9.99",
    "fiat_currency": "USD",
    "tx_hash": "3f9a…c21e",
    "paid_at": 1758038400,
    "test": false
}

Weicht der erhaltene Betrag von der Rechnung ab, kommen amount_received und amount_expected hinzu.

Zustellung und Wiederholungen

Alles außer 2xx oder keine Antwort innerhalb von 15 Sekunden wird mit exponentiellem Backoff erneut versucht, höchstens eine Stunde zwischen den Versuchen, bis zu 12 Versuche. Jeder Versuch wird mit neuem Timestamp neu signiert; Body und Ereignis-ID bleiben gleich, deduplizieren Sie also nach id.

Nach dem letzten Versuch wird das Ereignis als fehlgeschlagen markiert und der Shop-Inhaber erhält eine E-Mail. Weiterleitungen werden nie verfolgt, und die Callback-URL muss aus dem Internet erreichbar sein – kein localhost, keine privaten Adressen.

Bevor Sie eine Bestellung gutschreiben

  • Lesen Sie den Rohbody vor jedem JSON-Parsing.
  • Signatur neu berechnen und in konstanter Zeit vergleichen: hash_equals, crypto.timingSafeEqual, hmac.compare_digest.
  • Timestamps außerhalb Ihres Fensters ablehnen – die SDKs akzeptieren ±300 Sekunden.
  • Status und Betrag mit der Bestellung abgleichen, dann einmal pro Ereignis-ID gutschreiben.
  • Schnell mit 2xx antworten, langsame Arbeit erst danach erledigen.
webhook
<?php
require 'Payora.php';
$payora = new Payora('https://api.payora.money', getenv('PAYORA_KEY'), getenv('PAYORA_SECRET'));

$raw   = file_get_contents('php://input');           // raw, before any parsing
$event = $payora->verifyWebhook($raw, getallheaders()); // HMAC + ±300 s window, constant-time
if ($event === null) { http_response_code(400); exit; } // bad / forged / stale

if ($event['event'] === 'invoice.paid' && !alreadyProcessed($event['id'])) {
  creditOrder($event['order_id'], $event['amount'], $event['currency'], $event['tx_hash']);
  rememberProcessed($event['id']);
}
http_response_code(200); // 2xx stops retries
Spielwiese

Spielwiese für Webhook-Signaturen

Geben Sie Secret, Timestamp und Rohbody ein, um genau die Signatur zu sehen, die Payora senden würde – oder prüfen Sie eine erhaltene.

Läuft in Ihrem Browser mit WebCrypto. Nichts, was Sie eingeben, verlässt diese Seite. Auf einem geteilten Computer ein Test-Secret verwenden, kein echtes.

X-Payora-Timestamp
Signierte Zeichenkette
1758038400.{…}
Header, die Payora sendet
headers
X-Payora-Timestamp: 1758038400
X-Payora-Signature: …

Signatur zum Vergleich einfügen

massenauszahlungen

API für Massenauszahlungen

Senden Sie Krypto an bis zu 500 Wallets in einer signierten, idempotenten Anfrage — für Gehälter, Affiliate-Auszahlungen oder Abhebungen. Die Stapelsumme plus Gebühr je Zeile wird sofort auf Ihrem internen Guthaben gehalten; anschließend signiert und sendet der Betreiber, dann feuert ein signierter payout.sent-Webhook. Dieselbe HMAC-Authentifizierung wie überall sonst.

payout
# create a payout batch — funds held instantly, sent by the operator
curl -X POST https://api.payora.money/v1/payout \
  -H 'X-Payora-Key: pk_…' -H 'X-Payora-Timestamp: 1700000000' \
  -H 'X-Payora-Signature: <hmac-sha256>' -H 'Idempotency-Key: payroll-2026-01' \
  -d '{"currency":"USDT_TRON","items":[
        {"address":"TR7…","amount":"250.00"},
        {"address":"TX9…","amount":"99.50","tag":"batch-A"}]}'

# → 201 Created
{ "batch_id": 812, "status": "pending", "currency": "USDT_TRON",
  "item_count": 2, "total": "349.50", "fee": "…", "items": [ … ] }

# poll status, or receive a signed payout.sent webhook when it is sent
curl https://api.payora.money/v1/payout/812 -H 'X-Payora-Key: …' …

Die Validierung ist streng: Jede fehlerhafte Adresse oder ein zu genauer Betrag lehnt den gesamten Batch ab (HTTP 422) samt der Indizes der betroffenen Positionen — bei einem Gehaltslauf fällt niemals still ein Empfänger weg. Brechen Sie einen noch ausstehenden Batch mit POST /v1/payout/{id}/cancel ab, um die Sperre freizugeben. Siehe den Architektur-Beitrag.

referenz

Referenz der Endpunkte

Jeder Endpunkt spricht einfaches JSON über HTTPS unter api.payora.money. Alle außer /v1/health nutzen dieselbe HMAC-SHA256-Request-Authentifizierung. Die maschinenlesbare Spezifikation liegt unter openapi.json.

EndpointZugriffBeschreibung
GET/v1/healthno authServicestatus plus die Liste der aktivierten Währungen.
POST/v1/invoiceauthErstellen Sie eine Rechnung (fiat- oder crypto-Modus). Unterstützt Idempotency-Key. Gibt 201 mit invoice_id, status, pay_url und expires zurück; im crypto-Modus kommen Adresse, Betrag und Deeplink hinzu.
GET/v1/invoice/{id}authRechnungsstatus (nur eigene Rechnungen): status, remaining und charge — currency, Adresse, erwartete/erhaltene Beträge und tx_hash.
POST/v1/payoutauth · Pro+Erstellen Sie einen Massenauszahlungs-Batch (strenge Validierung, Gelder werden sofort gehalten). Unterstützt Idempotency-Key. Gibt 201 mit der Batch-Ansicht zurück: batch_id, status, Summen, Gebühr, Positionen.
GET/v1/payoutauthListen Sie Ihre letzten Auszahlungs-Batches auf (?limit=, default 50).
GET/v1/payout/{id}authStatus und Positionen des Auszahlungs-Batches (nur eigene Batches).
POST/v1/payout/{id}/cancelauthBrechen Sie einen noch ausstehenden Batch ab und geben Sie das gehaltene Guthaben frei. Gibt 409 zurück, wenn der Batch nicht mehr stornierbar ist.
Downloads

SDKs & Downloads

Einzelne Dateien ohne Abhängigkeiten. Alle SDKs signieren Anfragen und prüfen Webhooks auf dieselbe Weise.

phpPHPPayora.php

PHP 7.4+ mit cURL, eine Datei. createInvoice, getInvoice und verifyWebhook.

jsNode.jspayora.js

Node.js nur mit eingebautem https und crypto. Rechnungen, Guthaben, Auszahlungen und verifyWebhook.

pyPythonpayora.py

Nur Python-Standardbibliothek. Rechnungen, Guthaben, Auszahlungen und verify_webhook.

{ }Postmanpayora.postman_collection.json

Eine Postman-Collection, die jeden Aufruf für Sie signiert.

{…}OpenAPI 3.0openapi.json

Die maschinenlesbare Spezifikation aller Endpoints, für Codegeneratoren und API-Clients.

api.payora.moneyÖffnen
Sie nutzen WooCommerce, WHMCS, Magento oder ein anderes CMS?

Ein fertiges Modul erledigt all das für Sie: Rechnung, Weiterleitung und verifizierter Webhook.

Plugins ansehen
FAQ

Häufig gestellte Fragen

Klare Antworten, auch auf unbequeme Fragen: Verwahrung, Gebühren und was passiert, wenn etwas schiefgeht.

Hilfebereich

Wie integriere ich Payora?

Installieren Sie das PHP-SDK aus einer Datei (ohne Abhängigkeiten) oder rufen Sie die REST-API direkt auf. Erstellen Sie eine Rechnung mit createInvoice(), leiten Sie die Kundschaft auf deren pay_url und behandeln Sie ein einziges Webhook-Ereignis: status=paid. Eine erfahrene Entwicklerin ist in 30–60 Minuten live.

Gibt es eine REST-API für andere Stacks als PHP?

Ja. Alles ist schlichtes JSON über HTTPS, Sie können also aus jeder Sprache integrieren. Das PHP-SDK ist nur eine bequeme Hülle um dieselben Endpunkte: Rechnung erstellen, Rechnung abrufen und Webhook-Signaturen prüfen.

Kommt die Kundschaft nach der Zahlung zurück auf meine Seite, und in der richtigen Sprache?

Ja. Übergeben Sie beim Erstellen der Rechnung return_url (oder ?return_url= am Zahlungslink), dann zeigt die Bezahlseite sowohl auf dem Erfolgsbildschirm als auch während der Zahlung eine Schaltfläche „Zurück zum Shop“. Übergeben Sie lang (en, ru, uk, es, de) oder ?lang= am Link, damit jemand aus Ihrem deutschen Shop auf der deutschen Bezahlseite landet statt auf der englischen. Beides ist optional; return_url muss eine absolute http(s)-Adresse sein.

Wie funktioniert die API-Authentifizierung?

Anfragen und Webhooks werden mit HMAC-SHA256 über Zeitstempel und rohen Nachrichtenkörper mit Ihrem api_secret authentifiziert, mit einem Zeitfenster von ±120 Sekunden und Idempotenzschlüsseln. Signaturen werden in konstanter Zeit verglichen, um Timing-Angriffe auszuschließen.

Wie bekomme ich API-Schlüssel?

Legen Sie ein kostenloses Konto an. Ihr öffentlicher api_key und Ihr geheimer api_secret erscheinen in der Übersicht, zusammen mit dem SDK zum Herunterladen und der vollständigen Webhook-Referenz. Schlüssel lassen sich jederzeit in den Einstellungen erneuern.

Was steht im Webhook?

Ein signiertes JSON-Ereignis mit der Rechnungs-ID, Ihrer order_id, dem Status (zum Beispiel paid), Betrag und Währung sowie einer eindeutigen Ereignis-ID für die Idempotenz. Prüfen Sie immer die Signatur, bevor Sie eine Bestellung gutschreiben, und merken Sie sich die Ereignis-ID, damit Wiederholungen nicht doppelt verarbeitet werden.

Gibt es eine API für Krypto-Massenauszahlungen?

Ja. POST /v1/payout sendet Krypto an bis zu 500 Wallets in einer Anfrage — ein {address, amount, optional tag} je Zeile, in jeder für Ihr Konto aktivierten Münze. Es gilt dieselbe HMAC-SHA256-Authentifizierung und derselbe Idempotency-Key wie bei der Rechnungs-API, ein Wiederholungsversuch erzeugt also nie einen doppelten Stapel. Die Stapelsumme plus Gebühr je Zeile wird sofort auf Ihrem Guthaben reserviert; signiert und gesendet wird vom Betreiber, danach feuert ein signierter payout.sent-Webhook. Die Prüfung ist streng: Eine ungültige Adresse oder ein zu genauer Betrag weist den ganzen Stapel zurück (422), damit ein Gehaltslauf nie stillschweigend einen Empfänger verliert.

Wie automatisiere ich Löhne oder Partnerauszahlungen in Krypto?

Bauen Sie die Empfängerliste in Ihrem eigenen System und rufen Sie POST /v1/payout einmal je Lauf mit einem stabilen Idempotency-Key auf (etwa payroll-2026-01). Fragen Sie GET /v1/payout/{id} ab oder warten Sie auf den payout.sent-Webhook, um die Zustellung zu bestätigen und jeden Hash festzuhalten. Das Einreichen reserviert die Mittel, bewegt sie aber nicht von selbst: Signiert und gesendet wird vom Betreiber, allein durch einen API-Aufruf geht also nichts raus.

Ihre API-Schlüssel holen

Ein einziges PHP-SDK ohne Abhängigkeiten: Rechnungen erstellen, zur gehosteten Bezahlseite weiterleiten und signierte Webhooks prüfen. Für jede andere Sprache gibt es REST.

Welche Suchanfragen diese Seite beantwortet