# How to Integrate Retool with Payoneer

- Tool: Retool
- Difficulty: Intermediate
- Time required: 30 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Payoneer by creating a REST API Resource using Payoneer's OAuth 2.0 client credentials flow. Use Payoneer's API to build cross-border payout dashboards that manage payee accounts, initiate international transfers, track payment status, and view multi-currency account balances — giving finance and ops teams direct visibility into global vendor and freelancer payment operations.

## Build a Payoneer Global Payout Dashboard in Retool

Businesses that pay international freelancers, contractors, or vendors regularly face the same operational friction: switching between Payoneer's portal, spreadsheets, and internal databases to manage payout batches, verify payee status, and reconcile completed payments. Payoneer's web UI is built for individual transactions, not for the bulk management and reporting needs of finance and operations teams handling hundreds of payees across multiple currencies.

Retool bridges this gap by giving your team a configurable internal tool with direct access to Payoneer's API. You can build a payout operations panel that lists all active payees with their verification status and preferred payment method, shows real-time account balances across all Payoneer currencies, initiates single or batch payments directly from a Retool form, and tracks payment status with automated notifications when payments complete or fail.

Payoneer's API uses OAuth 2.0 client credentials for authentication — you configure the credentials once in Retool's resource settings, and all subsequent queries use the access token automatically. Retool's server-side proxy ensures your Payoneer client credentials never reach the browser, satisfying the security requirements for financial operations tooling.

## Before you start

- A Payoneer business account with API access enabled (contact Payoneer support or request through the Payoneer partner program to enable API access)
- Payoneer API credentials: Client ID and Client Secret from the Payoneer API developer portal (developer.payoneer.com)
- A Retool account with permission to create Resources
- Familiarity with Retool's query editor, Table component, and Form components
- Understanding of OAuth 2.0 client credentials flow for server-to-server authentication

## Step-by-step guide

### 1. Obtain Payoneer API credentials and store them in Retool

Payoneer API access is not available by default — you must request it through Payoneer's partner program or by contacting your Payoneer account manager. Once approved, log in to the Payoneer developer portal at developer.payoneer.com and navigate to your application settings to retrieve your Client ID and Client Secret.

Before configuring the Retool resource, store your Payoneer credentials as Retool configuration variables for security. Go to your Retool instance's Settings tab (in the left sidebar), select Configuration Variables, and create the following variables:
- PAYONEER_CLIENT_ID: your client ID string (mark as Secret)
- PAYONEER_CLIENT_SECRET: your client secret string (mark as Secret)

This ensures your credentials are never visible in query configurations or browser developer tools. Secret configuration variables in Retool are only accessible in resource configurations and Workflows — they are never exposed to the frontend or end users.

Note your Payoneer API environment: use https://api.payoneer.com for production and https://api.sandbox.payoneer.com for the sandbox environment. Always build and test in the sandbox environment first.

**Expected result:** Payoneer Client ID and Client Secret are stored as Secret configuration variables in Retool. Both production and sandbox base URLs are noted for resource configuration.

### 2. Configure the Payoneer REST API Resource

Navigate to the Resources tab in your Retool instance and click Add Resource. Select REST API from the resource type list. Name the resource 'Payoneer API' and in the Base URL field enter https://api.payoneer.com (or https://api.sandbox.payoneer.com for testing).

Payoneer uses OAuth 2.0 client credentials grant to issue Bearer access tokens. You need to first obtain a token, then use it in all subsequent requests. Configure authentication using the Custom Auth option in Retool, which supports multi-step token acquisition.

In the Authentication section, select Custom Auth. Configure the auth steps: Step 1 (HTTP Request) — Method: POST, URL: https://api.payoneer.com/v2/oauth2/token, Body: grant_type=client_credentials&client_id={{ retoolContext.configVars.PAYONEER_CLIENT_ID }}&client_secret={{ retoolContext.configVars.PAYONEER_CLIENT_SECRET }}, Content-Type header: application/x-www-form-urlencoded. Step 2 (JavaScript) — extract the access token: const token = steps[0].data.access_token; return { token };

In the Default Headers section, add: Key = Authorization, Value = Bearer {{ auth.token }}. Also add: Key = Content-Type, Value = application/json.

Set the token refresh trigger to 'On 401 response' so Retool automatically re-authenticates when the access token expires (Payoneer tokens typically expire after 3600 seconds).

Click Save Changes.

```
// Custom Auth Step 2 — extract Payoneer access token
const tokenResponse = steps[0].data;
if (!tokenResponse.access_token) {
  throw new Error('Failed to obtain Payoneer access token: ' + JSON.stringify(tokenResponse));
}
return {
  token: tokenResponse.access_token,
  expires_in: tokenResponse.expires_in || 3600
};
```

**Expected result:** The Payoneer API resource is saved with Custom Auth configured. Testing the resource with a simple GET to /v2/programs returns a successful response, confirming authentication is working correctly.

### 3. Query Payoneer payees and account balances

Create your first queries to retrieve payee and balance data. In your Retool app, open the Code panel and click the + icon to add a query. Name it getPayees, select the Payoneer API resource, set Method to GET, and set the path to /v4/payees. Add URL parameters for pagination: Key = pageSize, Value = 50, and Key = page, Value = {{ pagination.pageNumber || 1 }}.

The payees endpoint returns a list of registered payees with their verification status, preferred payment method, and registration details. Create a JavaScript transformer to flatten the nested payee response:

Create a second query named getAccountBalances with Method GET and path /v4/accounts/balances. This returns all currency balances for your Payoneer account. The response includes an array of balance objects with currency, available balance, and pending amounts.

Bind a Retool Table component named table_payees to {{ getPayees.data.payees || [] }} (after transformer). Add a Stat component for each major currency (USD, EUR, GBP) bound to values from getAccountBalances. Configure getAccountBalances to run automatically on page load.

When a payee row is selected in table_payees, trigger a getPayeeDetails query with path /v4/payees/{{ table_payees.selectedRow.id }} to load the full payee profile in a detail panel.

```
// JavaScript transformer — flatten Payoneer payee list
const payees = data?.payees || [];

return payees.map(payee => {
  return {
    id: payee.id || payee.payee_id,
    name: payee.name || `${payee.first_name || ''} ${payee.last_name || ''}`.trim() || 'Unknown',
    email: payee.email || 'N/A',
    country: payee.address?.country || 'N/A',
    status: payee.status || 'unknown',
    status_badge: payee.status === 'ACTIVE' ? '✓ Active'
      : payee.status === 'PENDING' ? '⏳ Pending'
      : '✗ Inactive',
    payment_method: payee.payment_method || 'Default',
    currency: payee.currency || 'USD',
    registered: payee.registration_date
      ? new Date(payee.registration_date).toLocaleDateString()
      : 'N/A'
  };
});
```

**Expected result:** The payee table populates with all registered Payoneer payees showing verification status and payment method. The account balance stats show current available balances in each configured currency.

### 4. Build payment initiation and tracking queries

Create queries to initiate payments and track their status. Create a query named initiatePayment with Method POST and path /v4/payments. Configure the request body as JSON:

In your Retool app, add a Form component with fields for payee selection (Dropdown bound to payee IDs), amount (Number Input), currency (Dropdown with USD/EUR/GBP/other options), description (Text Input), and an internal reference ID (Text Input for your tracking system).

Create a button named btnSendPayment with an event handler that triggers initiatePayment on click. Add a confirmation modal that appears before submission showing the payee name, amount, and currency for verification — this prevents accidental duplicate payments.

For tracking payment history, create getPaymentHistory with Method GET and path /v4/payments. Add URL parameters: Key = fromDate, Value = {{ dateRange.start }}, Key = toDate, Value = {{ dateRange.end }}, Key = status, Value = {{ select_status.value || '' }}. This retrieves all payments filtered by date range and optional status filter (PENDING, COMPLETED, FAILED).

Create a transformer to format payment history data including calculated net amounts (amount minus fee) and formatted currency values for display in a Retool Table.

```
// POST body for payment initiation
// Used in initiatePayment query body (JSON format)
{
  "payee_id": "{{ dropdown_payee.value }}",
  "amount": {{ numberInput_amount.value }},
  "currency": "{{ select_currency.value }}",
  "description": "{{ textInput_description.value }}",
  "client_reference_id": "{{ textInput_reference.value || ('PAY-' + Date.now()) }}"
}
```

**Expected result:** The payment form successfully submits to Payoneer and returns a payment ID and initial status. The payment history table shows all recent transactions with amounts, currencies, fees, and current status.

### 5. Add a payment reconciliation and export panel

Build a reconciliation view that combines Payoneer payment data with your internal records. If your company stores vendor payment records in a database connected to Retool, add that as a second resource and create a join query.

Create a JavaScript query named reconcilePayments that merges the Payoneer payment history with your internal payment records, matching on your client_reference_id field:

Add a date range picker component (DateRange component named dateRange) and a status filter dropdown. Wire these to the getPaymentHistory URL parameters so the table automatically refreshes when the filter changes.

Add a summary section with Stat components showing: total payments initiated, total payments completed, total failed payments, and total fees paid in the selected period. Calculate these using JavaScript transformers over the payment history data.

Add a CSV export button using Retool's built-in table download functionality (click the ... menu on any Table component → Download as CSV) for monthly reconciliation exports to accounting systems.

For teams managing complex multi-currency payout workflows involving multiple vendors and approval chains, RapidDev's team can help architect a comprehensive Retool payout management system that combines Payoneer with your ERP or accounting platform.

```
// JavaScript transformer — format payment history for reconciliation table
const payments = data?.payments || data?.items || [];

return payments.map(payment => {
  const amount = parseFloat(payment.amount || 0);
  const fee = parseFloat(payment.fee || 0);
  return {
    payment_id: payment.payment_id || payment.id,
    reference: payment.client_reference_id || 'N/A',
    payee: payment.payee_name || payment.payee_id || 'Unknown',
    gross_amount: `${payment.currency} ${amount.toFixed(2)}`,
    fee: `${payment.currency} ${fee.toFixed(2)}`,
    net_amount: `${payment.currency} ${(amount - fee).toFixed(2)}`,
    status: payment.status,
    initiated: payment.created_at
      ? new Date(payment.created_at).toLocaleDateString()
      : 'N/A',
    settled: payment.payment_date || payment.settled_at
      ? new Date(payment.payment_date || payment.settled_at).toLocaleDateString()
      : 'Pending'
  };
});
```

**Expected result:** The reconciliation dashboard shows a complete payment history filtered by date range and status. Summary stats show aggregate payment volume and fees. The table can be downloaded as CSV for accounting reconciliation.

## Best practices

- Store Payoneer Client ID and Client Secret as Secret configuration variables in Retool — never embed them directly in query bodies or headers where they might be visible in browser developer tools.
- Always build and test in Payoneer's sandbox environment (api.sandbox.payoneer.com) before switching to production credentials — sandbox testing prevents accidental real payments during development.
- Include a client_reference_id in every payment request that maps to your internal invoice or vendor record ID, making payment reconciliation straightforward without manual cross-referencing.
- Check payee status before rendering the payment initiation form — add conditional UI that shows a warning and disables the submit button for payees with non-ACTIVE verification status.
- Add a confirmation modal before payment submission showing the full payment details (payee name, amount, currency) — accidental duplicate submissions to Payoneer can be difficult to reverse once processing begins.
- Use Retool Workflows on a daily schedule to sync Payoneer payment statuses to your internal database, rather than querying Payoneer in real-time for every status check — this reduces API calls and gives your team a queryable local record of all payments.
- Implement Retool's permission groups to restrict payment initiation to authorized users (finance managers) while allowing read-only access to payment history for other team members.
- Format all monetary values in your transformers with the currency code prefix (e.g., 'USD 1,250.00') rather than currency symbols to avoid ambiguity in multi-currency dashboards.

## Use cases

### Build a payee directory and verification status dashboard

Create a Retool app that lists all registered Payoneer payees with their verification status (approved, pending, declined), preferred payment method, and country of residence. Add a search bar to filter by name or ID, and action buttons to view a payee's full details and payment history. Surface any unverified payees who need action before payments can be initiated.

Prompt example:

```
Build a payee management table that fetches all payees from the Payoneer API, shows name, email, country, verification status, and preferred currency, with a filter dropdown for status and a detail panel that opens when a row is selected to show the payee's full profile and recent payment history.
```

### Multi-currency account balance and payment initiation panel

Build a Retool dashboard that shows all Payoneer account balances across currencies in a summary stats section, with a form below that allows finance ops to initiate a single payment to a selected payee. Include fields for amount, currency, payment description, and an optional reference ID for internal tracking. Show the payment confirmation response after submission.

Prompt example:

```
Create an account overview panel with Stat components showing USD, EUR, and GBP balances from the Payoneer balances endpoint, and a payment form with payee selector, amount, currency, and description fields that posts to the payments endpoint and shows the resulting transaction ID and status.
```

### Payment history and reconciliation tracker

Build a reconciliation dashboard that fetches all completed and pending payments from Payoneer's payment history endpoint, filtered by date range and payment status. Display transaction ID, payee name, amount, currency, fee, status, and settlement date. Add a CSV export button and a Chart component showing monthly payment volume by currency.

Prompt example:

```
Build a payment history dashboard with a date range picker, a Table showing all Payoneer transactions with amount, currency, fee, status, and settlement date columns, and a bar chart showing total payment volume per month grouped by currency for the selected period.
```

## Troubleshooting

### 401 Unauthorized error on all Payoneer API requests after initial setup

Cause: The OAuth access token obtained during Custom Auth setup has expired (Payoneer tokens expire after 3600 seconds) or the token acquisition step is failing silently.

Solution: Verify the Custom Auth configuration in the Payoneer resource settings. Check that the token endpoint URL is correct (https://api.payoneer.com/v2/oauth2/token for production) and that the request body uses application/x-www-form-urlencoded format with the correct parameter names (grant_type, client_id, client_secret). Enable 'Refresh on 401' in the Custom Auth settings. If the issue persists, test the token endpoint directly using a new query with the POST method to the token URL.

### Payment initiation returns 400 Bad Request with 'Invalid payee status' error

Cause: Attempting to initiate a payment to a payee whose Payoneer account is not yet verified or is in a non-ACTIVE status. Payoneer requires payees to complete their account registration before receiving payments.

Solution: Before initiating payments, check the payee status using the /v4/payees/{id} endpoint. Only proceed with payment for payees with status = ACTIVE. In your Retool UI, add a conditional check that disables the payment submit button when table_payees.selectedRow.status !== 'ACTIVE', and display a warning message explaining that the payee needs to complete their Payoneer registration.

```
// Conditional to disable payment button
// Set the payment button's Disabled property to:
{{ table_payees.selectedRow?.status !== 'ACTIVE' }}
```

### Payee list returns empty array even though payees are registered in Payoneer

Cause: The Payoneer API may be filtering payees by program ID, and your account has multiple programs. The /v4/payees endpoint returns payees for the default program unless a program_id parameter is specified.

Solution: Add a URL parameter to your getPayees query: Key = program_id, Value = your Payoneer program ID (visible in the Payoneer portal under Settings → Programs). If you have multiple programs, create a separate query to first fetch all programs from /v4/programs, then allow the user to select which program's payees to view using a Dropdown component.

### Currency amounts display incorrectly or as very large integers

Cause: Some Payoneer API responses return monetary amounts in the smallest currency unit (cents for USD, pence for GBP) rather than decimal format, requiring division by 100 in transformers.

Solution: Check the Payoneer API documentation for your specific endpoint and verify whether amounts are returned as integers (cents) or decimals. If amounts appear 100x too large, divide by 100 in your JavaScript transformer before formatting: const amount = (payment.amount / 100).toFixed(2). Always include the currency code in displayed amounts to make the unit clear to users.

```
// Handle both cents and decimal formats in transformer
const rawAmount = payment.amount || 0;
// Detect if amount is in cents (value > 1000 for typical payments)
const amount = rawAmount > 1000 && Number.isInteger(rawAmount)
  ? (rawAmount / 100).toFixed(2)
  : parseFloat(rawAmount).toFixed(2);
return `${payment.currency} ${amount}`;
```

## Frequently asked questions

### Does Payoneer have a native connector in Retool?

No, Payoneer does not have a native connector in Retool. You must configure it as a REST API Resource using OAuth 2.0 client credentials authentication. The integration requires setting up a Custom Auth flow in Retool to obtain and refresh Bearer access tokens from Payoneer's token endpoint before making API calls.

### How do I get API access to Payoneer's API?

Payoneer API access is not self-serve for standard accounts. You need to either join Payoneer's partner program or contact your Payoneer account manager to request API credentials. Enterprise accounts and marketplace operators typically receive API access as part of their agreement. Once approved, credentials are available through the Payoneer developer portal at developer.payoneer.com.

### Can I use Retool to send batch payments to multiple payees at once?

Yes, you can build a batch payment workflow in Retool using a JavaScript query or a Retool Workflow with a Loop block. In the app, build a Table with checkboxes for payees and payment amounts, then trigger a Loop block that iterates over selected rows and calls the Payoneer payment endpoint for each payee. The Workflow handles retries and tracks success/failure per payment. Always include a unique client_reference_id per payment to detect and prevent duplicate submissions.

### What currencies does Payoneer support through the API?

Payoneer supports 70+ currencies for receiving and sending payments through the API, including USD, EUR, GBP, CAD, AUD, JPY, and many emerging market currencies. The available currencies for payout depend on the payee's country and Payoneer's coverage in that region. Query the /v4/accounts/balances endpoint to see which currency accounts are active on your Payoneer account.

### How do I reconcile Payoneer payments with my accounting system using Retool?

Build a Retool Workflow that runs on a daily schedule, fetches all completed Payoneer payments from the /v4/payments endpoint for the previous day, and writes them to your accounting database or Retool Database table. Include the client_reference_id (which maps to your internal invoice/purchase order ID) and all fee information. This creates a local payment ledger that can be queried without hitting Payoneer's API and exported to accounting formats as needed.

---

Source: https://www.rapidevelopers.com/retool-integrations/payoneer
© RapidDev — https://www.rapidevelopers.com/retool-integrations/payoneer
