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.



Next Steps

After retrieving charge status:

  1. If COMPLETED: Grant access to product/service, update order status
  2. If FAILED: Notify customer, offer retry or alternative payment method
  3. If PENDING: Continue polling or wait for webhook
  4. Set up webhooks for production use (see Webhook Documentation)