List Payins
Overview
Retrieve a paginated list of all payment charges (payins) for your organization. Use this endpoint to:
- View all payments received
- Filter payments by status
- Build transaction history dashboards
- Reconcile payments with your internal systems
- Export payment data for accounting
A payin (also called a charge) represents any incoming payment from a customer.
Authentication
Type: API Key (required)
Required Headers
| Header | Required | Description |
|---|---|---|
Authorization |
Yes | Format: Bearer sk_test_... or Bearer sk_live_... |
Request
Method & Path
GET /api/v1/payments/payins
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit |
integer | No | 50 | Number of results per page (1-100) |
offset |
integer | No | 0 | Number of results to skip (for pagination) |
status_filter |
string | No | - | Filter by status (e.g., COMPLETED, FAILED) |
Example Requests
Get first 50 payins:
curl https://api.usesyncpay.com/api/v1/payments/payins \
-H "Authorization: Bearer sk_live_abc123xyz..."
Get next page (51-100):
curl "https://api.usesyncpay.com/api/v1/payments/payins?limit=50&offset=50" \
-H "Authorization: Bearer sk_live_abc123xyz..."
Get only completed payments:
curl "https://api.usesyncpay.com/api/v1/payments/payins?status_filter=COMPLETED" \
-H "Authorization: Bearer sk_live_abc123xyz..."
Get 20 failed payments:
curl "https://api.usesyncpay.com/api/v1/payments/payins?status_filter=FAILED&limit=20" \
-H "Authorization: Bearer sk_live_abc123xyz..."
Response
200 – Success
Returns a paginated list of payins.
{
"total": 342,
"items": [
{
"charge_id": "chr_1a2b3c4d5e6f",
"checkout_id": "chk_9x8y7z6w5v",
"organization_id": "org_abc123",
"amount": "75000.00",
"currency": "NGN",
"status": "COMPLETED",
"payment_provider": null,
"provider_reference": "REF-12345",
"created_at": "2026-01-24T14:30:00.000Z",
"updated_at": "2026-01-24T14:35:00.000Z"
},
{
"charge_id": "chr_2b3c4d5e6f7g",
"checkout_id": "chk_8y7z6w5v4u",
"organization_id": "org_abc123",
"amount": "50.00",
"currency": "USD",
"status": "COMPLETED",
"payment_provider": null,
"provider_reference": "REF-67890",
"created_at": "2026-01-24T13:15:00.000Z",
"updated_at": "2026-01-24T13:20:00.000Z"
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
total |
integer | Total number of payins matching the filter |
items |
array | Array of payin objects (max length based on limit) |
items[].charge_id |
string | Unique charge identifier |
items[].checkout_id |
string | Associated checkout session ID |
items[].organization_id |
string | Your organization ID |
items[].amount |
string | Payment amount |
items[].currency |
string | Payment currency |
items[].status |
string | Current payment status |
items[].payment_provider |
string|null | Payment provider (not exposed for security) |
items[].provider_reference |
string | Transaction reference ID |
items[].created_at |
string | ISO 8601 timestamp of creation |
items[].updated_at |
string | ISO 8601 timestamp of last update |
400 – Bad Request
Invalid query parameters.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid query parameters",
"details": {
"limit": "Must be between 1 and 100",
"offset": "Must be non-negative"
}
}
}
401 – Unauthorized
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid API key"
}
}
Pagination
How Pagination Works
Use limit and offset to paginate through results:
- limit: How many results per page (1-100)
- offset: How many results to skip
Example: To get page 3 with 50 results per page:
- offset = (page - 1) × limit = (3 - 1) × 50 = 100
- limit = 50
curl "https://api.usesyncpay.com/api/v1/payments/payins?limit=50&offset=100"
Calculating Total Pages
const totalPages = Math.ceil(response.total / limit);
Building a Paginator
async function getAllPayins(statusFilter = null) {
const limit = 50;
let offset = 0;
let allPayins = [];
let hasMore = true;
while (hasMore) {
const url = new URL('https://api.usesyncpay.com/api/v1/payments/payins');
url.searchParams.append('limit', limit);
url.searchParams.append('offset', offset);
if (statusFilter) {
url.searchParams.append('status_filter', statusFilter);
}
const response = await fetch(url, {
headers: {
'Authorization': 'Bearer sk_live_abc123xyz...'
}
});
const data = await response.json();
allPayins = allPayins.concat(data.items);
// Check if there are more pages
hasMore = data.items.length === limit;
offset += limit;
}
return allPayins;
}
// Get all completed payments
const completedPayins = await getAllPayins('COMPLETED');
console.log(`Total completed payins: ${completedPayins.length}`);
Filtering by Status
Use status_filter to get payins in a specific status:
Available Status Filters
| Status | Description |
|---|---|
COMPLETED |
Successfully completed payments |
PENDING |
Awaiting customer action |
AWAITING_PAYMENT |
Customer initiated, waiting for confirmation |
PROCESSING |
Payment being processed |
FAILED |
Failed payments |
CANCELLED |
Cancelled by customer |
EXPIRED |
Expired before completion |
REFUNDED |
Refunded payments |
Example: Get Only Failed Payments
async function getFailedPayments() {
const response = await fetch(
'https://api.usesyncpay.com/api/v1/payments/payins?status_filter=FAILED&limit=100',
{
headers: {
'Authorization': 'Bearer sk_live_abc123xyz...'
}
}
);
const data = await response.json();
console.log(`Found ${data.total} failed payments`);
// Analyze failure reasons
for (const payin of data.items) {
const details = await getChargeDetails(payin.charge_id);
console.log(`Charge ${payin.charge_id} failed:`, details.status_history);
}
}
Example Use Case
Scenario: Your business dashboard needs to display a comprehensive transaction history showing all payments received. You need to build a paginated view that allows users to browse through completed payments, filter by status, and export transaction data for accounting purposes. The system should handle large volumes of transactions efficiently.
Implementation:
// Backend API
app.get('/api/transactions', async (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = 20;
const offset = (page - 1) * limit;
const response = await fetch(
`https://api.usesyncpay.com/api/v1/payments/payins?` +
`status_filter=COMPLETED&limit=${limit}&offset=${offset}`,
{
headers: {
'Authorization': `Bearer ${process.env.SYNCPAY_API_KEY}`
}
}
);
const data = await response.json();
res.json({
transactions: data.items,
totalPages: Math.ceil(data.total / limit),
currentPage: page,
totalTransactions: data.total
});
});
// Frontend
async function loadTransactions(page = 1) {
const response = await fetch(`/api/transactions?page=${page}`);
const data = await response.json();
// Display transactions
displayTransactions(data.transactions);
// Render pagination
renderPagination(data.currentPage, data.totalPages);
}
Sorting and Ordering
Payins are returned in reverse chronological order (newest first) based on created_at.
- Most recent payments appear first
- Pagination maintains this order across pages
Example: First page shows payins from today, last page shows oldest payins.
Performance Considerations
Limit Recommendations
| Use Case | Recommended Limit |
|---|---|
| Web dashboard (user-facing) | 20-50 |
| Admin panel | 50-100 |
| Bulk export/processing | 100 |
| Real-time monitoring | 10-20 |
Caching Strategies
For dashboards, consider caching results:
const cache = new Map();
const CACHE_TTL = 60000; // 1 minute
async function getCachedPayins(statusFilter, limit, offset) {
const cacheKey = `${statusFilter}-${limit}-${offset}`;
const cached = cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const data = await fetchPayins(statusFilter, limit, offset);
cache.set(cacheKey, {
data: data,
timestamp: Date.now()
});
return data;
}
Getting Detailed Information
This endpoint returns summary information. To get full details (including metadata, fees, status history):
async function getPayinsWithDetails(limit = 50) {
// 1. Get list of payins
const listResponse = await fetch(
`https://api.usesyncpay.com/api/v1/payments/payins?limit=${limit}`,
{ headers: { 'Authorization': 'Bearer sk_live_...' } }
);
const list = await listResponse.json();
// 2. Get details for each payin
const detailedPayins = await Promise.all(
list.items.map(async (payin) => {
const detailResponse = await fetch(
`https://api.usesyncpay.com/api/v1/payments/charges/${payin.charge_id}`,
{ headers: { 'Authorization': 'Bearer sk_live_...' } }
);
return await detailResponse.json();
})
);
return detailedPayins;
}
Note: Be mindful of rate limits when fetching details for many payins.
Export Example
Export all completed payments to CSV:
async function exportPayinsToCsv() {
const limit = 100;
let offset = 0;
let rows = ['Charge ID,Amount,Currency,Status,Created At,Reference'];
while (true) {
const response = await fetch(
`https://api.usesyncpay.com/api/v1/payments/payins?` +
`status_filter=COMPLETED&limit=${limit}&offset=${offset}`,
{ headers: { 'Authorization': 'Bearer sk_live_...' } }
);
const data = await response.json();
if (data.items.length === 0) break;
// Add rows
for (const payin of data.items) {
rows.push([
payin.charge_id,
payin.amount,
payin.currency,
payin.status,
payin.created_at,
payin.provider_reference
].join(','));
}
offset += limit;
}
// Write to file or return as string
return rows.join('\n');
}
Important Notes
Environment Separation
Test and live mode payins are completely separate:
sk_test_...returns test mode payins onlysk_live_...returns live mode payins only
Rate Limits
Be mindful of rate limits when paginating through large datasets:
- Standard tier: 100 requests per minute
- Consider implementing exponential backoff for bulk operations
Consistency
The total count may change between requests if:
- New payments are received
- Payments change status (e.g., PENDING → COMPLETED)
For consistent pagination, consider:
- Caching the initial result set
- Using timestamp-based filtering (coming soon)
Related Endpoints
- Get Charge Status - Get detailed information for a single charge
- Get Payin - Get a single payin by ID (same as Get Charge Status)
- Create Checkout - Create checkouts that generate payins
- Webhook Events - Receive real-time payin updates
Next Steps
After retrieving payins:
- Build dashboards showing revenue and transaction trends
- Reconcile payments with your internal order system
- Generate reports for accounting and financial analysis
- Monitor failed payments to identify issues
- Set up webhooks for real-time notifications (see Webhook Documentation)