Table of contents

Troubleshooting

Precium API Troubleshooting Guide

Solutions to common integration issues and debugging techniques.

Quick Diagnostics

API Health Check

BASH

curl -X GET "https://gate.reviopay.com/api/v1/clients/" \
  -H "Authorization: Bearer YOUR_API_KEY"

|Response|Meaning|Action| |---|---|---| |`200` with results|API working|Integration issue| |`401 Unauthorized`|Invalid API key|Check credentials| |`500 Server Error`|Platform issue|Contact support| |Connection refused|Network issue|Check connectivity|

Authentication Issues

Problem: 401 Unauthorized

Symptoms:

JSON

{
  "__all__": {
    "message": "Invalid or expired authentication token",
    "code": "invalid_token"
  }
}

Common Causes:

  1. Incorrect API Key

BASH

    # Wrong
    -H "Authorization: your_api_key"

    # Correct
    -H "Authorization: Bearer your_api_key"

  1. Environment Mismatch
  • Using the sandbox key in production
  • Using the production key in the sandbox
  1. Revoked Key
  • The key was regenerated in the dashboard
  • The key was disabled

Resolution:

  1. Verify key format includes "Bearer " prefix
  2. Check that the key in the dashboard matches the configuration
  3. Generate a new key if necessary
  4. Ensure the environment matches

Problem: Missing Authorization Header

Symptoms:

JSON

{
  "__all__": {
    "message": "Authorization header is required",
    "code": "missing_authorization"
  }
}

Resolution:

Ensure every request includes the header:

PYTHON

headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json"
}

Purchase Creation Issues

Problem: Invalid brand_id

Symptoms:

JSON

{
  "brand_id": {
    "message": "Invalid pk \"xxx\" - object does not exist",
    "code": "does_not_exist"
  }
}

Causes:

  • Incorrect brand ID
  • Brand ID from a different environment
  • Typo in UUID

Resolution:

  1. Copy brand_id directly from the dashboard
  2. Verify format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  3. Ensure the use of the correct environment's brand

Problem: checkout_url Not Generated

Symptoms:

  • checkout_url is null in response
  • direct_post_url is null

Causes:

  • Missing success_redirect or failure_redirect
  • purchase.request_client_details is not empty
  • Purchase is not in a payable state

Resolution:

Include redirect URLs:

JSON

{
  "success_redirect": "https://yoursite.com/success",
  "failure_redirect": "https://yoursite.com/failure",
  ...
}

Problem: Total Amount Mismatch

Symptoms:

  • Calculated total doesn't match expected
  • Checkout shows the wrong amount

Diagnosis:

PYTHON

# Check how total is calculated
total = sum(
    product['price'] * int(product.get('quantity', '1'))
    for product in products
)

Common Issues:

  • Quantity is a string, not applied correctly
  • Discount/tax calculations
  • Override fields not set properly

Resolution:

JSON

{
  "products": [
    {"name": "Item", "price": 5000, "quantity": "2"}  // quantity is STRING
  ],
  "total_override": null  // Don't set unless intentional
}

Payment Processing Issues

Problem: Card Declined

Symptoms:

  • Payment fails at checkout
  • Error message: "Card declined"

Possible Causes:

|Decline Reason|Meaning|Solution| |---|---|---| |`do_not_honour`|Generic decline|Try different card| |`insufficient_funds`|Not enough balance|Use different card| |`expired_card`|Card expired|Use valid card| |`invalid_card`|Card number invalid|Check digits| |`suspected_fraud`|Fraud detection|Contact bank|

Debugging:

BASH

# Check purchase for detailed error
GET /purchases/{id}/

# Response includes:
{
  "status": "failed",
  "payment_failure_reason": "do_not_honour"
}

Problem: 3DS Authentication Failed

Symptoms:

  • Customer fails 3D Secure challenge
  • Redirect to failure URL
  • Error: 3ds_authentication_failed

Causes:

  • The customer entered the wrong OTP/password
  • 3DS timeout
  • Customer cancelled
  • Browser pop-up blocked

Resolution:

  1. The customer should retry with the correct credentials
  2. Ensure pop-ups are not blocked
  3. Verify redirect URLs load quickly
  4. Check browser compatibility

Problem: Payment Stuck in Pending

Symptoms:

  • Status remains pending indefinitely
  • No success/failure redirect

Diagnosis:

BASH

# Check current status
GET /purchases/{id}/

# Response
{
  "status": "pending",
  "events": [...],  // Check for processing events
  "payment_method_details": {...}
}

Causes:

  • 3DS flow not completed
  • Customer abandoned payment
  • Processing delay

Resolution:

  1. Wait for processing (usually < 60 seconds)
  2. Check if the customer completed 3DS
  3. Set up webhooks for async notification
  4. For extended pending, contact support

Webhook Issues

Problem: Webhooks Not Received

Checklist:

  • Webhook URL is HTTPS
  • URL is publicly accessible
  • Firewall allows Precium IPs
  • Server responds within 5 seconds
  • Events are subscribed to

Debug Steps:

  1. Verify webhook configuration:

BASH

GET /webhooks/

# Check your endpoints are listed

  1. Test URL accessibility:

BASH

curl -X POST "https://yoursite.com/webhooks/precium" \
  -H "Content-Type: application/json" \
  -d '{"test": true}'

  1. Check server logs for incoming requests
  2. Verify the SSL certificate is valid

Problem: Webhook Signature Invalid

Symptoms:

  • Signature verification fails
  • Events appear legitimate, but don't validate

Debug:

PYTHON

import hmac
import hashlib

def debug_signature(payload, received_sig, secret):
    calculated = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()

    print(f"Received:   {received_sig}")
    print(f"Calculated: {calculated}")
    print(f"Match: {received_sig == calculated}")

    return received_sig == calculated

Common Issues:

  1. Payload modification: Use raw request body

PYTHON

    # Wrong - parsed JSON
    payload = json.dumps(request.json)

    # Correct - raw body
    payload = request.get_data(as_text=True)

  1. Encoding issues: Ensure UTF-8
  2. Wrong secret: Verify the secret from the dashboard

Problem: Duplicate Webhook Events

Cause: Webhook retry on non-200 response

Resolution:

PYTHON

# Implement idempotency
processed_events = set()

def handle_webhook(event):
    event_id = event.get('id')

    if event_id in processed_events:
        return  # Already processed

    processed_events.add(event_id)
    # Process event...

Best Practice: Store event IDs in the database:

SQL

CREATE TABLE webhook_events (
    event_id VARCHAR(50) PRIMARY KEY,
    event_type VARCHAR(50),
    processed_at TIMESTAMP DEFAULT NOW()
);

Recurring Payment Issues

Problem: Token Not Created

Symptoms:

  • force_recurring: true set but no token
  • Empty token list for client

Causes:

  • Payment not completed
  • The payment amount was 0 without skip_capture
  • Token creation is disabled for the payment method

Debug:

BASH

# Check if payment completed
GET /purchases/{id}/

# Verify status is "paid" or "hold"

# List client tokens
GET /clients/{client_id}/recurring_tokens/

Resolution:

For zero-amount tokenization:

JSON

{
  "purchase": {
    "products": [{"name": "Auth", "price": 0}]
  },
  "skip_capture": true,
  "force_recurring": true
}

Problem: Token Charge Failed

Symptoms:

  • /charge/ endpoint returns error
  • Token exists, but won't charge

Error Types:

|Error|Cause|Solution| |---|---|---| |`recurring_token_not_found`|Invalid token ID|Verify token exists| |`recurring_token_expired`|Card expired|Re-tokenize| |`card_declined`|Insufficient funds|Contact customer|

Debug:

BASH

# Verify token exists
GET /clients/{client_id}/recurring_tokens/{token_id}/

# Check original purchase
GET /purchases/{token_id}/

Direct Post Issues

Problem: direct_post_url is null

Causes:

  • Missing redirect URLs
  • purchase.request_client_details not empty
  • Purchase not in created state

Resolution:

JSON

{
  "success_redirect": "https://...",  // Required
  "failure_redirect": "https://...",  // Required
  "purchase": {
    "request_client_details": []  // Must be empty
  }
}

Problem: Direct Post Returns to Failure

Symptoms:

  • Valid card details
  • Redirect to failure URL

Debug Checklist:

  • Form fields match expected names exactly
  • Card number has no spaces
  • Expiry format is MM/YY
  • CVC is 3-4 digits
  • Cardholder name uses Latin characters only

Field Requirements:

HTML

<!-- Exact field names required -->
<input name="cardholder_name">  <!-- Latin, max 30 chars -->
<input name="card_number">       <!-- Digits only, max 19 -->
<input name="expires">           <!-- MM/YY format -->
<input name="cvc">               <!-- 3-4 digits -->
<input name="pm" value="visa">   <!-- Payment method -->

Performance Issues

Problem: Slow API Responses

Diagnosis:

PYTHON

import time

start = time.time()
response = requests.get(url, headers=headers)
elapsed = time.time() - start
print(f"Response time: {elapsed:.2f}s")

Causes:

  • Network latency
  • Large response payloads
  • Server load

Resolution:

  1. Implement connection pooling
  2. Use pagination for list endpoints
  3. Cache responses where appropriate
  4. Implement timeout handling

Problem: Rate Limit Exceeded

Symptoms:

JSON

HTTP 429 Too Many Requests

Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1619740860

Resolution:

PYTHON

import time

def api_request_with_backoff(func, max_retries=3):
    for attempt in range(max_retries):
        response = func()

        if response.status_code == 429:
            reset_time = int(response.headers.get('X-RateLimit-Reset', 0))
            wait = max(reset_time - time.time(), 2 ** attempt)
            print(f"Rate limited. Waiting {wait:.0f}s...")
            time.sleep(wait)
            continue

        return response

    raise Exception("Rate limit exceeded after retries")

Debugging Tools

Request Logging

PYTHON

import logging

logging.basicConfig(level=logging.DEBUG)

# Log all requests
import http.client
http.client.HTTPConnection.debuglevel = 1

Response Inspection

PYTHON

def debug_response(response):
    print(f"Status: {response.status_code}")
    print(f"Headers: {dict(response.headers)}")
    print(f"Body: {response.text}")

cURL Verbose Mode

BASH

curl -v -X POST "https://gate.reviopay.com/api/v1/purchases/" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"..."}'

Error Message Reference

|Error|HTTP|Quick Fix| |---|---|---| |`invalid_token`|401|Check API key format| |`required`|400|Add missing field| |`does_not_exist`|404|Verify UUID| |`duplicate_client`|409|Search existing client| |`purchase_already_paid`|409|Check status first| |`recurring_token_expired`|409|Re-tokenize card| |`rate_limit_exceeded`|429|Implement backoff|

Getting Support

Before Contacting Support

  1. Collect information:
  • Request ID (if available)
  • Full error response
  • Request payload (sanitized)
  • Timestamp of issue
  1. Check dashboard:
  • Transaction history
  • Webhook logs
  • Event logs
  1. Review documentation:
  • API reference
  • Error codes guide

Contact Support

Email: support@precium.com

Include:

  • Merchant ID / Brand ID
  • Environment (Sandbox/Production)
  • Purchase ID(s) affected
  • Steps to reproduce
  • Error messages
  • Timestamps