> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gosurge.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Server Integration

> Learn how to initialize a Surge checkout session from your backend and register as a merchant.

## Merchant Registration

Before integrating, you need a Surge merchant account. You can register via the dashboard or the API.

### Via Dashboard (Recommended)

Sign up at [merchant.gosurge.xyz/register](https://merchant.gosurge.xyz/register). Once approved, log in to find your **Merchant ID** under **Settings → API Keys**.

<Steps>
  <Step title="Register">
    Go to [merchant.gosurge.xyz/register](https://merchant.gosurge.xyz/register) and fill in your business details.
  </Step>

  <Step title="Wait for approval">
    New accounts are reviewed within 24 hours. You'll receive an email when approved.
  </Step>

  <Step title="Generate your API key">
    Once approved, the Surge team enables API access for your account. Log in to the merchant dashboard, go to **Settings → API Keys**, and click **Generate API Key**. Copy the key immediately — it is only shown once. Your **Merchant ID** (`mer_...`) is shown on the same page.
  </Step>
</Steps>

<Tip>
  Store your credentials as environment variables (`SURGE_API_KEY`, `SURGE_MERCHANT_ID`) and never commit them to version control.
</Tip>

### Via API

```bash theme={null}
POST /api/v1/auth/merchant/register
```

**Request**

```json theme={null}
{
  "email": "you@yourstore.com",
  "password": "your-password",
  "business_name": "Your Store Name",
  "business_url": "https://yourstore.com"
}
```

**Response**

```json theme={null}
{
  "ok": true,
  "data": {
    "merchantId": "mer_998877",
    "status": "pending",
    "email": "you@yourstore.com"
  }
}
```

<Note>
  New merchant accounts require approval before they can create live checkout sessions. You will be notified by email once your account is activated.
</Note>

***

## Creating a Checkout Session

Before rendering the checkout widget, your backend must initialize a transaction by creating a **Checkout Session**. This session is short-lived (30 minutes) and secures the transaction details server-side.

### Endpoint

`POST /api/v1/checkout/sessions`

### Authentication

Authenticate with your API key on every request:

```bash theme={null}
Authorization: Bearer surge_live_sk_...
```

### Request Headers

| Header            | Required    | Description                                                 |
| :---------------- | :---------- | :---------------------------------------------------------- |
| `Authorization`   | ✅           | `Bearer surge_live_sk_...` (your Surge API key)             |
| `Idempotency-Key` | Recommended | A UUID v4 to prevent duplicate sessions on network retries. |

### Payload Parameters

| Field             | Type      | Description                                           |
| :---------------- | :-------- | :---------------------------------------------------- |
| `merchant_id`     | `string`  | Your merchant ID from the dashboard.                  |
| `amount`          | `integer` | Total amount in kobo (e.g., `120000` for ₦1,200.00).  |
| `currency`        | `string`  | ISO 4217 currency code (e.g., `NGN`).                 |
| `title`           | `string`  | Product or order name shown in the widget.            |
| `order_reference` | `string`  | Your internal unique reference for this order.        |
| `customer_email`  | `string`  | (Optional) Pre-fills the login form for the customer. |

### Request Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.gosurge.xyz/api/v1/checkout/sessions \
    -H "Authorization: Bearer surge_live_sk_..." \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
    -d '{
      "merchant_id": "mer_998877",
      "amount": 120000,
      "currency": "NGN",
      "title": "Apple AirPods Pro",
      "order_reference": "ORD-9912384",
      "customer_email": "customer@example.com"
    }'
  ```

  ```javascript Node.js theme={null}
  const { v4: uuidv4 } = require('uuid');

  async function createSurgeCheckoutSession({ amount, title, orderReference, customerEmail }) {
    const response = await fetch('https://api.gosurge.xyz/api/v1/checkout/sessions', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.SURGE_API_KEY}`,
        'Content-Type': 'application/json',
        'Idempotency-Key': uuidv4(),
      },
      body: JSON.stringify({
        merchant_id: process.env.SURGE_MERCHANT_ID,
        amount,        // in kobo — e.g. 120000 = ₦1,200.00
        currency: 'NGN',
        title,
        order_reference: orderReference,
        customer_email: customerEmail,
      }),
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail ?? `Surge API error: ${response.status}`);
    }

    const { data } = await response.json();
    return data.session_token; // pass this to your frontend
  }
  ```

  ```python Python theme={null}
  import os
  import uuid
  import httpx  # or use requests

  async def create_surge_checkout_session(amount: int, title: str, order_reference: str, customer_email: str = None) -> str:
      async with httpx.AsyncClient() as client:
          response = await client.post(
              'https://api.gosurge.xyz/api/v1/checkout/sessions',
              headers={
                  'Authorization': f'Bearer {os.environ["SURGE_API_KEY"]}',
                  'Content-Type': 'application/json',
                  'Idempotency-Key': str(uuid.uuid4()),
              },
              json={
                  'merchant_id': os.environ['SURGE_MERCHANT_ID'],
                  'amount': amount,  # in kobo
                  'currency': 'NGN',
                  'title': title,
                  'order_reference': order_reference,
                  'customer_email': customer_email,
              }
          )
          response.raise_for_status()
          return response.json()['data']['session_token']
  ```
</CodeGroup>

### Response — Success

```json theme={null}
{
  "ok": true,
  "data": {
    "session_token": "fcs_7a2b9d1e...",
    "expires_at": "2026-03-11T13:00:00Z"
  }
}
```

### Error Responses

| Status            | Reason                                            |
| :---------------- | :------------------------------------------------ |
| `404 Not Found`   | The `merchant_id` does not exist in our system.   |
| `403 Forbidden`   | The merchant account is not currently active.     |
| `400 Bad Request` | The `Idempotency-Key` header is not a valid UUID. |

<Tip>
  Store the `session_token` returned from this request and pass it to the Frontend SDK in the next step.
</Tip>

***

## Previewing a Payment Plan

Before completing checkout, you can preview what the installment schedule will look like for a given amount and plan configuration. This is useful for showing customers a breakdown before they confirm.

### Endpoint

`POST /api/v1/checkout/preview`

### Request

```json theme={null}
{
  "merchant_id": "mer_998877",
  "customer_id": "cust_xyz",
  "amount": 120000,
  "schedule_type": "monthly",
  "installment_count": 3
}
```

### Response

```json theme={null}
{
  "ok": true,
  "data": {
    "schedule_type": "monthly",
    "installment_count": 3,
    "deposit_amount": 40000,
    "installment_amounts": [40000, 40000, 40000],
    "due_dates": ["2026-04-01", "2026-05-01", "2026-06-01"],
    "total_amount": 120000
  }
}
```

***

## Idempotency

The `POST /checkout/sessions` endpoint supports the `Idempotency-Key` header to protect against duplicate requests caused by network timeouts, client retries, or double-clicks.

### How it works

1. Generate a **UUID v4** and attach it as the `Idempotency-Key` header on your request.
2. If your request times out or fails at the network layer, **re-send the exact same request** with the same `Idempotency-Key`.
3. Surge will return the **original session** — no duplicate session or double-charge will occur.
4. Keys expire after **24 hours**. After expiry, the same key will create a fresh session.

```javascript theme={null}
const { v4: uuidv4 } = require('uuid');

const idempotencyKey = uuidv4(); // e.g. "550e8400-e29b-41d4-a716-446655440000"

// First attempt (or any retry) — safe to call multiple times
const response = await fetch('https://api.gosurge.xyz/api/v1/checkout/sessions', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.SURGE_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': idempotencyKey,
  },
  body: JSON.stringify({
    merchant_id: 'mer_998877',
    amount: 120000,
    currency: 'NGN',
    title: 'Apple AirPods Pro',
    order_reference: 'ORD-9912384',
  }),
});
```

<Warning>
  Generate a **new** UUID for each distinct order. Reusing the same key for a different order will return the original session, not a new one.
</Warning>

***

## Payment Links

Payment links are reusable, shareable URLs that let customers check out without needing a server-side session. Ideal for sharing via WhatsApp, Instagram, or email.

### Create a Payment Link

```bash theme={null}
POST /api/v1/payment-links
Authorization: Bearer surge_live_sk_...
```

**Request**

```json theme={null}
{
  "merchant_id": "mer_998877",
  "title": "Nike Air Max 270",
  "amount": 85000,
  "currency": "NGN",
  "description": "Limited edition — sizes 40–45 available.",
  "redirect_url": "https://yourstore.com/thank-you"
}
```

**Response**

```json theme={null}
{
  "ok": true,
  "data": {
    "id": "pl_abc123",
    "slug": "aX8kP2mQ",
    "publicUrl": "https://consumer.gosurge.xyz/l/aX8kP2mQ",
    "merchantId": "mer_998877",
    "title": "Nike Air Max 270",
    "amount": { "amount": 85000, "currency": "NGN" },
    "redirectUrl": "https://yourstore.com/thank-you",
    "isActive": true,
    "createdAt": "2026-05-01T10:00:00Z",
    "updatedAt": "2026-05-01T10:00:00Z"
  }
}
```

<Note>
  All fields in the payment link response use **camelCase** (`redirectUrl`, `isActive`, `createdAt`, `merchantId`, `publicUrl`). The response schema uses Pydantic's `alias_generator=to_camel`.
</Note>

If `redirectUrl` is set, the customer is redirected there after a successful checkout instead of their Surge dashboard.

### List Your Payment Links

```bash theme={null}
GET /api/v1/payment-links/merchant/{merchant_id}
Authorization: Bearer surge_live_sk_...
```

### Toggle a Link On/Off

```bash theme={null}
PATCH /api/v1/payment-links/{id}/toggle
Authorization: Bearer surge_live_sk_...
Content-Type: application/json

{ "is_active": false }
```
