Payment Gateway API Documentation

Complete integration guide for our Payment Gateway API. Payments are captured on your payment provider's hosted checkout page — your integration initializes the payment, redirects the customer, and confirms the result server-side.

Key Features

  • Hosted provider checkout — card data never touches your servers
  • 3D Secure handled on the provider's hosted flow
  • Automatic payment method selection per your account configuration
  • Flexible address handling
  • Transaction status API and refunds
  • Multi-currency support

Authentication

All API requests must include your API credentials in the request headers:

X-Api-Key: your_api_key_here
X-Api-Secret: your_api_secret_here
Content-Type: application/json
Security: Never expose your API credentials in client-side code. All API calls should be made from your secure server environment.

Payment Processing

Our gateway automatically handles payment method selection and routing based on your account configuration. You don't need to specify payment providers - the system will use the optimal method for each transaction.

Feature Support Description
Cards ✅ Via your acquirer Card schemes supported by the acquirer account you connect
3D Secure ✅ Provider-hosted 3DS runs on the provider's hosted checkout where the issuer requires it
Local rails ✅ Via providers M-Pesa and other local methods through providers such as Paystack
Multi-Currency ✅ Provider-dependent Any 3-letter ISO currency your connected provider supports

Address Handling

Proper billing address information is crucial for payment processing and 3DS authentication. The API supports flexible address formats:

Single String Format (Recommended)

{
    "billing_address": "123 Main Street, New York, NY, 10001, US"
}

Individual Components Format

{
    "address_line": "123 Main Street",
    "city": "New York", 
    "state": "NY",
    "postal_code": "10001",
    "country": "US"
}

Address Requirements

Component Required Description
Street Address Required Full street address including number and street name
City Required City or locality name
State/Province Optional State, province, or administrative area
Postal Code Optional ZIP/postal code (recommended for better approval rates)
Country Required 2-letter ISO country code (US, GB, CA, etc.)
Important: Placeholder values like "N/A" or empty strings will be rejected. Provide complete, accurate address information for best results.

Initialize Payment

Create a new payment transaction. The system selects the payment provider from your account configuration and returns a hosted checkout URL — redirect your customer there to complete payment. No card details are sent to this endpoint.

Endpoint:

POST https://euppay.com/api/v1/payments/initialize

Parameters:

Parameter Type Required Description
order_id string Required Your unique order identifier
amount decimal Required Payment amount (e.g., 100.50)
currency string Required 3-letter currency code (USD, EUR, GBP)
customer_name string Optional Cardholder name
customer_email string Optional Customer email address
billing_address string Required Complete billing address (see Address Handling section)
return_url string Required URL for successful payment redirect
cancel_url string Required URL for cancelled/failed payment redirect

Example Request:

curl -X POST "https://euppay.com/api/v1/payments/initialize" \
    -H "Content-Type: application/json" \
    -H "X-Api-Key: your_api_key" \
    -H "X-Api-Secret: your_api_secret" \
    -d '{
        "order_id": "ORDER123456",
        "amount": 100.50,
        "currency": "USD",
        "customer_name": "John Doe",
        "customer_email": "john.doe@example.com",
        "billing_address": "123 Main Street, New York, NY, 10001, US",
        "return_url": "https://your-website.com/payment/success",
        "cancel_url": "https://your-website.com/payment/cancel"
    }'

Response Types:

1. Redirect Response:

{
    "success": true,
    "action": "redirect",
    "message": "Transaction initialized successfully",
    "redirect_url": "https://checkout.provider.example/pay/abc123def456",
    "transaction_reference": "550e8400-e29b-41d4-a716-446655440000"
}
Send your customer to redirect_url — the provider's hosted checkout page. The customer enters payment details there (never on your site), completes any 3DS challenge, and is returned to your return_url or cancel_url. Always confirm the result with the status endpoint before fulfilling the order.

2. Error Response:

{
    "success": false,
    "message": "Validation failed",
    "errors": {
        "billing_address": ["Street address is required"],
        "currency": ["The currency must be a valid 3-letter code"]
    },
    "error_code": "VALIDATION_ERROR"
}

3D Secure

3D Secure authentication happens on your payment provider's hosted checkout page — not in your integration. When the issuer requires a challenge, the provider renders it as part of the hosted flow after you redirect the customer to redirect_url.

What this means for your integration: there is nothing 3DS-specific to build. Redirect the customer, let the provider handle authentication, and when the customer returns to your return_url confirm the outcome server-side with the status endpoint. A successful response includes "3ds_authenticated": true when the issuer authenticated the cardholder.
Never trust the redirect alone. The customer returning to your return_url is not proof of payment — always verify the transaction status from your server before fulfilling an order.

Check Transaction Status

Retrieve the current status and details of a transaction.

Endpoint:

GET https://euppay.com/api/v1/payments/{reference}/status

Example Request:

curl -X GET "https://euppay.com/api/v1/payments/550e8400-e29b-41d4-a716-446655440000/status" \
    -H "X-Api-Key: your_api_key" \
    -H "X-Api-Secret: your_api_secret"

Response:

{
    "success": true,
    "message": "Transaction status retrieved",
    "data": {
        "reference": "550e8400-e29b-41d4-a716-446655440000",
        "order_id": "ORDER123456",
        "status": "completed",
        "amount": 100.50,
        "currency": "USD",
        "payment_method": "card",
        "card_type": "visa",
        "card_last_four": "1111",
        "customer_email": "john.doe@euppay.com",
        "created_at": "2023-12-01T10:30:00Z",
        "completed_at": "2023-12-01T10:31:45Z",
        "3ds_authenticated": true
    }
}

Transaction Statuses

Status Description Next Steps
initialized Transaction created, pending processing Wait for completion or check again
processing Payment is being processed Wait for completion
completed Payment successfully completed Fulfill order/service
failed Payment failed or was declined Retry with different card or method
cancelled Payment was cancelled by user Offer alternative payment method
refunded Payment has been refunded Update order status accordingly

Refund Transaction

Process a full or partial refund for a completed transaction.

Endpoint:

POST https://euppay.com/api/v1/payments/{reference}/refund

Parameters:

Parameter Type Required Description
amount decimal Optional Refund amount (defaults to full amount)
reason string Optional Reason for refund

Example Request:

curl -X POST "https://euppay.com/api/v1/payments/550e8400-e29b-41d4-a716-446655440000/refund" \
    -H "Content-Type: application/json" \
    -H "X-Api-Key: your_api_key" \
    -H "X-Api-Secret: your_api_secret" \
    -d '{
        "amount": 50.25,
        "reason": "Partial refund - item returned"
    }'

Response:

{
    "success": true,
    "message": "Refund processed successfully",
    "data": {
        "refund_id": "ref_550e8400-e29b-41d4-a716-446655440000",
        "original_reference": "550e8400-e29b-41d4-a716-446655440000",
        "refund_amount": 50.25,
        "currency": "USD",
        "status": "completed",
        "processed_at": "2023-12-01T15:30:00Z"
    }
}

Error Handling

The API uses standard HTTP status codes and provides detailed error information in the response body.

Common Error Codes

HTTP Status Error Code Description
400 BAD_REQUEST Invalid request format or parameters
401 UNAUTHORIZED Invalid or missing API credentials
422 VALIDATION_ERROR Request validation failed
429 RATE_LIMIT_EXCEEDED Too many requests - rate limit exceeded
500 INTERNAL_ERROR Internal server error

3DS Specific Errors

{
    "success": false,
    "message": "Authentication required",
    "error_code": "3DS_AUTH_REQUIRED",
    "details": {
        "reason": "Card authentication required by issuer",
        "recommended_action": "complete_3ds_challenge"
    }
}

Address Validation Errors

{
    "success": false,
    "message": "Address validation failed",
    "error_code": "ADDRESS_VALIDATION_ERROR",
    "errors": {
        "billing_address": [
            "Street address is required",
            "Country must be a valid 2-letter code"
        ]
    }
}

Testing Your Integration

Integrate and test against sandbox credentials first. Sandbox access is available as soon as your account is set up. Going live on card rails is a separate step coordinated with your acquirer.

Sandbox Testing

  • Use the test cards and test credentials published by your payment provider — never real card numbers
  • Exercise the full flow: initialize → redirect to hosted checkout → return → status check
  • Test success, decline, and cancellation outcomes, plus full and partial refunds
  • Verify that your return_url handler confirms the transaction status server-side

Before Going Live

Go-live: enabling live card processing requires your acquirer to approve the gateway connection on your MID — a process measured in weeks that we coordinate with you. Once approved, run a small controlled live pilot before opening full traffic.

Complete Code Examples

Complete PHP Integration

<?php
class PaymentGateway {
    private $apiKey;
    private $apiSecret;
    private $baseUrl;

    public function __construct($apiKey, $apiSecret) {
        $this->apiKey = $apiKey;
        $this->apiSecret = $apiSecret;
        $this->baseUrl = 'https://euppay.com/api/v1';
    }

    public function initializePayment($paymentData) {
        $url = $this->baseUrl . '/payments/initialize';

        $headers = [
            'Content-Type: application/json',
            'X-Api-Key: ' . $this->apiKey,
            'X-Api-Secret: ' . $this->apiSecret
        ];

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($paymentData));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode !== 200) {
            throw new Exception('API request failed with HTTP code: ' . $httpCode);
        }

        return json_decode($response, true);
    }

    public function checkTransactionStatus($reference) {
        $url = $this->baseUrl . '/payments/' . $reference . '/status';

        $headers = [
            'X-Api-Key: ' . $this->apiKey,
            'X-Api-Secret: ' . $this->apiSecret
        ];

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }
}

// Usage: initialize, then redirect the customer to the provider's hosted checkout
try {
    $gateway = new PaymentGateway('your_api_key', 'your_api_secret');

    $paymentData = [
        'order_id' => 'ORDER-' . time(),
        'amount' => 100.50,
        'currency' => 'USD',
        'customer_name' => 'John Doe',
        'customer_email' => 'john.doe@example.com',
        'billing_address' => '123 Main Street, New York, NY, 10001, US',
        'return_url' => 'https://your-website.com/success',
        'cancel_url' => 'https://your-website.com/cancel'
    ];

    $result = $gateway->initializePayment($paymentData);

    if ($result['success'] && ($result['action'] ?? null) === 'redirect') {
        // Send the customer to the provider's hosted checkout page
        header('Location: ' . $result['redirect_url']);
        exit;
    }

    echo 'Payment failed: ' . ($result['message'] ?? 'Unknown error');

} catch (Exception $e) {
    echo 'Error: ' . $e->getMessage();
}

// On your return_url handler: confirm before fulfilling
// $status = $gateway->checkTransactionStatus($_GET['reference'] ?? '');
// if (($status['data']['status'] ?? null) === 'completed') { /* fulfil order */ }
?>
No card form needed. Your site never collects card numbers — the customer enters payment details on the provider's hosted checkout page. Your integration only builds the initialize request, performs the redirect, and confirms the result server-side.

Support and Resources

Need help with your integration? Here are your support options:

Technical Support

Email: hello@gateway.euppay.com

Founder-led support; same-business-day responses on Core plans and above.

Documentation

This guide covers most integration scenarios

See the getting-started documentation