Überblick
Mit InstantPay nimmt deine Website Krypto-Zahlungen an, ohne dass du selbst eine Wallet betreiben musst. Dein Kunde zahlt in SOL, USDC, USDT, ETH, BNB oder BTC auf einer von uns gehosteten Checkout-Seite; du bekommst einen signierten Webhook und eine Gutschrift in EUR oder USD auf deinem InstantPay-Guthaben. Jede bestätigte Zahlung kostet pauschal 1,66 % des Rechnungsbetrags. Ausgezahlt wird an deine eigene Wallet, wann immer du willst, in SOL, einem Stablecoin, ETH, BNB, POL, TRX, BTC oder LTC.
So läuft eine Zahlung ab:
- Dein Server legt eine Rechnung an mit einem Preis in EUR oder USD und bekommt eine Checkout-URL zurück.
- Der Kunde zahlt auf der Checkout-Seite (oder in einem Overlay auf deiner Seite): Coin wählen, Adresse und exakten Betrag sehen, senden. Der Kurs wird in diesem Moment eingefroren.
- InstantPay beobachtet die Chain. Sobald die Zahlung endgültig ist, bekommt deine Webhook-URL
invoice.confirmed. - Du lieferst. Der Rechnungsbetrag minus Gebühr liegt auf deinem Guthaben; eine Auszahlung in dem Coin deiner Wahl forderst du an, wann du willst.
Was du brauchst: ein InstantNode-Konto, einen Server, der HTTPS-Aufrufe machen kann (Node, PHP oder etwas anderes), und eine öffentliche https://-URL, die Webhooks entgegennimmt. Mit Coins, Adressen oder Wechselkursen hast du nie selbst zu tun.
Probier den kompletten Ablauf zuerst aus: unser Demo-Shop unter http://5.230.154.241 ist ein ganz normaler Shop, der InstantPay im Testmodus nutzt. Kauf etwas, zahl mit dem Knopf „Simulate payment“ und sieh zu, wie die Bestellung auf bezahlt springt.
Erste Schritte
Sechs Schritte von null bis zur Live-Integration. Für die Schritte 1 bis 5 brauchst du keine Freischaltung; du kannst bauen und testen, während wir dein Konto prüfen.
- Anmelden. Öffne pay.instantnode.eu/dashboard und melde dich mit deinem InstantNode-Konto an. Dabei entsteht ein Merchant-Konto im Status pending.
- Konto vervollständigen. Trag unter Account Firma, Website und eine kurze Beschreibung dessen ein, was du verkaufst, akzeptiere die Bedingungen und schick es ab. InstantNode prüft das und schaltet dich frei, in der Regel innerhalb eines Tages.
- Test-Key kopieren. Unter API-Keys hast du schon ein Live- und ein Test-Paar: einen Secret Key (
sk_test_…, für deinen Server) und einen Public Key (pk_test_…, für den Browser). Zeig den Test-Secret-Key an und leg ihn in die Konfiguration deines Servers, nie in Browser-Code. - Webhook-Endpunkt anlegen. Trag unter Webhooks die
https://-Adresse auf deinem Server ein, die Ereignisse empfangen soll, und drück auf der Endpunkt-Seite Send test event, um zu prüfen, dass deine Signaturprüfung funktioniert. - Testkauf machen. Leg mit dem Test-Key eine Rechnung an (siehe unten), öffne die Checkout-URL, drück Simulate payment. Ein paar Sekunden später bekommt dein Webhook
invoice.confirmedmitlivemode: false. - Live gehen. Sobald dein Konto active ist, schaltest du das Dashboard in den Live-Modus, zeigst den Live-Secret-Key an (wird einmal angezeigt) und tauschst ihn gegen den Test-Key; leg einen Live-Webhook-Endpunkt an. Rechnungen aus einem Live-Key werden mit echten Coins bezahlt und deinem Guthaben gutgeschrieben.
Wege der Integration
Alle Wege nutzen dieselbe API; der einzige Unterschied ist, wo der Kunde bezahlt. Eine Regel gilt für alle: Die Rechnung wird immer auf deinem Server erzeugt, nie im Browser, sonst ist dein API-Key öffentlich.
Hosted Checkout
Der einfachste Weg. Dein Server legt die Rechnung an und leitet den Kunden auf checkoutUrl weiter. Nach der Zahlung kommt der Kunde auf deine redirectUrl zurück. Funktioniert in jedem Shop, braucht kein JavaScript.
// Node (Express) - das SDK ist eine einzige Datei: /sdk/node/instapay.mjs
import { InstantPay } from './instapay.mjs';
const pay = new InstantPay({ baseUrl: 'https://pay.instantnode.eu', apiKey: process.env.INSTAPAY_KEY });
app.post('/checkout', async (req, res) => {
const invoice = await pay.createInvoice({
amount: '19.99',
currency: 'EUR',
orderId: order.id,
description: 'T-Shirt, blau, M',
redirectUrl: 'https://shop.example/danke?order=' + order.id,
cancelUrl: 'https://shop.example/warenkorb',
}, order.id); // Idempotency-Key: ein Retry liefert dieselbe Rechnung
res.redirect(invoice.checkoutUrl);
});// PHP - /sdk/php/InstaPay.php
require 'InstaPay.php';
$pay = new InstantPay('https://pay.instantnode.eu', getenv('INSTAPAY_KEY'));
$invoice = $pay->createInvoice([
'amount' => '19.99', 'currency' => 'EUR', 'orderId' => (string) $orderId,
'redirectUrl' => 'https://shop.example/danke?order=' . $orderId,
], (string) $orderId);
header('Location: ' . $invoice['checkoutUrl']);Payment-Links
Ganz ohne Code. Lege unter Zahlungslinks einen Link mit festem Betrag oder offenem Betrag an (der Kunde gibt ihn ein, innerhalb deiner Grenzen), wiederverwendbar oder einmalig, mit optionalem Ablaufdatum und Erfolgs-URL. Der Link ist eine Seite unter https://pay.instantnode.eu/l/<slug>, die für jeden, der sie öffnet, eine Rechnung erstellt; du bekommst die URL, einen QR-Code und ein Einbett-Snippet. Jede Rechnung aus einem Link trägt paymentLinkId und die Bestellnummer link:<slug>:<n>, Webhook und Gutschrift funktionieren also genauso. Die Link-Seite zählt Aufrufe und Umsatz und listet ihre Zahlungen.
Overlay-Widget
Der Kunde bleibt auf deiner Seite; der Checkout öffnet sich in einem Overlay. Lade instapay.js und öffne es mit dem Token - das ist der letzte Teil der checkoutUrl und kommt von deinem Server. Wenn du den Token nicht durch deine Seite reichen willst, holt ihn der Browser mit deinem Public Key: POST /v1/public/checkout-sessions mit { "invoiceId" } antwortet { token, checkoutUrl } für eine Rechnung, die dein Server angelegt hat; mehr kann ein Public Key nicht.
<script src="https://pay.instantnode.eu/instapay.js"></script>
<script>
InstantPay.open({
token: token, // letzter Teil der checkoutUrl
lang: 'de', // oder 'en'
onStatus: (s) => console.log(s.status),
onPaid: (s) => location.href = '/danke',
onExpired: (s) => alert('Das Zahlungsfenster ist abgelaufen'),
onClose: () => console.log('geschlossen'),
closeOnPaid: true,
});
</script>Das Widget fragt den Status alle vier Sekunden ab und ruft onPaid auf, sobald die Zahlung bestätigt ist. Betrachte das trotzdem nur als Service für den Kunden: ob eine Bestellung bezahlt ist, entscheidet allein der Webhook.
Eigene Zahlungsseite
Rechnung anlegen, POST /v1/invoices/:id/select mit dem vom Kunden gewählten Coin aufrufen und depositAddress sowie amountExpected selbst anzeigen. Den Status über GET /v1/invoices/:id abfragen oder auf den Webhook warten.
Rechnung anlegen
POST /v1/invoices mit deinem Key im Header X-API-Key. Beträge werden als Strings übertragen; rechne mit Geld nie in Fließkommazahlen.
curl -X POST https://pay.instantnode.eu/v1/invoices \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1001" \
-d '{
"amount": "19.99",
"currency": "EUR",
"orderId": "ORD-1001",
"description": "T-Shirt, blau, M",
"redirectUrl": "https://shop.example/danke?order=1001",
"cancelUrl": "https://shop.example/warenkorb",
"metadata": {"sku": "shirt-blue-m"},
"ttlSeconds": 1200
}'| Feld | Pflicht | Bedeutung |
|---|---|---|
amount | ja | Preis als String mit höchstens zwei Nachkommastellen, z. B. "19.99" |
currency | ja | EUR oder USD |
orderId | nein | Deine Bestellnummer. Eindeutig pro Konto; dieselbe orderId liefert dieselbe Rechnung |
description | nein | Wird dem Kunden im Checkout angezeigt |
redirectUrl / cancelUrl | nein | Wohin der Kunde nach der Zahlung bzw. nach dem Abbruch geht |
webhookUrl | nein | Überschreibt für diese Rechnung die Standard-Webhook-URL aus deinen Einstellungen |
metadata | nein | Beliebiges JSON-Objekt bis 4 KB; kommt in jedem Webhook zurück |
asset | nein | Coin vorwählen (z. B. USDC_SOL), dann entfällt die Auswahl im Checkout |
ttlSeconds | nein | Wie lange die Rechnung bezahlbar bleibt: Standard 1200 (20 Minuten), 60 bis 86400 |
customerEmail | nein | Der Kunde bekommt eine Beleg-Mail, sobald die Zahlung bestätigt ist; dir wird sie bei der Zahlung angezeigt |
Die Antwort ist die Rechnung (201):
{
"id": "f987fead-cbc0-47e1-b9c1-02423c18ec97",
"orderId": "ORD-1001",
"status": "created",
"paid": false,
"amount": "19.99",
"currency": "EUR",
"checkoutUrl": "https://pay.instantnode.eu/pay/Tx7CVPbpJk7IcTkdKMCKCCKt",
"expiresAt": "2026-09-19T21:20:13.527Z",
"asset": null, "amountExpected": null, "amountReceived": null, "depositAddress": null
}Limits: 60 Aufrufe pro Minute und Key (429), höchstens 1000 offene Rechnungen gleichzeitig (429 too_many_open_invoices). Derselbe Idempotency-Key mit anderem Inhalt antwortet 409. Felder, die du weglässt, kommen aus deinen _Checkout_-Einstellungen: Zeit zum Bezahlen (ttlSeconds), Toleranz, Erfolgs- und Abbruch-URL und die im Checkout angebotenen Coins.
Webhooks
Der Webhook ist der Teil, auf den es ankommt. Die Weiterleitung nach der Zahlung ist nur kosmetisch: Der Kunde kann den Browser schließen und die Coins trotzdem senden, also liefere Ware erst, wenn das Ereignis mit paid: true angekommen ist.
Unter Webhooks legst du bis zu zehn Endpunkte pro Modus an (Live und Test sind getrennte Listen). Jeder Endpunkt hat sein eigenes Signatur-Secret (whsec_…), eine Liste der Event-Typen, die er abonniert (* für alle), und eine Statuszeile. InstantPay sendet an jeden abonnierten Endpunkt einen POST mit JSON-Body. Die URL muss https:// mit öffentlichem Hostnamen sein; Weiterleitungen werden nicht verfolgt, und dein Server hat 10 Sekunden zum Antworten.
X-InstantPay-Signature: t=1758315600,v1=<hex hmac-sha256>
X-InstantPay-Event: invoice.confirmed
X-InstantPay-Livemode: true
X-InstantPay-Delivery: 42
Idempotency-Key: evt_01K5N3Y7Z2Q8XW6M3R9V4T1B5CDieselben Header kommen zusätzlich in der bisherigen Schreibweise X-InstaPay-, damit ein bestehender Empfänger weiterläuft.
Signatur prüfen
Die Signatur ist ein HMAC-SHA256 über "<t>.<roher Body>" mit dem Secret des Endpunkts (auf der Endpunkt-Seite nach einer frischen Anmeldung einsehbar). Prüfe die rohen Bytes, die du empfangen hast, nicht ein neu serialisiertes Objekt, und weise Zeitstempel ab, die älter als fünf Minuten sind.
// Node (Express) - verifyWebhook kommt aus dem SDK
import { verifyWebhook } from './instapay.mjs';
app.post('/webhooks/instantpay', express.raw({ type: '*/*' }), (req, res) => {
const raw = req.body.toString('utf8');
if (!verifyWebhook(process.env.INSTANTPAY_WEBHOOK_SECRET, req.get('x-instantpay-signature'), raw)) {
return res.status(400).send('bad signature');
}
const event = JSON.parse(raw);
if (event.livemode === false) return res.json({ ok: true }); // ein Test-Event: nie liefern
const invoice = event.data.object;
if (event.type === 'invoice.confirmed' && invoice.paid) markOrderPaid(invoice.orderId);
res.json({ ok: true }); // schnell antworten, danach arbeiten
});// PHP
$raw = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_INSTANTPAY_SIGNATURE'] ?? '';
$event = InstantPay::parseWebhook(getenv('INSTANTPAY_WEBHOOK_SECRET'), $signature, $raw);
if ($event === null) { http_response_code(400); exit('bad signature'); }
if (($event['livemode'] ?? true) === false) { echo 'ok'; exit; }
$invoice = $event['data']['object'];
if ($event['type'] === 'invoice.confirmed' && $invoice['paid']) markOrderPaid($invoice['orderId']);
echo 'ok';Der Ereignis-Body
data.object ist das Objekt genau so, wie GET /v1/invoices/:id (oder /v1/payouts/:id) es zurückgibt; Webhook und Abruf widersprechen sich nie.
{
"id": "evt_01K5N3Y7Z2Q8XW6M3R9V4T1B5C",
"object": "event",
"type": "invoice.confirmed",
"livemode": true,
"created": "2026-09-19T21:05:00.000Z",
"data": {
"object": {
"object": "invoice",
"id": "f987fead-cbc0-47e1-b9c1-02423c18ec97",
"orderId": "ORD-1001",
"status": "confirmed",
"paid": true,
"livemode": true,
"amount": "19.99",
"currency": "EUR",
"asset": "SOL",
"amountExpected": "0.206789123",
"amountReceived": "0.206789123",
"metadata": {"sku": "shirt-blue-m"},
"createdAt": "2026-09-19T21:00:13.527Z",
"expiresAt": "2026-09-19T21:20:13.527Z",
"confirmedAt": "2026-09-19T21:05:00.000Z"
}
}
}| Ereignis | Wann |
|---|---|
invoice.created | Die Rechnung existiert |
invoice.detected | Eine Transaktion wurde gesehen, ist aber noch nicht final |
invoice.confirmed | Bezahlt. paid ist true |
invoice.overpaid | Bezahlt, mehr als nötig; alles Eingegangene wird gutgeschrieben. paid ist true |
invoice.underpaid | Zu wenig angekommen; du kannst die Teilzahlung im Dashboard akzeptieren |
invoice.expired | Vor Ablauf ist nichts angekommen |
invoice.paid_late | Nach Ablauf der Frist bezahlt; siehe Gebühren, Guthaben und Auszahlungen |
invoice.cancelled / invoice.failed | Storniert, oder etwas ist schiefgegangen |
deposit.confirmed | Geld ist auf der statischen Adresse eines Kunden gelandet (Funktion Kunden) |
payout.paid / payout.failed | Eine Auszahlung an deine Wallet ist abgeschlossen; data.object ist die Auszahlung |
refund.paid / refund.failed | Eine Erstattung an einen Kunden ist abgeschlossen; data.object ist die Erstattung |
account.approved / account.suspended | Dein Konto hat den Status gewechselt |
Ein Endpunkt kann auch auf den Legacy-Body gestellt werden (event, livemode und invoice / deposit / payout auf oberster Ebene, priceAmount statt amount); das bekommen Integrationen aus der Zeit vor den Endpunkten. invoice.overpaid kommt dort als invoice.confirmed mit overpaid: true an. Neue Integrationen sollten den Standard nutzen.
Regeln für einen robusten Empfänger
- Antworte innerhalb von 10 Sekunden mit
2xxund erledige die eigentliche Arbeit danach. Alles andere wird mit wachsenden Abständen wiederholt (5 s, 20 s, 1 min, 3 min, 10 min, 30 min, 1 h, 2 h, 4 h, 8 h), insgesamt zehn Versuche, dann gilt die Zustellung als dead. Ein Endpunkt, der 20 Zustellungen in Folge über mindestens drei Tage nicht annimmt, wird abgeschaltet, und du bekommst eine E-Mail; aktiviere ihn auf seiner Seite wieder, sobald er repariert ist. - Sei idempotent. Es gibt genau ein Event pro Ereignis, aber eine Zustellung kann sich wiederholen (Wiederholungen, der Button Erneut senden). Nutze den Header
Idempotency-Keyoderevent.id, um Bereits-Verarbeitetes zu überspringen. - Prüfe
livemode. Ereignisse aus Testrechnungen und vom Button Send test event tragenlivemode: false. Sie sind zum Prüfen deines Codes da, nie zum Versenden von Ware. - Im Zweifel nachfragen.
GET /v1/eventslistet jedes Ereignis deines Kontos, neueste zuerst, undGET /v1/invoices/:idantwortet mitpaid. Der Tab Events im Dashboard zeigt dieselbe Liste mit jeder Zustellung und einem Button Erneut an Endpunkt senden.
Testmodus
Ein Test-Key verhält sich genau wie ein echter, nur dass seine Rechnungen nie mit Coins bezahlt werden. Im Checkout sieht der Kunde (also du) ein Banner „Test mode“ mit dem Knopf Simulate payment; dein Server kann dasselbe über die API tun. Testrechnungen werden einem getrennten Testguthaben gutgeschrieben, das du nur siehst, wenn der Live/Test-Schalter im Dashboard auf Test steht; es ist nie auszahlbar und nie echtes Geld. Ihre Webhooks tragen livemode: false.
# eine Testrechnung vom eigenen Server aus bezahlen - "case" kann exact, under oder over sein
curl -X POST https://pay.instantnode.eu/v1/invoices/<id>/simulate \
-H "X-API-Key: sk_test_..." -H "Content-Type: application/json" \
-d '{"case": "exact"}'Checkliste, bevor du live gehst:
- Dein Webhook lehnt eine falsche Signatur ab (
400) und akzeptiert das Testereignis aus dem Dashboard. - Eine Bestellung wird erst nach
invoice.confirmedmitpaid: trueundlivemode: trueals bezahlt markiert. - Eine wiederholte Zustellung erzeugt keinen zweiten Versand.
- Bei
invoice.underpaidundinvoice.expiredsieht der Kunde etwas Sinnvolles. - Der Test-Key ist in deiner Konfiguration durch einen Live-Key ersetzt und der Test-Key ist widerrufen.
Status einer Rechnung
paid ist das Feld, auf das du schauen solltest: Es ist true bei confirmed und overpaid und false bei allem anderen.
| Status | Bedeutung | paid |
|---|---|---|
created | Angelegt, Coin noch nicht gewählt | nein |
awaiting_payment | Adresse angezeigt, wartet auf die Überweisung | nein |
detected | Transaktion gesehen, noch nicht endgültig | nein |
confirmed | Bezahlt und endgültig | ja |
overpaid | Bezahlt, mehr als nötig | ja |
underpaid | Zu wenig angekommen; du kannst den Eingang akzeptieren (Dashboard, bis 7 Tage nach Ablauf) | nein |
expired | Frist abgelaufen, nichts angekommen | nein |
paid_late | Nach Ablauf der Frist bezahlt | nein |
cancelled / failed | Abgebrochen bzw. ein Fehler ist aufgetreten | nein |
Ein Kunde, der minimal zu wenig schickt (bis 0,5 %), gilt trotzdem als bezahlt. Darunter wird die Rechnung underpaid.
Gebühren, Guthaben und Auszahlungen
- Gebühr. Jede bestätigte Zahlung wird deinem Guthaben in der Rechnungswährung gutgeschrieben, abzüglich der Plattformgebühr, standardmäßig 1,66 %. Rechnung 100.00 € → Gutschrift 98.34 €. Die Gebühr wird beim Anlegen der Rechnung eingefroren, eine spätere Änderung betrifft nur neue Rechnungen.
- Überzahlt. Gutgeschrieben wird alles, was angekommen ist, zum für die Rechnung fixierten Kurs, abzüglich Gebühr. Das Geld des Kunden gehört dir.
- Zu spät bezahlt. Bis 60 Minuten nach Ablauf wird die Zahlung automatisch zum fixierten Kurs gutgeschrieben. Spätere warten auf dich: Späte Zahlung akzeptieren auf der Rechnung schreibt den Eingang zum aktuellen Kurs gut; die Kursbewegung seit der Rechnung trägst du.
- Zu wenig bezahlt. Von selbst wird nichts gutgeschrieben. Teilzahlung akzeptieren auf der Rechnung schreibt den Eingang zum fixierten Kurs abzüglich Gebühr gut; möglich bis 7 Tage nach Ablauf der Rechnung, danach über den Support.
- Guthaben. Balance im Dashboard zeigt drei Zahlen je Währung: verfügbar (was du auszahlen kannst), ausstehend (auf der Chain erkannte, noch nicht bestätigte Zahlungen) und reserviert (offene Auszahlungen und Erstattungen, bereits abgezogen). Darunter jede Buchung:
sale,fee,payout,payout_reversal,refund,refund_reversalundadjustment, mit laufendem Saldo und CSV-Export für deine Buchhaltung. - Erstattungen. Aus einer bezahlten Rechnung heraus schickt Erstattung einen Teil des gutgeschriebenen Betrags an eine vom Kunden genannte Adresse zurück, im Coin, mit dem er bezahlt hat, oder in deinem Auszahlungs-Coin. Der Fiat-Betrag verlässt dein Guthaben sofort; die Netzwerkgebühr geht davon ab, die genauen Zahlen siehst du vor der Bestätigung. Erstattungen bis 200 € von Konten, die seit 30 Tagen oder länger freigegeben sind, gehen von selbst raus, größere prüft InstantNode.
refund.paid/refund.failedkommen als Webhooks;GET /v1/refundslistet sie. Testrechnungen können nicht erstattet werden. - Auszahlungen. Wähle unter Payouts den Coin, in dem du ausgezahlt werden willst (SOL als Standard; außerdem USDC und USDT auf Solana, ETH, USDT und USDC auf Ethereum, BNB, USDT auf BSC, POL, TRX, USDT auf TRON, BTC und LTC), hinterlege deine Wallet-Adresse für diesen Coin und fordere eine Auszahlung an. Dein Guthaben bleibt in EUR/USD; der Coin ist nur das, worin die Auszahlung gesendet wird. Mindestens 10 € (oder $), höchstens 2.000 pro Tag, eine offene Auszahlung gleichzeitig. Jeder Coin hat seine eigene Adresse, und eine neue Adresse muss 24 Stunden alt sein, bevor sie eine Auszahlung empfangen kann. Anfragen bis 500 € werden innerhalb einer Minute automatisch freigegeben; größere prüft InstantNode. Vor der Bestätigung zeigt das Dashboard ein Angebot (Kurs, Coin-Menge, geschätzte Netzwerkgebühr, was ankommt), 60 Sekunden gültig; die Netzwerkgebühr geht von der Auszahlung ab. Der Krypto-Betrag wird bei der Freigabe erneut fixiert und an deine Wallet gesendet. Du bekommst
payout.paidoderpayout.failedals Webhook; das Feldpayout.assetsagt dir, welcher Coin gesendet wurde,networkFeeCrypto, was der Transfer gekostet hat. - Automatische Auszahlungen. Lege unter Payouts einen Schwellenwert, einen Zeitplan (sobald er erreicht ist, höchstens einmal am Tag, höchstens einmal pro Woche) und einen Betrag fest, der im Guthaben bleibt; die Regel fordert Auszahlungen von selbst an, markiert als Automatisch. Aus deinem eigenen System heraus macht
POST /v1/payoutsmit{ "currency": "EUR", "amount": "250.00" }(oder"amount": "all") genau das, was das Dashboard-Formular tut, mit denselben Prüfungen; es antwortet201mit dem Auszahlungsobjekt,409 payout_open, solange eine offen ist, und400 test_modefür einen Test-Key.
Dein Konto
- Antrag. Unter Konto füllst du das Geschäftsprofil aus: Name für Kunden, rechtlicher Name, Website, Geschäftsbereich, Land, USt-IdNr. (optional), erwartetes Monatsvolumen und was du verkaufst, dann akzeptierst du die Händlerbedingungen. InstantNode prüft das, meist innerhalb eines Tages; du bekommst in jedem Fall eine Mail. Test-Keys funktionieren, während du wartest.
- Bedingungen. Ändern sich die Händlerbedingungen, bekommst du eine Mail, und der nächste Dashboard-Besuch zeigt die neue Version mit einem Haken, bevor irgendetwas anderes aufgeht; API-Keys und Webhooks laufen derweil weiter. Die aktuelle Version steht immer unter /terms.
- Benachrichtigungen. Unter Benachrichtigungen wählst du, welche Mails du willst (Zahlung eingegangen, Auszahlung oder Erstattung gesendet oder gescheitert, Webhook-Endpunkt abgeschaltet, Kontostatus, neue Anmeldung von einem neuen Gerät), trägst bis zu 5 weitere Empfänger ein und optional einen Discord- oder Slack-Webhook, der dieselben Ereignisse als kurze Nachricht bekommt.
- Sitzungen. Konto listet jeden angemeldeten Browser mit Gerät, IP und letzter Aktivität; melde einen ab oder alle anderen. Eine Anmeldung von einem Gerät, das wir auf deinem Konto noch nicht gesehen haben, bekommst du per Mail.
- Datenexport. Export erstellen baut ein Zip mit Profil, Zahlungen, Kontobuch, Auszahlungen, Erstattungen, Endpunkten, Ereignissen und Zahlungslinks als JSON. Der Link gilt 60 Minuten und wird einmal gezeigt; eine frische Anmeldung wird verlangt.
- Konto schließen. Möglich, sobald das Live-Guthaben null ist und keine Auszahlung oder Erstattung offen ist. Keys und Endpunkte werden sofort widerrufen, alle Sitzungen enden, die Daten bleiben für die Aufbewahrungsfrist.
API-Referenz
Basis-URL https://pay.instantnode.eu. Jeder Aufruf unter /v1 braucht X-API-Key: sk_live_… (oder Authorization: Bearer …); ein Key aus der Zeit vor den Paaren (ik_<id>.<secret>) funktioniert weiter. Keys liegen unter API-Keys: ein Secret Key je Modus für deinen Server (voller Zugriff, einmal angezeigt, Erneuern mit 24 h Überlappung, optionale IP-Allowlist) und ein Public Key je Modus für den Browser, der nur auf GET /v1/public/config, POST /v1/public/checkout-sessions und dem Checkout-Status angenommen wird. Alles andere antwortet einem Public Key mit 403 public_key_not_allowed.
| Scope | Erlaubt |
|---|---|
invoices:read | Rechnungen, Währungen, dein Konto, Guthaben, Ledger und Auszahlungen lesen |
invoices:write | Rechnungen anlegen, Coin vorwählen, Testzahlungen simulieren |
Schreibende Aufrufe brauchen ein aktives Konto (403 merchant_not_approved solange pending, 403 merchant_suspended bei Sperre). Ein Test-Key darf schon schreiben, während das Konto noch pending ist. Lesen geht immer.
Jeder Endpunkt mit Parametern, Bodies und Antworten steht in der interaktiven Referenz weiter unten. Dort kannst du Requests mit deinem eigenen Key ausprobieren.
Fehler kommen als JSON mit einem festen error-Code:
{"error": "invalid_request", "message": "amount: Required", "requestId": "…"}| Code | HTTP | Bedeutung |
|---|---|---|
unauthorized | 401 | Key fehlt oder stimmt nicht |
forbidden | 403 | Dem Key fehlt der Scope |
public_key_not_allowed | 403 | Ein Public Key wurde außerhalb von /v1/public/* benutzt |
ip_not_allowed | 403 | Der Key hat eine IP-Allowlist, und diese Adresse steht nicht darauf |
key_expired | 401 | Der Key wurde erneuert, und seine 24-h-Übergangsfrist ist vorbei |
merchant_not_approved | 403 | Konto noch nicht aktiv; Bewerbung im Dashboard abschicken |
merchant_suspended | 403 | Konto gesperrt; offene Rechnungen werden noch abgewickelt |
not_found | 404 | Keine solche Rechnung für diesen Key |
invalid_request | 400 | Ein Feld fehlt oder ist fehlerhaft |
invalid_amount | 400 | Betrag nicht positiv oder mehr als zwei Nachkommastellen |
price_currency_not_allowed | 400 | Nur EUR und USD |
unsafe_webhook_url | 400 | Kein https, kein öffentlicher Hostname oder ein privates Ziel |
selection_failed | 400 | Coin nicht verfügbar, Betrag zu klein oder Rechnung abgelaufen |
not_test_invoice | 403 | simulate wurde auf einer Live-Rechnung aufgerufen |
idempotency_conflict | 409 | Gleicher Idempotency-Key, anderer Inhalt |
too_many_open_invoices | 429 | Mehr als 1000 offene Rechnungen |
amount_too_large | 400 | Über dem für dein Konto gesetzten Höchstbetrag je Rechnung |
maintenance | 503 | InstantPay ist in Wartung: neue Live-Rechnungen und Auszahlungsanfragen pausieren kurz; versuche es nach den Retry-After-Sekunden erneut |
Too Many Requests | 429 | Rate-Limit; siehe Header retry-after |
internal_error | 500 | Nenn uns die requestId |
SDKs und Beispiele
Alles ist eine einzelne Datei, die du in dein Projekt kopierst; installiert werden muss nichts.
- Node: /sdk/node/instapay.mjs -
createInvoice,getInvoice,listInvoices,selectAsset,getMerchant,listLedger,listPayouts,getPayout,createPayout,listRefunds,getRefund,simulatePayment,listEvents,getEvent,verifyWebhook,parseWebhook. Der Konstruktor nimmt den Secret Key;parseWebhookversteht den Standard- und den Legacy-Body. - PHP: /sdk/php/InstaPay.php - dieselben Methoden für PHP 8 (Klasse
InstantPay). - Kompletter Shop: /examples/demo-shop/server.mjs ist der Quellcode des Demo-Shops: Produkte, Hosted Checkout, Overlay, Webhook-Empfänger und Bestellliste in einer Datei.
- Overlay in reinem HTML: /examples/plain-html.html.
- WooCommerce: /examples/woocommerce-instapay.php zusammen mit dem PHP-SDK in
wp-content/plugins/instapay/; Basis-URL, Key und Webhook-Secret unter WooCommerce → Einstellungen → Zahlungen eintragen.
Fragen oder eine Integration, die hakt: [email protected].