Get Charge Status
Overview
Retrieve the current status and full details of a payment charge. Use this endpoint to:
- Check if a payment has been completed
- Get payment provider details and references
- View payment amount and currency
- See status history and transitions
- Retrieve metadata you attached during checkout
A charge represents a customer's payment attempt. Each completed checkout creates a charge.
When to use: Poll this endpoint to check payment status, or use it to retrieve charge details after receiving a webhook notification.
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/charges/{charge_id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
charge_id |
string | Yes | The unique charge identifier (starts with chr_) |
Example Request
curl https://api.usesyncpay.com/api/v1/payments/charges/chr_1a2b3c4d5e6f \
-H "Authorization: Bearer sk_live_abc123xyz..."
Response
200 – Success
Returns complete charge details including status history.
{
"charge_id": "chr_1a2b3c4d5e6f",
"organization_id": "org_abc123",
"customer_id": "cust_xyz789",
"amount": "75000.00",
"currency": "NGN",
"settlement_currency": "NGN",
"settlement_amount": "74250.00",
"status": "COMPLETED",
"payment_provider": null,
"provider_reference": "REF-12345",
"metadata": {
"order_id": "ORD-12345",
"product_sku": "PREMIUM-ANNUAL"
},
"status_history": [
{
"status": "PENDING",
"occurred_at": "2026-01-24T14:30:00.000Z",
"provider_reference": null,
"reason": null
},
{
"status": "AWAITING_PAYMENT",
"occurred_at": "2026-01-24T14:30:30.000Z",
"provider_reference": "REF-12345",
"reason": null
},
{
"status": "COMPLETED",
"occurred_at": "2026-01-24T14:35:00.000Z",
"provider_reference": "REF-12345",
"reason": "Payment received and confirmed"
}
],
"created_at": "2026-01-24T14:30:00.000Z",
"updated_at": "2026-01-24T14:35:00.000Z"
}
Response Fields
| Field | Type | Description |
|---|---|---|
charge_id |
string | Unique charge identifier |
organization_id |
string | Your organization ID |
customer_id |
string | Customer identifier |
amount |
string | Amount customer paid |
currency |
string | Currency customer paid in |
settlement_currency |
string | Currency you'll receive settlement in |
settlement_amount |
string | Amount you'll receive (after fees) |
status |
string | Current charge status (see statuses below) |
payment_provider |
string|null | Payment provider (not exposed for security) |
provider_reference |
string | Transaction reference ID |
metadata |
object | Your custom metadata from checkout |
status_history |
array | Chronological history of status changes |
created_at |
string | ISO 8601 timestamp of charge creation |
updated_at |
string | ISO 8601 timestamp of last update |
Charge Statuses
Charges go through various statuses during their lifecycle:
| Status | Description | Is Final? |
|---|---|---|
PENDING |
Charge created, awaiting customer action | No |
AWAITING_PAYMENT |
Customer initiated payment, waiting for confirmation | No |
PROCESSING |
Payment received, being processed | No |
COMPLETED |
Payment successful, funds settled | Yes |
FAILED |
Payment failed or was declined | Yes |
CANCELLED |
Customer cancelled the payment | Yes |
EXPIRED |
Charge expired before payment completed | Yes |
REFUNDED |
Payment was refunded to customer | Yes |
Final Statuses
Once a charge reaches a final status (COMPLETED, FAILED, CANCELLED, EXPIRED, REFUNDED), it will not change again.
404 – Not Found
Charge doesn't exist or doesn't belong to your organization.
{
"error": {
"code": "NOT_FOUND",
"message": "Charge not found"
}
}
Causes:
- Invalid
charge_id - Charge belongs to a different organization
- Charge exists in a different environment (test vs live)
401 – Unauthorized
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid API key"
}
}
403 – Forbidden
You don't have access to this charge.
{
"error": {
"code": "FORBIDDEN",
"message": "Charge does not belong to your organization"
}
}
Cause: The charge was created by a different organization.
Example Use Case
Scenario: Your order management system needs to automatically update order status when payments complete. After redirecting a customer to checkout, you need to monitor the payment status and automatically fulfill orders when payments succeed, or notify customers if payments fail. You want to poll the charge status periodically until you receive a final status.
Implementation:
async function waitForPaymentCompletion(chargeId, maxAttempts = 60) {
const finalStatuses = ['COMPLETED', 'FAILED', 'CANCELLED', 'EXPIRED', 'REFUNDED'];
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
// Get charge status
const response = await fetch(
`https://api.usesyncpay.com/api/v1/payments/charges/${chargeId}`,
{
headers: {
'Authorization': 'Bearer sk_live_abc123xyz...'
}
}
);
const charge = await response.json();
console.log(`[Attempt ${attempt}] Status: ${charge.status}`);
// Check if payment reached a final status
if (finalStatuses.includes(charge.status)) {
return {
completed: charge.status === 'COMPLETED',
status: charge.status,
charge: charge
};
}
// Wait 5 seconds before next poll
await new Promise(resolve => setTimeout(resolve, 5000));
}
// Timeout after 5 minutes (60 attempts * 5 seconds)
throw new Error('Payment status check timed out');
}
// Usage
try {
const result = await waitForPaymentCompletion('chr_1a2b3c4d5e6f');
if (result.completed) {
console.log('Payment successful!');
console.log('Settlement amount:', result.charge.settlement_amount);
// Grant access to product/service
} else {
console.log('Payment failed:', result.status);
// Handle failure
}
} catch (error) {
console.error('Error:', error);
}
Understanding Settlement Amounts
The settlement_amount is what you actually receive after fees are deducted:
settlement_amount = amount - fees
Example:
- Customer pays:
NGN 75,000.00(amount) - Fees:
NGN 750.00 - You receive:
NGN 74,250.00(settlement_amount)
The fees are calculated based on:
- Payment method used
- Your fee configuration
- Transaction amount
Using Status History
The status_history array shows every status change with timestamps:
// Find when payment was completed
const charge = await getCharge('chr_1a2b3c4d5e6f');
const completedEvent = charge.status_history.find(e => e.status === 'COMPLETED');
if (completedEvent) {
console.log('Payment completed at:', completedEvent.occurred_at);
console.log('Processing time:',
new Date(completedEvent.occurred_at) - new Date(charge.created_at),
'milliseconds'
);
}
// Check for failures
const failedEvent = charge.status_history.find(e => e.status === 'FAILED');
if (failedEvent && failedEvent.reason) {
console.log('Failure reason:', failedEvent.reason);
}
Common Questions
How long should I poll?
Most payments complete within 5-10 minutes. Recommended timeout: 10 minutes.
What if status is stuck in PENDING?
- Wait at least 10 minutes before assuming an issue
- Check if customer completed the payment
- Contact support if status doesn't update after 15 minutes
Can a COMPLETED charge change to FAILED?
No. Once COMPLETED, the status is final. However, a completed charge can later be REFUNDED.
How do I know the exact amount I'll receive?
Use the settlement_amount field. This is your net amount after all fees.
Can I get charges for a specific checkout?
Yes, use List Payins and filter by checkout_id.
Related Endpoints
- Create Checkout - Create a checkout that generates a charge
- List Payins - List all charges for your organization
- Webhook Events - Receive real-time charge updates
Next Steps
After retrieving charge status:
- If COMPLETED: Grant access to product/service, update order status
- If FAILED: Notify customer, offer retry or alternative payment method
- If PENDING: Continue polling or wait for webhook
- Set up webhooks for production use (see Webhook Documentation)