Transaction History Component

Filterable transaction table to view, manage, and export transaction data

BETA

Embed a near real-time transaction table directly in your platform so merchants can review activity, filter and sort results, open transaction details, and export data without switching tools.

Installation

We offer a variety of npm modules for popular frameworks. The easiest way to get started is to install the module for the framework being used.

npm i @nmipayments/nmi-reporting-react
npm i @nmipayments/nmi-reporting

Get Your API Keys

Sandbox Keys for Testing

For testing, you can find your sandbox key on the My Sandbox Keys page.

  • Located under Partner Key section
  • Must be kept secure on your server
  • Authorizes access to transaction data

Production Keys

When you are ready to go live, replace your sandbox key with a production key.

Production Keys are available in the Partner Portal. See Getting Your API Keys for details.

🚧

Security: Never expose your API security key in client-side code. Always keep it secure on your server. While we have included your test key in the code sample, you should not commit it to source control and instead inject it via an environment variable.

Merchant Central only partners should use the Merchant Central API Key.

If you are not a Gateway partner, you will create a session token using your Merchant Central API token instead of the Gateway key.

  1. Log in to your NMI Payments portal
  2. Click your username in the top-right corner
  3. Select Settings
  4. Open the API Settings tab
  5. Click Create New API Token

Give the token a name, optionally restrict IPs, then click Add New Token.

Your new token is now generated and displayed in a popup window (along with your public key which isn't needed for the deposit history component).

Once created, it cannot be copied after initially being created so be sure to save it during creation.


Key Functional Component Properties

Required Properties

fetchSessionId

The fetchSessionId property is a required function that you pass that returns a session token.

fetchSessionId: () => Promise<SessionResponse>

SessionResponse Type:

interface SessionResponse {
  sessionToken: string;
  expiresAt: number;
}

sequenceDiagram
    participant TR as TransactionReporting Component
    participant YA as Your Application
    participant API as Your API
    participant RS as NMI Reporting Service

    Note over TR,RS: Session Token Flow

    TR->>YA: fetchSessionId() called
    Note right of TR: Component needs session token<br/>for API authentication

    YA->>API: Call your session endpoint
    Note right of YA: Your app calls your API<br/>with merchant context

    API->>RS: POST /api/v1/sessions
    Note right of API: Send API credentials<br/>and merchant context

    RS-->>API: SessionResponse
    Note left of RS: {<br/>  sessionToken: "sess_xxx",<br/>  expiresAt: timestamp<br/>}

    API-->>YA: SessionResponse
    Note left of API: Return session token<br/>to your application

    YA-->>TR: SessionResponse
    Note left of YA: Pass session token<br/>to component

    TR->>RS: API calls with session token
    Note right of TR: Use token for all<br/>reporting API requests

    RS-->>TR: Deposit data
    Note left of RS: Return deposit information<br/>based on session permissions

reportingServiceUrl

Required. The URL of the reporting endpoint from which data will be retrieved.

reportingServiceUrl: String

Optional Properties

demoSet

Optional. When provided, the component will load demo data for preview purposes. Accepted values: gateway, merchant-central.
To load production data, omit this property or pass an empty value.

demoSet?: String //gateway, merchant-central

appearance

Optional styling configuration. See the Appearance API to learn more.

appearance?: Appearance

pagination

The pagination state.

  • pageSize: Number of items per page (default: 10)
  • currentPage: Initial page number (default: 1)
pagination?: {
  pageSize?: number;
  currentPage?: number;
}

onTransactionsLoaded

Fires with TransactionData when transaction data is loaded.

onTransactionsLoaded?: ((transactions: TransactionData[]) => void)

TransactionData Type:

interface TransactionData {
  id: string;
  date: string; // ISO 8601 format
  type: TransactionType;
  status: TransactionStatus;
  amount: number; // Decimal number with currency precision
  payment_method: PaymentMethod; // e.g., 'ach' or 'card'
  processor_response_code: string;
  processor_response_code_description: string;
  gateway_response_code: string;
  gateway_response_description: string;
  payment_method_brand: PaymentCardBrand;
  payment_method_last_4: string; // Last 4 digits of card/account
  payment_method_expiration_date: string; // 'MM/YY' format
  customer_name: string;
  customer_email: string;
  customer_address: string;
  customer_country: string;
  order_id: string;
  entry_method: EntryMethod;
  merchant_defined_fields: Record<string, string>;
  authorization_code: string;
  events: TransactionEvent[];
}

type TransactionType = 'payment' | 'refund';
type TransactionStatus = 'pending' | 'failed' | 'complete' | 'canceled';
type PaymentMethod = 'card' | 'ach';
type PaymentCardBrand = 'visa' | 'mastercard' | 'american_express' | 'discover';
type TransactionEvent = {
  name: string;
  description?: string; // optional
  date: string; // ISO 8601 format
}

onError

Fires when an error occurs during data loading or processing.

onError?: (error: { type: string; message: string; code?: string }) => void

onRowClick

Fires when a deposit row is clicked.

onRowClick?: (transaction: TransactionData) => void

onFilterChange

Fires when filter settings change.

onFilterChange?: (filters: TransactionFilters) => void

TransactionFilters Type:

type TransactionFilters = {
  statuses?: TransactionStatus[]; // Transaction status filter - exact match
  types?: TransactionType[]; // Transaction type filter - exact match
  payment_method?: PaymentMethod[]; // Payment method filter - exact match
  amount_min?: number; // Minimum amount filter - exact match
  amount_max?: number; // Maximum amount filter - exact match
  transaction_id?: string; // Transaction ID filter - exact match
  customer_first_name?: string; // Customer first name filter - exact match
  customer_last_name?: string; // Customer last name filter - exact match
  customer_email?: string; // Customer email filter - exact match
  start_date?: string; // ISO 8601 date string for filtering by created date (inclusive)
  end_date?: string; // ISO 8601 date string for filtering by created date (inclusive)
}

onSortChange

Fires when sort settings change.

onSortChange?: (sort: TransactionSortConfig) => void

TransactionSortConfig Type:

interface TransactionSortConfig {
  field: 'date' | 'types' | 'statuses' | 'customer_name' | 'amount' | 'id';
  direction: 'asc' | 'desc';
}

onPaginationChange

Fires when pagination settings change.

onPaginationChange?: (pagination: TransactionPaginationState) => void

PaginationState Type:

interface TransactionPaginationState {
  currentPage: number;
  pageSize: number;
  totalCount: number;
  lastPage: number;
}

onExport

Fires when export data is ready.

onExport?: (data: TransactionReportingExportData) => void

ExportData Type:

interface TransactionReportingExportData extends TransactionReportingExportConfig {
  downloadUrl: string;
  fileSize: string;
  expiresAt: string;
  fileHash: string;
}

interface TransactionReportingExportConfig {
  format: 'csv';
  filters: TransactionFilters;
  sort: string;
}

children

Optional React children rendered inside the component.

children?: ReactNode

Example Implementation

import { TransactionReporting } from '@nmipayments/nmi-reporting-react';

const MyComponent = () => {
  const fetchSessionId = async () => {
    //check session page for details
  };

  const handleTransactionsLoaded = (transactions) => {
    console.log('Transactions loaded:', transactions);
  };

  const handleError = (error) => {
    console.error('Error:', error);
  };

  return (
    <TransactionReporting
      fetchSessionId={fetchSessionId}
      reportingServiceUrl="REPLACE_WITH_REPORTING_SERVICE_URL"
      pagination={{ pageSize: 25, currentPage: 1 }}
      onTransactionsLoaded={handleTransactionsLoaded}
      onError={handleError}
      onRowClick={(deposit) => console.log('Row clicked:', deposit)}
      onFilterChange={(filters) => console.log('Filters changed:', filters)}
      onSortChange={(sort) => console.log('Sort changed:', sort)}
      onPaginationChange={(pagination) => console.log('Pagination changed:', pagination)}
      onExport={(data) => console.log('Export ready:', data)}
    />
  );
};
// main.js
import '@nmipayments/nmi-reporting';

const fetchSessionId = async () => {
    //check session page for details
};

const widget = document.createElement('nmi-transaction-reporting');

widget.fetchSessionId = fetchSessionId;
widget.reportingServiceUrl = REPORTING_SERVICE_URL;
widget.pagination = { pageSize: 10, currentPage: 1 };
widget.onTransactionsLoaded = (transactions) => console.log('Transactions loaded:', transactions);
widget.onError = (error) => console.error('Error:', error);
widget.onRowClick = (transaction) => console.log('Row clicked:', transaction);
widget.onFilterChange = (filters) => console.log('Filters changed:', filters);
widget.onSortChange = (sort) => console.log('Sort changed:', sort);
widget.onPaginationChange = (pagination) => console.log('Pagination changed:', pagination);
widget.onExport = (data) => console.log('Export:', data);

document.getElementById('transaction-reporting-container').appendChild(widget);