ARYZE Open Finance

Consume webhooks

Receive payment status updates, handle retries, and keep your handler idempotent.

Whenever a payment's status changes, ARYZE POSTs a JSON body to the webhook URL configured on your API key. There is one event type today: payment.status_updated.

Configure your webhook URL

Webhook URLs are set per API key in the dashboard at Open Finance → API Keys. You can update the URL without rotating the key. The endpoint must be HTTPS and reachable from the public internet — non-HTTPS URLs are rejected on save.

Event shape

{
  "event": "payment.status_updated",
  "transactionId": "2f1a3e8c-9b7d-4a11-8c6f-d3e5e9b1a2c0",
  "mastercardPaymentId": "mcob_8f3c2a...",
  "status": "COMPLETED",
  "amount": 100.50,
  "currencyCode": "EUR",
  "timestamp": "2026-04-21T14:32:10Z"
}

Prop

Type

Your merchant reference and any metadata you sent on POST /v1/payments/initiate are not included in the webhook. Look them up by transactionId against your own store — you should have saved them when you created the payment.

Acknowledge quickly, process later

Return 200 OK as soon as you've persisted the event. Do the real work (fulfilment, emails, accounting) in a background job. ARYZE treats any non-2xx response as failure and retries.

Express.js
import express from 'express';

const app = express();
app.use(express.json());

app.post('/webhooks/aryze', async (req, res) => {
  const event = req.body;

  try {
    await saveEventIfNew(event); // idempotency check
    res.status(200).json({ received: true });
  } catch (err) {
    console.error('Webhook persistence failed', err);
    res.status(500).json({ error: 'retry please' });
    return;
  }

  // Off the request path — don't await this.
  enqueueFulfilmentJob(event).catch(console.error);
});

app.listen(3000);

Idempotency

ARYZE may deliver the same event more than once (retries, network retransmits, or the same transaction moving through the same terminal state). Store each event by transactionId + status and skip work you've already done.

async function saveEventIfNew(event: WebhookEvent) {
  const key = `${event.transactionId}:${event.status}`;
  const inserted = await db.webhookEvents.insert({
    key,
    payload: event,
    receivedAt: new Date(),
  }).onConflict('key').ignore();

  if (!inserted) throw new DuplicateEvent(key);
}

Retry policy

If your endpoint doesn't return a 2xx response within 10 seconds, ARYZE retries.

Prop

Type

There is no HMAC signature on webhook requests today. Until signing is available, use an unguessable webhook URL (for example, include a long random segment) and cross-check every event by fetching the transaction with GET /v1/payments/{transactionId} before acting on it.

Handling each status

On this page