PHP-SDK
Eine Datei, keine Abhängigkeiten. createInvoice(), getInvoice() und verifyWebhook() — einfach in jedes Projekt legen.
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.payora.moneyEin API-Aufruf mit Bestell-ID und einem Betrag in Fiat oder Krypto liefert eine gehostete Zahlungs-URL.
Er wählt einen Coin, scannt den QR-Code oder öffnet seine Wallet — der Checkout bestätigt live bei Finalität.
HMAC-Signatur prüfen, Bestellung einmal gutschreiben — und die Zahlung landet auf Ihrem Guthaben.
Eine Datei, keine Abhängigkeiten. createInvoice(), getInvoice() und verifyWebhook() — einfach in jedes Projekt legen.
Anfragen und Webhooks sind mit HMAC-SHA256 signiert, mit Zeitfenster und Idempotenzschlüsseln.
Schlichtes JSON über HTTPS — Integration aus jedem Stack, nicht nur aus PHP.
<?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 retriesconst Payora = require('./payora');
const payora = new Payora('https://api.payora.money', process.env.PAYORA_KEY, process.env.PAYORA_SECRET);
// 1 — create an invoice and redirect
app.post('/checkout', async (req, res) => {
const inv = await payora.createInvoice({ order_id: 'ORDER-42', mode: 'fiat', amount: '9.99' }, 'ORDER-42');
res.redirect(inv.pay_url);
});
// 2 — webhook: verify over the RAW body
app.post('/payora/webhook', express.raw({ type: '*/*' }), (req, res) => {
const event = payora.verifyWebhook(req.body, req.headers);
if (event === null) return res.status(400).end();
if (event.status === 'paid') creditOrderOnce(event.id, event.order_id);
res.status(200).end();
});import os
from payora import Payora
payora = Payora('https://api.payora.money', os.environ['PAYORA_KEY'], os.environ['PAYORA_SECRET'])
# 1 — create an invoice and redirect
inv = payora.create_invoice({'order_id': 'ORDER-42', 'mode': 'fiat', 'amount': '9.99'}, 'ORDER-42')
return redirect(inv['pay_url'])
# 2 — webhook: verify over the RAW body
event = payora.verify_webhook(request.get_data(), dict(request.headers))
if event is None:
return ('', 400)
if event['status'] == 'paid':
credit_order_once(event['id'], event['order_id'])
return ('', 200)# signature = lowercase hex HMAC-SHA256(api_secret, timestamp + "." + raw_body)
BODY='{"order_id":"ORDER-42","mode":"fiat","amount":"9.99"}'
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"
# → 201 { "invoice_id": …, "status": "pending", "pay_url": "https://pay.payora.money/i/…", "expires": … }Erhalten Sie Ihren API key und Secret, indem Sie ein Konto erstellen. Das vollständige SDK finden Sie in Ihrem Dashboard.
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.
| Header | Wert | Beschreibung |
|---|---|---|
X-Payora-Key | pk_… | Ihr öffentlicher api_key. Identifiziert den Shop. |
X-Payora-Timestamp | unix seconds | Der Zeitpunkt der Signatur, in Unix-Sekunden. |
X-Payora-Signature | hex · 64 | HMAC-SHA256 über timestamp + "." + Rohbody mit Ihrem api_secret als Schlüssel, als Hex in Kleinbuchstaben. |
X-Payora-Test | 1 | Markiert eine Rechnung als Test Ihrer Integration: sie ist echt und kann Münzen empfangen, zählt aber nicht in Nachfrage- und Conversion-Berichten. |
Idempotency-Key | string | Optional 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-Type | application/json | Pflicht bei Anfragen mit Body. |
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.
<?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);const crypto = require('crypto');
const body = JSON.stringify({ order_id: 'ORDER-42', mode: 'fiat', amount: '9.99' });
const ts = String(Math.floor(Date.now() / 1000));
const sig = crypto.createHmac('sha256', API_SECRET).update(ts + '.' + body).digest('hex');
const res = await fetch('https://api.payora.money/v1/invoice', {
method: 'POST',
headers: {
'X-Payora-Key': API_KEY,
'X-Payora-Timestamp': ts,
'X-Payora-Signature': sig,
'Idempotency-Key': 'ORDER-42',
'Content-Type': 'application/json',
},
body, // send exactly the bytes you signed
});import hashlib, hmac, json, time, urllib.request
body = json.dumps({'order_id': 'ORDER-42', 'mode': 'fiat', 'amount': '9.99'}, separators=(',', ':'))
ts = str(int(time.time()))
sig = hmac.new(API_SECRET.encode(), (ts + '.' + body).encode(), hashlib.sha256).hexdigest()
req = urllib.request.Request('https://api.payora.money/v1/invoice', data=body.encode(), method='POST', headers={
'X-Payora-Key': API_KEY,
'X-Payora-Timestamp': ts,
'X-Payora-Signature': sig,
'Idempotency-Key': 'ORDER-42',
'Content-Type': 'application/json',
})
invoice = json.load(urllib.request.urlopen(req))# GET has an empty body: the signed string is just the timestamp and a dot
TS=$(date +%s)
SIG=$(printf '%s.' "$TS" | openssl dgst -sha256 -hmac "$PAYORA_SECRET" | cut -d' ' -f2)
curl https://api.payora.money/v1/invoice/1042 \
-H "X-Payora-Key: $PAYORA_KEY" \
-H "X-Payora-Timestamp: $TS" \
-H "X-Payora-Signature: $SIG"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.
| Parameter | Typ | Beschreibung |
|---|---|---|
order_id | string · required | Ihre eindeutige Bestellreferenz (≤190 Zeichen). Eine Wiederholung wird mit 409 abgelehnt — sicher gegen Doppel-Übermittlungen. |
amount | string · required | Fiat-Betrag (mode=fiat) oder exakter Krypto-Betrag (mode=crypto). |
mode | fiat | crypto | Standard fiat: Der Kurs wird pro Coin beim Checkout festgeschrieben. crypto legt Coin und Betrag vorab fest. |
fiat_currency | string | ISO-Fiat-Code für den fiat-Modus (default USD). |
currency | string | Coin für den crypto-Modus (z. B. TON, TRX, USDT_TRON). |
return_url | https URL | Wohin die Schaltfläche „Zurück zum Shop“ im Checkout den Kunden zurückschickt — auf Ihre Website. Nur absolute http(s). |
lang | en·ru·uk·es·de | Checkout-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. |
ttl | seconds | Wie lange die Rechnung bezahlbar bleibt (120–86400 Sekunden, Standard 1800). |
customer_email | Optional — erscheint auf dem Beleg und wird dem Zahler per E-Mail gesendet. | |
notes | string | Freitextnotiz, 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.
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.
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.
Ä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.
| Ereignis | status | Wann es ausgelöst wird |
|---|---|---|
invoice.paid | paid | Die Zahlung ist on-chain bestätigt. Enthält Betrag, Coin und tx_hash. |
invoice.underpaid | underpaid | Die Rechnung ist abgelaufen, nachdem weniger als der erwartete Betrag eingegangen ist. |
invoice.expired | expired | Die Rechnung ist ohne Zahlungseingang abgelaufen. |
invoice.cancelled | cancelled | Die 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.sent | sent | Ein Auszahlungsbatch wurde signiert und gesendet. Enthält jede Position mit ihrem tx_hash. |
| Header | Wert | Beschreibung |
|---|---|---|
X-Payora-Id | uuid | Eindeutige Ereignis-ID, identisch mit id im Body. Speichern Sie sie, um Wiederholungen zu ignorieren. |
X-Payora-Event | invoice.paid | Name des Ereignisses. |
X-Payora-Timestamp | unix seconds | Wann dieser Versuch signiert wurde. |
X-Payora-Signature | hex · 64 | Dasselbe Schema wie bei Anfragen: HMAC-SHA256 über timestamp + "." + Rohbody mit Ihrem api_secret. |
| Feld | Typ | Beschreibung |
|---|---|---|
id | uuid | Ereignis-ID zur Deduplizierung. |
event | string | Name des Ereignisses. |
invoice_id | int | Payora-Rechnungsnummer. |
order_id | string | Ihre Bestellreferenz, wie beim Erstellen der Rechnung gesendet. |
status | string | paid bei invoice.paid. |
currency | string | Vom Zahler genutzte Coin, z. B. USDT_TRON. |
amount | decimal string | Erhaltener Betrag. |
amount_units | integer string | Derselbe Betrag in den kleinsten Einheiten der Coin – für exakte Vergleiche. |
expected | decimal string | Von der Rechnung geforderter Betrag. |
fiat_amount | decimal string | null | Fiat-Preis der Rechnung, wie Sie sie erstellt haben; null bei Rechnungen im Krypto-Modus. |
fiat_currency | string | null | ISO-Code von fiat_amount; null bei Rechnungen im Krypto-Modus. |
tx_hash | string | On-chain-Transaktionshash. |
paid_at | unix seconds | Wann das Ereignis erstellt wurde. |
test | bool | true bei Sandbox-Rechnungen. |
{
"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.
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.
hash_equals, crypto.timingSafeEqual, hmac.compare_digest.<?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// Express: capture the RAW body for this route
app.post('/payora/webhook', express.raw({ type: '*/*' }), (req, res) => {
const event = payora.verifyWebhook(req.body, req.headers); // HMAC + ±300 s, timingSafeEqual
if (event === null) return res.status(400).end();
if (event.event === 'invoice.paid' && !alreadyProcessed(event.id)) {
creditOrder(event.order_id, event.amount, event.currency, event.tx_hash);
rememberProcessed(event.id);
}
res.status(200).end(); // 2xx stops retries
});# Flask: request.get_data() is the exact raw body
@app.post('/payora/webhook')
def payora_webhook():
event = payora.verify_webhook(request.get_data(), dict(request.headers))
if event is None:
return ('', 400) # bad / forged / stale
if event['event'] == 'invoice.paid' and not already_processed(event['id']):
credit_order(event['order_id'], event['amount'], event['currency'], event['tx_hash'])
remember_processed(event['id'])
return ('', 200) # 2xx stops retries# Recompute the signature of a delivery you saved byte-for-byte to body.json
TS='1758038400' # X-Payora-Timestamp
SIG='…' # X-Payora-Signature
EXPECTED=$(printf '%s.' "$TS" | cat - body.json | openssl dgst -sha256 -hmac "$PAYORA_SECRET" | cut -d' ' -f2)
[ "$EXPECTED" = "$SIG" ] && echo valid || echo forgedGeben 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.
1758038400.{…}X-Payora-Timestamp: 1758038400
X-Payora-Signature: …Signatur zum Vergleich einfügen
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.
# 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: …' …<?php
// The one-file PHP SDK covers invoices and webhooks; payouts are one signed POST.
$body = json_encode(['currency' => 'USDT_TRON', 'items' => [
['address' => 'TR7…', 'amount' => '250.00'],
['address' => 'TX9…', 'amount' => '99.50', 'tag' => 'batch-A'],
]], JSON_UNESCAPED_SLASHES);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $body, $apiSecret);
$ch = curl_init('https://api.payora.money/v1/payout');
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: payroll-2026-01', 'Content-Type: application/json']]);
$batch = json_decode(curl_exec($ch), true); // 201: batch_id, status, totals, fee, itemsconst batch = await payora.createPayout({
currency: 'USDT_TRON',
items: [
{ address: 'TR7…', amount: '250.00' },
{ address: 'TX9…', amount: '99.50', tag: 'batch-A' },
],
}, 'payroll-2026-01'); // Idempotency-Key: a retried run never doubles
const status = await payora.getPayout(batch.batch_id);
// still pending? await payora.cancelPayout(batch.batch_id) releases the holdbatch = payora.create_payout({
'currency': 'USDT_TRON',
'items': [
{'address': 'TR7…', 'amount': '250.00'},
{'address': 'TX9…', 'amount': '99.50', 'tag': 'batch-A'},
],
}, 'payroll-2026-01') # Idempotency-Key: a retried run never doubles
status = payora.get_payout(batch['batch_id'])
# still pending? payora.cancel_payout(batch['batch_id']) releases the holdDie 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.
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.
| Endpoint | Zugriff | Beschreibung |
|---|---|---|
GET/v1/health | no auth | Servicestatus plus die Liste der aktivierten Währungen. |
POST/v1/invoice | auth | Erstellen 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} | auth | Rechnungsstatus (nur eigene Rechnungen): status, remaining und charge — currency, Adresse, erwartete/erhaltene Beträge und tx_hash. |
POST/v1/payout | auth · 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/payout | auth | Listen Sie Ihre letzten Auszahlungs-Batches auf (?limit=, default 50). |
GET/v1/payout/{id} | auth | Status und Positionen des Auszahlungs-Batches (nur eigene Batches). |
POST/v1/payout/{id}/cancel | auth | Brechen Sie einen noch ausstehenden Batch ab und geben Sie das gehaltene Guthaben frei. Gibt 409 zurück, wenn der Batch nicht mehr stornierbar ist. |
Kein Endpoint passt.
Einzelne Dateien ohne Abhängigkeiten. Alle SDKs signieren Anfragen und prüfen Webhooks auf dieselbe Weise.
PHP 7.4+ mit cURL, eine Datei. createInvoice, getInvoice und verifyWebhook.
Node.js nur mit eingebautem https und crypto. Rechnungen, Guthaben, Auszahlungen und verifyWebhook.
Nur Python-Standardbibliothek. Rechnungen, Guthaben, Auszahlungen und verify_webhook.
Eine Postman-Collection, die jeden Aufruf für Sie signiert.
Die maschinenlesbare Spezifikation aller Endpoints, für Codegeneratoren und API-Clients.
Ein fertiges Modul erledigt all das für Sie: Rechnung, Weiterleitung und verifizierter Webhook.
Klare Antworten, auch auf unbequeme Fragen: Verwahrung, Gebühren und was passiert, wenn etwas schiefgeht.
HilfebereichInstallieren 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.
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.
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.
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.
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.
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.
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.
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.
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.