Documentation/API/Notifications "Webhook"

Transaction Notification Stream - Consumer Guide

Subject to change with minimum impact

VERTEX ENGINE

00

Table of Contents

  1. Message Schema
  2. Request-Reply Pattern
  3. JavaScript Examples
  4. FAQ

Overview

The Transaction Notification Stream provides real-time notifications for transaction lifecycle events using NATS request-reply messaging. This system delivers events reliably with automatic retry and timeout handling.

Message Schema

Subject Pattern

Messages are published to subjects following this pattern:

workqueue.notification.<partner_id>.transaction.<transaction_id>

Examples:

workqueue.notification.950db7cb-febe-4c5e-a447-0373a2ab001b.transaction.2f805c37-ba32-43c5-b5f8-4d8970f4bdd9
workqueue.notification.52c844f1-17b3-4aa5-9a59-f4f7eaca22c3.transaction.2992b67d-8a5b-40b7-abeb-7e8e11742c99

Message Payload

All messages follow this JSON schema:

{
  "event": "created",
  "data": {
    "notification_type": "transaction",
    "transaction_id": "2f805c37-ba32-43c5-b5f8-4d8970f4bdd9",
    "transaction_type": "EFT",
    "account_id": "9c09dcf2-ee29-4d85-a6c5-843ea8113509",
    "amount": {
      "amount": 10000000,
      "currency": "ZAR"
    },
    "timestamp": "2025-10-09T10:51:01.862974041+02:00"
  }
}

Field Descriptions

FieldTypeDescription
eventstringEvent lifecycle phase: created, succeeded, failed, cancelled
data.notification_typestringAlways "transaction" for this stream
data.transaction_idUUIDUnique identifier for the transaction
data.transaction_typestringType of transaction: EFT, CARD, INSTANT_PAYMENT, etc.
data.account_idUUIDAccount associated with the transaction
data.amount.amountintegerAmount in minor units (e.g., cents for ZAR)
data.amount.currencystringISO 4217 currency code (e.g., ZAR, KES)
data.timestampRFC3339Event creation timestamp

Amount Field Notes

Important

The amount field represents minor units (smallest currency denomination).

Subscription Patterns:

// Listen to all transactions for your partner
const myPartnerSubject = `workqueue.notification.${partnerId}.transaction.*`;

// Listen to all notifications (any type) for your partner
const allPartnerNotifications = `workqueue.notification.${partnerId}.>`;

Request-Reply Pattern

How It Works

The notification system uses NATS request-reply messaging:

  1. Sava sends request: Transaction event is published to your subject
  2. Your service receives: Message arrives at your subscribed handler
  3. Your service processes: Parse JSON, execute business logic
  4. Your service responds: Send acknowledgment reply (required within 5s)

Response Requirements

CRITICAL

You MUST respond to every request within 5 seconds:

// Simple acknowledgment (success)
msg.respond(JSON.stringify({}));

Note: Use JSON.parse() for decoding incoming JSON messages.

Failure to respond will:

  • Trigger automatic retries
  • Cause the same message to be redelivered
  • Impact system performance

JavaScript Examples

Language Support

This is a JavaScript example. You can use any other programming language with NATS client libraries.

Basic Consumer (Browser/Node.js)

import { connect, jwtAuthenticator, JSONCodec } from "nats.ws";

async function main() {
  // Connection initialisation truncated for brevity
  const m = { json: (data) => JSON.parse(data) };

  // Subscribe to partner's transactions
  const subject = `workqueue.notification.${config.partnerId}.transaction.*`;

  const sub = nc.subscribe(subject, {
    callback: async (err, msg) => {
      if (err) {
        console.error("Subscription error:", err);
        return;
      }

      // Parse notification (automatically decoded from JSON)
      const notification = m.json();

      console.log(`Transaction ${notification.data.transaction_id}: ${notification.event}`);
      console.log(`  Type: ${notification.data.transaction_type}`);
      console.log(`  Amount: ${notification.data.amount.currency} ${notification.data.amount.amount / 100}`);

      // Process notification
      await processTransaction(notification);

      // CRITICAL: Send response (automatically encoded to JSON)
      msg.respond(JSON.stringify({}));
    }
  });

  console.log(`Listening for notifications on: ${subject}`);

  // Cleanup setup if required
}

async function processTransaction(notification) {
  // Your business logic here
}

Support & Resources

NATS Resources