Skip to content
Last updated

Tutorial: White-label payment solution

What you will build

A reseller platform that:

  1. Creates merchant accounts under your reseller client
  2. Configures processor integrations for each merchant
  3. Processes payments on behalf of merchants
  4. Reports on transactions across your merchant portfolio

Architecture

Your Platform
type: reseller

Merchant A
type: merchant

Merchant B
type: merchant

Merchant C
type: merchant

Users / API keys

Integrations
TSYS, Vericheck

Transactions

Users / API keys

Integrations

Transactions

Your Platform
type: reseller

Merchant A
type: merchant

Merchant B
type: merchant

Merchant C
type: merchant

Users / API keys

Integrations
TSYS, Vericheck

Transactions

Users / API keys

Integrations

Transactions

Key concepts

ConceptDescription
Reseller clientYour platform's account — the parent for all merchants you onboard
Merchant clientEach merchant account, created as a child of your reseller
Merchant API keyEach merchant gets their own API key for transaction processing
Parent visibilityResellers can view and manage all child merchants and their data

For details on the account model, see Clients and resellers.

Prerequisites

  • A reseller-type client account with Paradise Gateway
  • Your reseller API key — see Obtain API credentials
  • Processor credentials (TSYS Merchant ID, Vericheck details) for each merchant

Step 1: Onboard a new merchant

Create a merchant client under your reseller account.

import requests, os

RESELLER_API_KEY = os.environ["PARADISE_RESELLER_API_KEY"]
BASE = os.environ.get("PARADISE_BASE_URL", "https://api.dev.paradisegateway.net")
HEADERS = {"Content-Type": "application/json", "APIKEY": RESELLER_API_KEY}

def create_merchant(dba: str, parent_id: str, contact: dict) -> dict:
    resp = requests.post(f"{BASE}/v1/clients", headers=HEADERS, json={
        "dba": dba,
        "parent_id": parent_id,
        "type": "merchant",
        "admin_contact_details": {
            "first_name": contact["first_name"],
            "last_name": contact["last_name"],
            "email": contact["email"],
            "phone": contact.get("phone", ""),
            "time_zone": contact.get("time_zone", "America/New_York"),
        },
    })
    resp.raise_for_status()
    return resp.json()

Step 2: Create a merchant user and API key

Each merchant needs at least one user account, then an API key for processing.

import base64

def create_merchant_user(client_id: str, user_data: dict) -> dict:
    resp = requests.post(f"{BASE}/v1/users", headers=HEADERS, json={
        "client_id": client_id,
        "first_name": user_data["first_name"],
        "last_name": user_data["last_name"],
        "email": user_data["email"],
        "password": user_data["password"],
        "time_zone": user_data.get("time_zone", "America/New_York"),
    })
    resp.raise_for_status()
    return resp.json()

def get_merchant_api_key(email: str, password: str) -> str:
    credentials = base64.b64encode(f"{email}:{password}".encode()).decode()
    resp = requests.post(
        f"{BASE}/v1/auth/keys",
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Basic {credentials}",
        },
    )
    resp.raise_for_status()
    return resp.json()["key"]
Store credentials securely

Store each merchant's API key in your secrets manager — never in your database in plain text. See Secure API keys.

Step 3: Configure processor integration

Add a TSYS integration so the merchant can process card transactions.

def add_tsys_integration(merchant_api_key: str, config: dict) -> dict:
    merchant_headers = {"Content-Type": "application/json", "APIKEY": merchant_api_key}
    resp = requests.post(f"{BASE}/v1/integrations", headers=merchant_headers, json={
        "name": "tsys",
        "is_active": True,
        "configuration": {
            "mid": config["mid"],
            "tid": config["tid"],
            "industry_type": config.get("industry_type", "e_commerce"),
            "settlement_time": config.get("settlement_time", "23:59:00"),
        },
    })
    resp.raise_for_status()
    return resp.json()

Step 4: Process payments on behalf of merchants

Use the merchant's API key (not the reseller key) for transaction processing.

def process_merchant_payment(merchant_api_key: str, amount: int, card: dict) -> dict:
    merchant_headers = {"Content-Type": "application/json", "APIKEY": merchant_api_key}
    resp = requests.post(f"{BASE}/v1/transactions", headers=merchant_headers, json={
        "type": "card_sale",
        "amount": amount,
        "card": {
            "pan": card["pan"],
            "expiry_month": card["expiry_month"],
            "expiry_year": card["expiry_year"],
            "cvv": card["cvv"],
            "cardholder_name": card["name"],
        },
    })
    resp.raise_for_status()
    return resp.json()

Step 5: Portfolio reporting

As a reseller, query transactions and merchants across your portfolio.

def list_merchants() -> list:
    resp = requests.get(f"{BASE}/v1/clients", headers=HEADERS)
    resp.raise_for_status()
    return resp.json()["data"]

def list_merchant_transactions(merchant_api_key: str, skip: int = 0, take: int = 50) -> dict:
    merchant_headers = {"Content-Type": "application/json", "APIKEY": merchant_api_key}
    resp = requests.get(
        f"{BASE}/v1/transactions?skip={skip}&take={take}",
        headers=merchant_headers,
    )
    resp.raise_for_status()
    return resp.json()

Complete onboarding flow

Paradise GatewayYour PlatformParadise GatewayYour PlatformMerchant is ready to processPOST /v1/clients (create merchant)client_idPOST /v1/users (create merchant user)user_idPOST /v1/auth/keys (Basic Auth)merchant_api_keyPOST /v1/integrations (TSYS config)integration_id
Paradise GatewayYour PlatformParadise GatewayYour PlatformMerchant is ready to processPOST /v1/clients (create merchant)client_idPOST /v1/users (create merchant user)user_idPOST /v1/auth/keys (Basic Auth)merchant_api_keyPOST /v1/integrations (TSYS config)integration_id

Best practices

  • Automate onboarding — script the full create-client → create-user → get-key → add-integration flow.
  • Separate API keys per merchant — never share keys across merchants.
  • Store keys in a secrets manager — not in your database in plaintext.
  • Use reseller key for management, merchant key for transactions — this enforces proper data isolation.
  • Monitor across your portfolio — track approval rates and error rates per merchant to identify issues early.

Next steps