This guide provides comprehensive examples and patterns for integrating with Gnosis Pay’s transaction APIs, covering all three transaction kinds and their unique behaviors.

Basic Integration Setup

Authentication and API Setup

const GNOSIS_PAY_API = 'https://api.gnosispay.com';

class GnosisPayClient {
  constructor(authToken) {
    this.authToken = authToken;
  }

  async getTransactions(params = {}) {
    const queryParams = new URLSearchParams(params);
    const response = await fetch(
      `${GNOSIS_PAY_API}/api/v1/cards/transactions?${queryParams}`,
      {
        headers: {
          'Authorization': `Bearer ${this.authToken}`,
          'Content-Type': 'application/json'
        }
      }
    );
    
    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }
    
    return response.json();
  }
}

Handling Different Transaction Kinds

Transaction Processing Logic

class TransactionProcessor {
  processTransactions(transactions) {
    const processed = {
      payments: { pending: [], completed: [] },
      refunds: [],
      reversals: []
    };

    transactions.forEach(transaction => {
      switch (transaction.kind) {
        case 'Payment':
          this.processPayment(transaction, processed);
          break;
        case 'Refund':
          this.processRefund(transaction, processed);
          break;
        case 'Reversal':
          this.processReversal(transaction, processed);
          break;
        default:
          console.warn('Unknown transaction kind:', transaction.kind);
      }
    });

    return processed;
  }

  processPayment(payment, processed) {
    if (payment.isPending) {
      processed.payments.pending.push({
        ...payment,
        displayStatus: 'Processing',
        balanceImpact: -parseInt(payment.billingAmount), // Already deducted
        canCancel: this.canCancelPayment(payment)
      });
    } else {
      processed.payments.completed.push({
        ...payment,
        displayStatus: this.getPaymentDisplayStatus(payment),
        balanceImpact: 0, // Already accounted for when pending
        settlementDate: payment.clearedAt
      });
    }
  }

  processRefund(refund, processed) {
    processed.refunds.push({
      ...refund,
      displayStatus: 'Refund Processed',
      balanceImpact: parseInt(refund.refundAmount), // Money returned
      refundDate: refund.clearedAt,
      originalTransaction: this.findOriginalTransaction(refund)
    });
  }

  processReversal(reversal, processed) {
    processed.reversals.push({
      ...reversal,
      displayStatus: 'Transaction Reversed',
      balanceImpact: parseInt(reversal.reversalAmount), // Money returned
      reversalDate: reversal.clearedAt,
      reversalReason: this.determineReversalReason(reversal)
    });
  }

  getPaymentDisplayStatus(payment) {
    switch (payment.status) {
      case 'Approved': return 'Completed';
      case 'IncorrectPin': return 'Failed - Incorrect PIN';
      case 'InsufficientFunds': return 'Failed - Insufficient Funds';
      case 'Reversal': return 'Reversed';
      case 'PartialReversal': return 'Partially Reversed';
      default: return 'Completed';
    }
  }
}

Next Steps