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

# Quick Start

## Integration Overview

Get started with Tabby's Buy Now, Pay Later solution. This guide walks you through integrating Tabby Payments into your website or mobile app, allowing your customers to split purchases into interest-free installments.

## See It In Action

<video controls alt="Tabby demo" className="product-shot w-80" src="https://mintcdn.com/tabby-5f40add6/kcrEXIITvX2nLYrq/images/tabby-demo-0826.mp4?fit=max&auto=format&n=kcrEXIITvX2nLYrq&q=85&s=748b245e05112eba65148b96567abb34" data-path="images/tabby-demo-0826.mp4" />

## Integration Steps

### Setup

<Steps>
  <Step
    stepNumber={1}
    title={(
  <span>
    <a href="https://merchant.tabby.ai/">
      Register for a Tabby merchant account
    </a>
    <span style={{ fontWeight: 'normal', fontSize: '0.9em' }}>
      &nbsp;(KSA: <a href="https://merchant.tabby.sa/">merchant.tabby.sa</a>)
    </span>
    <span style={{ fontWeight: 'normal' }}>
      &nbsp;and complete your application to obtain access to Tabby Merchant Dashboard
    </span>
  </span>
)}
  />

  <Step
    stepNumber={2}
    title={(
  <span style={{ fontWeight: 'normal' }}>
    Retrieve your test API keys and merchant codes from Tabby Merchant Dashboard or your Tabby account manager
  </span>
)}
  />
</Steps>

### Development

<Steps>
  <Step
    stepNumber={3}
    title={(
  <span>
    <span style={{ fontWeight: 'normal' }}>
      Implement checkout integration for your platform:&nbsp;
    </span>
    <a href="/pay-in-4-custom-integration/checkout-flow">
      Web
    </a>
    <span style={{ fontWeight: 'normal' }}>
      &nbsp;or&nbsp;
    </span>
    <a href="/pay-in-4-custom-integration/mobile-apps/sdk-all">
      Mobile
    </a>
  </span>
)}
  />

  <Step
    stepNumber={4}
    title={(
  <span>
    <span style={{ fontWeight: 'normal' }}>
      Integrate&nbsp;
    </span>
    <a href="/pay-in-4-custom-integration/payment-processing">
      Payment Processing
    </a>
    <span style={{ fontWeight: 'normal' }}>
      &nbsp;to handle payment status updates and order fulfillment
    </span>
  </span>
)}
  />

  <Step
    stepNumber={5}
    title={(
  <span>
    <span style={{ fontWeight: 'normal' }}>
      Add&nbsp;
    </span>
    <a href="/pay-in-4-custom-integration/on-site-messaging">
      Tabby Promo snippets and widgets
    </a>
    <span style={{ fontWeight: 'normal' }}>
      &nbsp;to your site (required for optimal conversion)
    </span>
  </span>
)}
  />

  <Step
    stepNumber={6}
    title={(
  <span>
    <a href="/testing-guidelines/testing-credentials">
      Test basic scenarios
    </a>
    <span style={{ fontWeight: 'normal' }}>
      &nbsp;with test credentials, then complete the&nbsp;
    </span>
    <a href="/pay-in-4-custom-integration/full-testing-checklist">
      full testing checklist
    </a>
    <span style={{ fontWeight: 'normal' }}>
      &nbsp;before submitting for Tabby QA review
    </span>
  </span>
)}
  />
</Steps>

#### Your first session, server-side

Create a checkout session from your backend (never from the browser — the request carries your Secret Key), read the HPP link from `configuration.available_products.installments[0].web_url`, and redirect the customer to it. Full payload reference: <a href="/api-reference/checkout/session-payload-model">Session payload model</a>.

<Accordion title="Code examples: cURL · Node.js · Python · PHP · C#">
  <CodeGroup>
    ```bash cURL theme={"dark"}
    curl https://api.tabby.ai/api/v2/checkout \
      -H "Authorization: Bearer sk_test_..." \
      -H "Content-Type: application/json" \
      -d '{
        "payment": {
          "amount": "340.00",
          "currency": "AED",
          "buyer": { "name": "John Doe", "email": "otp.success@tabby.ai", "phone": "+971500000001" },
          "shipping_address": { "city": "Dubai", "address": "Sheikh Zayed Rd", "zip": "00000" },
          "order": {
            "reference_id": "order-1001",
            "items": [{ "title": "Sneakers", "quantity": 1, "unit_price": "340.00", "category": "Shoes" }]
          },
          "buyer_history": { "registered_since": "2024-03-01T00:00:00Z", "loyalty_level": 0 },
          "order_history": []
        },
        "lang": "en",
        "merchant_code": "your_merchant_code",
        "merchant_urls": {
          "success": "https://your-store.com/tabby/success",
          "cancel": "https://your-store.com/tabby/cancel",
          "failure": "https://your-store.com/tabby/failure"
        }
      }'
    ```

    ```javascript Node.js theme={"dark"}
    const res = await fetch('https://api.tabby.ai/api/v2/checkout', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.TABBY_SECRET_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload), // the JSON from the cURL tab
    });
    const session = await res.json();

    if (session.status === 'created') {
      const webUrl = session.configuration.available_products.installments[0]?.web_url;
      if (webUrl) return redirect(webUrl); // save session.payment.id first
    }
    // status "rejected" (or missing web_url): show the rejection message, offer another method
    ```

    ```python Python theme={"dark"}
    import os, requests

    res = requests.post(
        "https://api.tabby.ai/api/v2/checkout",
        headers={"Authorization": f"Bearer {os.environ['TABBY_SECRET_KEY']}"},
        json=payload,  # the JSON from the cURL tab
    )
    session = res.json()

    if session["status"] == "created":
        installments = session["configuration"]["available_products"].get("installments") or []
        web_url = installments[0].get("web_url") if installments else None
        if web_url:
            return redirect(web_url)  # save session["payment"]["id"] first
    # status "rejected" (or missing web_url): show the rejection message
    ```

    ```php PHP theme={"dark"}
    $ch = curl_init('https://api.tabby.ai/api/v2/checkout');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . getenv('TABBY_SECRET_KEY'),
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode($payload), // the JSON from the cURL tab
    ]);
    $session = json_decode(curl_exec($ch), true);

    $webUrl = $session['configuration']['available_products']['installments'][0]['web_url'] ?? null;
    if ($session['status'] === 'created' && $webUrl) {
        header('Location: ' . $webUrl); // save $session['payment']['id'] first
        exit;
    }
    // status "rejected" (or missing web_url): show the rejection message
    ```

    ```csharp C# theme={"dark"}
    using var http = new HttpClient();
    http.DefaultRequestHeaders.Authorization =
        new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("TABBY_SECRET_KEY"));

    var res = await http.PostAsJsonAsync("https://api.tabby.ai/api/v2/checkout", payload); // the JSON from the cURL tab
    var session = await res.Content.ReadFromJsonAsync<JsonElement>();

    var status = session.GetProperty("status").GetString();
    var installments = session.GetProperty("configuration")
        .GetProperty("available_products").TryGetProperty("installments", out var arr) ? arr : default;
    if (status == "created" && installments.ValueKind == JsonValueKind.Array && installments.GetArrayLength() > 0)
    {
        var webUrl = installments[0].GetProperty("web_url").GetString(); // save payment.id first
        return Redirect(webUrl);
    }
    // status "rejected" (or missing web_url): show the rejection message
    ```
  </CodeGroup>
</Accordion>

After the customer returns, verify the payment server-side and capture it — see <a href="/pay-in-4-custom-integration/payment-processing">Payment Processing</a>.

### Going Live

<Steps>
  <Step
    stepNumber={7}
    title={(
  <span style={{ fontWeight: 'normal' }}>
    Submit your integration for Tabby QA review after completing the full testing checklist
  </span>
)}
  />

  <Step
    stepNumber={8}
    title={(
  <span style={{ fontWeight: 'normal' }}>
    After successful QA approval, coordinate your go-live plan and marketing campaign with your Tabby account manager
  </span>
)}
  />

  <Step
    stepNumber={9}
    title={(
  <span style={{ fontWeight: 'normal' }}>
    Request live API keys and deploy to production
  </span>
)}
  />
</Steps>

#### Production cutover checklist

Test-key configuration does **not** carry over to live keys. When switching to production, verify each of these:

* [ ] Swap `sk_test_...` → live `sk_...` on the backend and `pk_test_...` → live `pk_...` in snippets — never expose any `sk_` key client-side.
* [ ] **Re-register webhooks with the live key** — webhooks registered with a test key receive test payments only (see <a href="/pay-in-4-custom-integration/webhooks">Webhooks</a>).
* [ ] Confirm all calls use the base URL matching the merchant's region (<a href="/api-reference/overview#base-urls">Base URLs</a>).
* [ ] Place one real live order end-to-end: session → HPP → `AUTHORIZED` → capture → `closed` webhook received.

## How It Works

Here's what happens when a customer uses Tabby:

1. **Customer chooses Tabby at checkout**\
   Your site checks if the customer is eligible using Tabby's API (background check based on purchase amount and customer details).

2. **Customer completes purchase**\
   If eligible, customer selects Tabby, clicks "Place order", and is redirected to Tabby's secure payment page to complete verification.

3. **You get paid, customer pays in installments**\
   Tabby authorizes the payment immediately. You capture the full amount and fulfill the order. The customer pays Tabby in interest-free installments.

<Note>
  For detailed technical implementation, see the <a href="/pay-in-4-custom-integration/checkout-flow">Checkout Flow Guide</a>.
</Note>

## Complete Integration Flow

This diagram shows the complete end-to-end integration flow including eligibility checks, session creation, payment processing, and all possible outcomes:

```mermaid theme={"dark"}
sequenceDiagram
    autonumber
    participant Customer
    participant Merchant Site
    participant Merchant Backend
    participant Tabby Checkout
    participant Tabby API

    Customer ->>+ Merchant Site: Opens Checkout page
    Merchant Site ->>+ Merchant Backend: Check customer eligibility with Tabby
    Merchant Backend ->>+ Tabby API: POST /api/v2/checkout<br/>{ amount, currency, buyer.phone, buyer.email, merchant_code }
    Tabby API -->>- Merchant Backend: Response<br/>{"status" of session}

    alt "status" of session == "created"
        Merchant Backend -->> Merchant Site: Customer is eligible
        Merchant Site -->> Customer: Show Tabby on Checkout
        Note right of Customer: Customer can select Tabby payment

        Customer ->>+ Merchant Site: Selects Tabby & clicks Place Order
        Merchant Site ->>+ Merchant Backend: Create Tabby payment session
        Note over Merchant Backend,Tabby API: New session is created (not eligibility check)

        Merchant Backend ->>+ Tabby API: POST /api/v2/checkout<br/>{ all required attributes }
        Tabby API -->>- Merchant Backend: Response<br/>{"payment.id", "web_url"}

        Merchant Backend ->>+ Tabby Checkout: Redirect to Tabby Checkout
        loop Tabby Checkout steps
            Tabby Checkout -->> Customer: Guide through payment steps
        end

    else "status" of session == "rejected"
        Merchant Backend -->> Merchant Site: Customer is not eligible
        Merchant Site -->> Customer: Hide Tabby on Checkout
    end
    alt Customer is redirected back to Merchant Site

        Tabby Checkout ->> Merchant Site: Redirect via success/cancel/failure url
        Merchant Site ->> Customer: Show success/cancel/failure screen and message
        Note right of Customer: If payment is unsuccessful, customer can retry <br/>or select a different payment method
        Merchant Backend ->>+ Tabby API: GET /api/v2/payments/{payment.id}
        Tabby API -->>- Merchant Backend: { "status" of the payment }

    else Customer is not redirected
        Note over Tabby API,Merchant Backend: Tabby sends payment status<br/>via webhook or merchant checks it via API
        Tabby API -->>+ Merchant Backend: POST webhook <br />{ "id" of the payment, "status" of the payment }
        Merchant Backend ->>+ Tabby API: GET /api/v2/payments/{payment.id}
        Tabby API -->>- Merchant Backend: { "status" of the payment }

    end

Note over Merchant Backend: Always verify payment status via Tabby API<br/>Do not rely on redirect URL or query params alone
    alt payment.status == "AUTHORIZED"
        Merchant Backend ->>+ Merchant Site: Create order in backend
        Merchant Backend -->> Tabby API: POST /api/v2/payments/{payment.id}/captures<br/>{ amount, reference_id}
    else payment.status == "CLOSED"
        Merchant Backend ->>+ Merchant Site: Create order in backend<br/>(payment already captured — no capture call)
    else payment.status == "REJECTED" or "EXPIRED"
        Merchant Backend -->> Merchant Site: Payment failed/cancelled
    end
```

## Next Steps

Beyond the flow covered above:

* <a href="/pay-in-4-custom-integration/payment-statuses">Payment statuses reference</a>
* <a href="/api-reference/payments/refund-a-payment">Refunds and cancellations</a>
* <a href="/pay-in-4-custom-integration/disputes">Disputes handling</a>
* <a href="/introduction/faq">FAQ</a> for common implementation questions
* <a href="/marketing/toolkit">Marketing toolkit</a> with guidelines and assets for every channel

## Need Help?

**Integration support:**\
Contact your assigned Business Manager or Integrations Team via your integration email thread.

**Technical or API questions:**\
Email `partner@tabby.ai` / `partner@tabby.sa` or use Partner Support in Tabby Business App.

**Direct your customers to:**\
Customer Support in Tabby App or `help@tabby.ai` / `help@tabby.sa`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.