# 

## 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

```mermaid
flowchart TD
    A[Your Platform<br/>type: reseller] --> B[Merchant A<br/>type: merchant]
    A --> C[Merchant B<br/>type: merchant]
    A --> D[Merchant C<br/>type: merchant]
    B --> E[Users / API keys]
    B --> F[Integrations<br/>TSYS, Vericheck]
    B --> G[Transactions]
    C --> H[Users / API keys]
    C --> I[Integrations]
    C --> J[Transactions]
```

### Key concepts

| Concept | Description |
|  --- | --- |
| **Reseller client** | Your platform's account — the parent for all merchants you onboard |
| **Merchant client** | Each merchant account, created as a child of your reseller |
| **Merchant API key** | Each merchant gets their own API key for transaction processing |
| **Parent visibility** | Resellers can view and manage all child merchants and their data |


For details on the account model, see [Clients and resellers](/docs/concepts/account-hierarchy/clients-and-resellers).

## Prerequisites

* A reseller-type client account with Paradise Gateway
* Your reseller API key — see [Obtain API credentials](/docs/how-tos/setup/obtain-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.

Python
```python
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()
```

JavaScript
```javascript
const RESELLER_API_KEY = process.env.PARADISE_RESELLER_API_KEY;
const BASE = process.env.PARADISE_BASE_URL || "https://api.dev.paradisegateway.net";
const headers = { "Content-Type": "application/json", "APIKEY": RESELLER_API_KEY };

async function createMerchant(dba, parentId, contact) {
  const resp = await fetch(`${BASE}/v1/clients`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      dba,
      parent_id: parentId,
      type: "merchant",
      admin_contact_details: {
        first_name: contact.firstName,
        last_name: contact.lastName,
        email: contact.email,
        phone: contact.phone || "",
        time_zone: contact.timeZone || "America/New_York",
      },
    }),
  });
  if (!resp.ok) throw new Error(`Create merchant failed: ${resp.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.

Python
```python
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"]
```

JavaScript
```javascript
async function createMerchantUser(clientId, userData) {
  const resp = await fetch(`${BASE}/v1/users`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      client_id: clientId,
      first_name: userData.firstName,
      last_name: userData.lastName,
      email: userData.email,
      password: userData.password,
      time_zone: userData.timeZone || "America/New_York",
    }),
  });
  if (!resp.ok) throw new Error(`Create user failed: ${resp.status}`);
  return resp.json();
}

async function getMerchantApiKey(email, password) {
  const credentials = btoa(`${email}:${password}`);
  const resp = await fetch(`${BASE}/v1/auth/keys`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Basic ${credentials}`,
    },
  });
  if (!resp.ok) throw new Error(`Get API key failed: ${resp.status}`);
  const body = await resp.json();
  return body.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](/docs/tutorials/security/secure-api-keys).

## Step 3: Configure processor integration

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

Python
```python
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()
```

JavaScript
```javascript
async function addTsysIntegration(merchantApiKey, config) {
  const resp = await fetch(`${BASE}/v1/integrations`, {
    method: "POST",
    headers: { "Content-Type": "application/json", "APIKEY": merchantApiKey },
    body: JSON.stringify({
      name: "tsys",
      is_active: true,
      configuration: {
        mid: config.mid,
        tid: config.tid,
        industry_type: config.industryType || "e_commerce",
        settlement_time: config.settlementTime || "23:59:00",
      },
    }),
  });
  if (!resp.ok) throw new Error(`Add integration failed: ${resp.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.

```python
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.

```python
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

```mermaid
---
config:
  theme: 'neutral'
---
sequenceDiagram
    participant Platform as Your Platform
    participant PG as Paradise Gateway
    Platform->>PG: POST /v1/clients (create merchant)
    PG-->>Platform: client_id
    Platform->>PG: POST /v1/users (create merchant user)
    PG-->>Platform: user_id
    Platform->>PG: POST /v1/auth/keys (Basic Auth)
    PG-->>Platform: merchant_api_key
    Platform->>PG: POST /v1/integrations (TSYS config)
    PG-->>Platform: integration_id
    Note over Platform: Merchant is ready to process
```

## 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

* [Onboard a new client](/docs/how-tos/clients-users/onboard-client)
* [Add an integration](/docs/how-tos/integrations/add-integration)
* [Client reports](/docs/how-tos/reports/client-reports)
* [Users and roles](/docs/concepts/account-hierarchy/users-and-roles)