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

# Quickstart

> Take a test payment end to end: create it, pay it in the sandbox, and receive the webhook.

**1. Get your sandbox key**

Email [support@flipeet.io](mailto:support@flipeet.io) from your business account's email address and ask for sandbox access. We send you a sandbox key, which starts with `fpay_test_`, and a sandbox webhook signing secret. Store both somewhere safe.

```bash theme={null}
export FLIPEET_SECRET_KEY="fpay_test_…"
```

> [!WARNING]
>
> Keep secret keys on your server. Never put one in a mobile app, a browser or a public repository.

**2. Create a payment**

Ask for ₦25,000. You get back a `checkoutUrl` to send your customer to, and a `txRef` that identifies the payment.

```bash cURL theme={null}
curl -X POST "https://api.pay.flipeet.io/api/v1/transaction/initialize" \
  -H "x-api-key: $FLIPEET_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": 25000,
  "currency": "NGN",
  "email": "ada@example.com",
  "reference": "order_1042",
  "redirectUrl": "https://shop.example.com/thanks"
}'
```

```javascript Node.js theme={null}
const response = await fetch("https://api.pay.flipeet.io/api/v1/transaction/initialize", {
  method: "POST",
  headers: {
    "x-api-key": process.env.FLIPEET_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "amount": 25000,
    "currency": "NGN",
    "email": "ada@example.com",
    "reference": "order_1042",
    "redirectUrl": "https://shop.example.com/thanks"
  }),
});
const { data } = await response.json();
```

```python Python theme={null}
import os
import requests

response = requests.post(
    "https://api.pay.flipeet.io/api/v1/transaction/initialize",
    headers={"x-api-key": os.environ["FLIPEET_SECRET_KEY"]},
    json={
        "amount": 25000,
        "currency": "NGN",
        "email": "ada@example.com",
        "reference": "order_1042",
        "redirectUrl": "https://shop.example.com/thanks"
    },
)
data = response.json()["data"]
```

```json Response theme={null}
{
  "message": "Transaction initialized successfully",
  "status": "success",
  "statusCode": 201,
  "data": {
    "amount": 25000,
    "currency": "NGN",
    "checkoutUrl": "https://pay.flipeet.io/checkout?ref=fp_8f2k3m",
    "payerEmail": "ada@example.com",
    "mode": "sandbox",
    "reference": "order_1042",
    "txRef": "fp_8f2k3m",
    "theme": "light",
    "status": "pending"
  }
}
```

**3. Pay it**

Open the `checkoutUrl`. Because this is a test payment, the page shows a sandbox banner with buttons to complete or fail it. Or settle it from your server:

```bash cURL theme={null}
curl -X POST "https://api.pay.flipeet.io/api/v1/sandbox/simulate" \
  -H "x-api-key: $FLIPEET_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reference": "fp_8f2k3m",
  "outcome": "success"
}'
```

```javascript Node.js theme={null}
const response = await fetch("https://api.pay.flipeet.io/api/v1/sandbox/simulate", {
  method: "POST",
  headers: {
    "x-api-key": process.env.FLIPEET_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "reference": "fp_8f2k3m",
    "outcome": "success"
  }),
});
const { data } = await response.json();
```

```python Python theme={null}
import os
import requests

response = requests.post(
    "https://api.pay.flipeet.io/api/v1/sandbox/simulate",
    headers={"x-api-key": os.environ["FLIPEET_SECRET_KEY"]},
    json={
        "reference": "fp_8f2k3m",
        "outcome": "success"
    },
)
data = response.json()["data"]
```

**4. Receive the webhook**

Tell us the `https` URL to send sandbox webhooks to. When the payment completes we POST `checkout.completed` to it, signed with your sandbox webhook secret. Check the signature before you trust it:

```javascript Node.js (Express) theme={null}
import crypto from "node:crypto";
import express from "express";

const app = express();

// Keep the raw body: the signature is over these exact bytes.
app.post("/hooks/flipeet", express.raw({ type: "application/json" }), (req, res) => {
  const header = req.get("x-flipeetpay-signature-v2") ?? "";
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = crypto
    .createHmac("sha256", process.env.FLIPEET_WEBHOOK_SECRET)
    .update(`${t}.${req.body}`)
    .digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  const valid = v1?.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
  if (!fresh || !valid) return res.sendStatus(400);

  const event = JSON.parse(req.body);
  if (event.event === "checkout.completed") {
    // Mark event.reference as paid.
  }
  res.sendStatus(200);
});
```

```python Python (Flask) theme={null}
import hashlib, hmac, json, os, time
from flask import Flask, request

app = Flask(__name__)

@app.post("/hooks/flipeet")
def flipeet_webhook():
    raw = request.get_data()  # the exact bytes that were signed
    header = request.headers.get("x-flipeetpay-signature-v2", "")
    parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
    expected = hmac.new(
        os.environ["FLIPEET_WEBHOOK_SECRET"].encode(),
        f"{parts.get('t', '')}.".encode() + raw,
        hashlib.sha256,
    ).hexdigest()
    fresh = abs(time.time() - int(parts.get("t", 0))) < 300
    if not fresh or not hmac.compare_digest(expected, parts.get("v1", "")):
        return "", 400

    event = json.loads(raw)
    if event["event"] == "checkout.completed":
        pass  # Mark event["reference"] as paid.
    return "", 200
```

**5. Go live**

When it all works, ask us for a live key and live webhook secret, give us your live webhook URL, and swap the key on your server. Nothing else changes. The [go-live checklist](https://docs.flipeet.io/going-live.md) covers the rest.


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