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

# Guide for AI Agents

> Complete context for AI agents (Claude, Cursor, Codex) to implement Forebit cryptocurrency payments into any website

# Forebit Payments — Guide for AI Agents

This page contains everything an AI agent (Claude, Cursor, Codex, or any LLM-based coding tool) needs to integrate **Forebit Payments** into a website. Copy-paste this entire page into your AI agent's context.

You are integrating **Forebit Payments**, a cryptocurrency payment processing API. Forebit provides a hosted checkout page — you create a payment via the API, redirect the customer to the checkout URL, and listen for webhook events to confirm payment.

## Architecture Overview

The integration flow is:

1. **Your server** creates a payment via the REST API
2. The API returns a `url` to a **Forebit-hosted checkout page**
3. You **redirect the customer** to that URL
4. The customer selects a cryptocurrency and pays
5. Forebit sends a **webhook** to your server when the payment status changes
6. Your server **verifies the webhook signature** and updates the order
7. Optionally, the customer is **redirected back** to your site via `redirectUrl`

There is no client-side SDK. All API calls happen server-side. The checkout UI is fully hosted by Forebit.

***

## Credentials

Obtain these from the Forebit dashboard:

| Credential         | Where to find it                | Purpose                                                         |
| ------------------ | ------------------------------- | --------------------------------------------------------------- |
| **Business ID**    | Payments → Settings → Developer | Identifies your business in API URLs                            |
| **API Key**        | Payments → Settings → Developer | Bearer token for API authentication                             |
| **Webhook Secret** | Developer → Webhooks            | `whsec_...` prefix, used with Svix to verify webhook signatures |

### Environment variables

```bash theme={null}
FOREBIT_BUSINESS_ID=your_business_id
FOREBIT_API_KEY=your_payments_api_key
FOREBIT_WEBHOOK_SECRET=whsec_...
```

***

## API Basics

### Base URL

```
https://prod-payments-api.forebit.io
```

All requests must use HTTPS.

### Authentication

Every request requires a Bearer token:

```
Authorization: Bearer YOUR_API_KEY
```

### Response format

**Success:**

```json theme={null}
{
  "data": { ... },
  "message": null,
  "errors": null
}
```

**Error (RFC 7807 ProblemDetails):**

```json theme={null}
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "Bad Request",
  "status": 400,
  "detail": "Validation failed"
}
```

### HTTP status codes

| Status | Meaning                                    |
| ------ | ------------------------------------------ |
| `200`  | Success                                    |
| `400`  | Invalid parameters or validation error     |
| `401`  | Invalid or missing API key                 |
| `403`  | Insufficient permissions for this business |
| `404`  | Payment or business not found              |

***

## Endpoints

All endpoints are scoped to a business:

| Method | Endpoint                                                | Description               |
| ------ | ------------------------------------------------------- | ------------------------- |
| `POST` | `/v1/businesses/{businessId}/payments`                  | Create a new payment      |
| `GET`  | `/v1/businesses/{businessId}/payments/{paymentId}`      | Get a single payment      |
| `GET`  | `/v1/businesses/{businessId}/payments`                  | List payments (paginated) |
| `PUT`  | `/v1/businesses/{businessId}/payments/{paymentId}/note` | Update internal note      |

***

## Creating a Payment

**`POST /v1/businesses/{businessId}/payments`**

### Request body

| Field               | Type           | Required | Description                                                                                         |
| ------------------- | -------------- | -------- | --------------------------------------------------------------------------------------------------- |
| `currency`          | string         | **Yes**  | ISO 4217 currency code (e.g. `USD`, `EUR`)                                                          |
| `amount`            | number         | **Yes**  | Payment amount (minimum `0.5`)                                                                      |
| `name`              | string         | No       | Display name shown to customer on checkout page                                                     |
| `description`       | string         | No       | Internal description, not visible to customers                                                      |
| `customerEmail`     | string (email) | No       | Customer email for receipts and status updates                                                      |
| `customerIp`        | string         | No       | Customer IP address. Auto-detected from checkout page visit if omitted                              |
| `customerUserAgent` | string         | No       | Customer user-agent. Auto-detected from checkout page visit if omitted                              |
| `redirectUrl`       | string (URI)   | No       | URL to redirect the customer after payment completes                                                |
| `notifyUrl`         | string (URI)   | No       | Webhook URL for this specific payment (overrides default)                                           |
| `metadata`          | object         | No       | Arbitrary key-value string pairs stored with the payment. Use this to attach your internal order ID |
| `paymentMethods`    | object         | No       | Restrict which payment methods are available to the customer                                        |
| `feeTransfers`      | array          | No       | Fee transfer configuration                                                                          |

### Example request

```bash theme={null}
curl -X POST https://prod-payments-api.forebit.io/v1/businesses/{businessId}/payments \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "USD",
    "amount": 25.00,
    "name": "Order #1234",
    "description": "Premium plan subscription",
    "customerEmail": "customer@example.com",
    "redirectUrl": "https://yoursite.com/thank-you",
    "notifyUrl": "https://yoursite.com/webhooks/forebit",
    "metadata": {
      "orderId": "1234",
      "plan": "premium"
    }
  }'
```

### Example response

```json theme={null}
{
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "url": "https://pay.forebit.io/payment/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  },
  "message": null,
  "errors": null
}
```

* `id` — UUID of the payment, use this to query the payment later
* `url` — hosted checkout page URL, redirect the customer here

### Restricting payment methods

Pass the `paymentMethods` object to control which cryptocurrencies are available. If omitted, all methods configured for your business are enabled.

```json theme={null}
{
  "paymentMethods": {
    "FOREBIT_CRYPTO": ["BITCOIN", "ETHEREUM", "SOLANA"],
    "CONTRACT_CRYPTO": ["CONTRACT_ERC20_USDT", "CONTRACT_ERC20_USDC"]
  }
}
```

**Charge types:**

| Type              | Description                                 |
| ----------------- | ------------------------------------------- |
| `FOREBIT_CRYPTO`  | Native coins and tokens via Forebit wallets |
| `CONTRACT_CRYPTO` | ERC-20 tokens via smart contract            |
| `CONTRACT_TRX`    | TRC-20 tokens via smart contract            |
| `NONE`            | No crypto payment method                    |

**Available coins per charge type:**

* **FOREBIT\_CRYPTO:** `BITCOIN`, `ETHEREUM`, `LITECOIN`, `BITCOIN_CASH`, `ETH_USD_COIN`, `ETH_TETHER`, `MONERO`, `BNB`, `ETH_BUSD`, `ETH_MATIC`, `ETH_SHIBA_INU`, `ETH_APE_COIN`, `ETH_CRONOS`, `ETH_DAI`, `ETH_UNISWAP`, `TRON`, `TRX_TETHER`, `TRX_USD_C`, `SOLANA`, `SOL_TETHER`, `SOL_USD_COIN`, `TON`
* **CONTRACT\_CRYPTO:** `CONTRACT_ERC20_ETH`, `CONTRACT_ERC20_USDT`, `CONTRACT_ERC20_USDC`
* **CONTRACT\_TRX:** `CONTRACT_TRC20_TRX`, `CONTRACT_TRC20_USDT`, `CONTRACT_TRC20_USDC`

***

## Retrieving a Payment

**`GET /v1/businesses/{businessId}/payments/{paymentId}`**

```bash theme={null}
curl https://prod-payments-api.forebit.io/v1/businesses/{businessId}/payments/{paymentId} \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response fields

| Field                   | Type          | Description                                   |
| ----------------------- | ------------- | --------------------------------------------- |
| `id`                    | string (UUID) | Payment identifier                            |
| `name`                  | string        | Display name                                  |
| `description`           | string        | Internal description                          |
| `endAmount`             | number        | Final payment amount                          |
| `prePaymentAmount`      | number        | Amount before payment processing              |
| `currency`              | string        | ISO 4217 currency code                        |
| `status`                | PaymentStatus | Current payment status                        |
| `createdAt`             | date-time     | When the payment was created                  |
| `expiresAt`             | date-time     | When the payment expires                      |
| `timeline`              | array         | Status change history                         |
| `customer`              | object        | Customer details including email and IP info  |
| `metadata`              | object        | Custom key-value pairs you attached           |
| `selectedPaymentMethod` | PaymentMethod | Method chosen by the customer                 |
| `forebitCryptoCharge`   | object        | Forebit crypto charge details (if applicable) |
| `contractCharge`        | object        | Contract charge details (if applicable)       |
| `forebitFee`            | number        | Fee amount                                    |
| `note`                  | string        | Internal note                                 |
| `netAmountUsd`          | number        | Net amount in USD                             |

***

## Listing Payments

**`GET /v1/businesses/{businessId}/payments`**

### Query parameters

| Parameter      | Type      | Description                                                        |
| -------------- | --------- | ------------------------------------------------------------------ |
| `PageNumber`   | integer   | Page number                                                        |
| `PageSize`     | integer   | Results per page                                                   |
| `fromTime`     | date-time | Start of date range                                                |
| `toTime`       | date-time | End of date range                                                  |
| `statuses`     | array     | Filter by status (repeat parameter for multiple)                   |
| `cryptoCoins`  | array     | Filter by cryptocurrency                                           |
| `fromAmount`   | number    | Minimum amount                                                     |
| `toAmount`     | number    | Maximum amount                                                     |
| `searchString` | string    | Free-text search across description, name, note, or customer email |

Example:

```bash theme={null}
curl "https://prod-payments-api.forebit.io/v1/businesses/{businessId}/payments?PageSize=20&statuses=COMPLETED&statuses=PENDING" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

***

## Payment Statuses

| Status             | Description                                         |
| ------------------ | --------------------------------------------------- |
| `AWAITING_PAYMENT` | Payment created, waiting for customer to pay        |
| `PENDING`          | Payment detected on-chain, awaiting confirmation    |
| `PROCESSING`       | Payment is being processed                          |
| `UNDERPAID`        | Customer sent less than the required amount         |
| `COMPLETED`        | Payment confirmed and completed — fulfill the order |
| `FAILED`           | Payment failed                                      |
| `CANCELLED`        | Payment was cancelled                               |
| `EXPIRED`          | Payment expired before completion                   |

***

## Webhooks

Forebit uses **Svix** for webhook delivery. Svix provides automatic retries, signature validation, and delivery logs.

### Webhook events

| Event                     | Description                                                    |
| ------------------------- | -------------------------------------------------------------- |
| `PAYMENT_CREATED`         | Payment was created                                            |
| `PAYMENT_METHOD_SELECTED` | Customer selected a payment method                             |
| `PAYMENT_PENDING`         | Payment detected, awaiting confirmation                        |
| `PAYMENT_UNDERPAID`       | Customer sent less than required                               |
| `PAYMENT_COMPLETED`       | Payment confirmed — **this is the event to fulfill orders on** |
| `PAYMENT_EXPIRED`         | Payment expired                                                |
| `PAYMENT_CANCELLED`       | Payment was cancelled                                          |

### Webhook payload structure

```json theme={null}
{
  "EventType": "PAYMENT_COMPLETED",
  "ForPaymentEvents": {
    "Id": "78d1cc6a-2e46-421b-b03b-3c307bfbd1bc",
    "BusinessId": 1001,
    "Name": "Order #1234",
    "Description": "",
    "EndAmount": 25.00,
    "PrePaymentAmount": 25.00,
    "Currency": "USD",
    "Status": "COMPLETED",
    "CreatedAt": "2025-08-14T09:18:56.295788Z",
    "ExpiresAt": "2025-08-14T09:48:56.295788Z",
    "Timeline": [
      { "Time": "2025-08-14T09:18:56Z", "PaymentStatus": "AWAITING_PAYMENT" },
      { "Time": "2025-08-14T09:20:40Z", "PaymentStatus": "PENDING" },
      { "Time": "2025-08-14T09:20:40Z", "PaymentStatus": "COMPLETED" }
    ],
    "Customer": {
      "Id": 68,
      "Email": "customer@example.com",
      "IpAddresses": [
        {
          "City": "New York",
          "Ip": "203.0.113.50",
          "Country": "United States",
          "RiskScore": 0,
          "ConnectionType": "RESIDENTIAL",
          "ISP": "Example ISP",
          "DateCreated": "2025-07-21T09:13:11Z"
        }
      ]
    },
    "SelectedPaymentMethod": "FOREBIT_CRYPTO",
    "ForebitCryptoCharge": {
      "Amount": 0.00025,
      "CoinName": "BITCOIN",
      "ExchangeRate": 100000.00,
      "IsUnderpaid": false,
      "Address": "bc1q...",
      "Transaction": {
        "Amount": 0.00025,
        "ToAddress": "bc1q...",
        "Id": "txhash...",
        "Confirmations": 3,
        "Network": "BTC",
        "FromAddress": "bc1qsender...",
        "TokenName": "BITCOIN"
      },
      "WalletName": "main"
    },
    "ForebitFee": 0.50,
    "RedirectUrl": "https://yoursite.com/thank-you"
  }
}
```

**Important:** Webhook field names use **PascalCase** (e.g. `EventType`, `ForPaymentEvents`, `EndAmount`), while the REST API responses use **camelCase** (e.g. `endAmount`, `currency`).

### Webhook payload TypeScript types

```typescript theme={null}
interface BaseWebhookResponse {
  EventType: string;
  ForPaymentEvents?: PaymentForWebhookResponse | null;
}

interface PaymentForWebhookResponse {
  Id: string;
  BusinessId: number;
  Name?: string;
  Description?: string;
  EndAmount: number;
  PrePaymentAmount: number;
  Currency: string;
  Status: PaymentStatus;
  CreatedAt: string;
  ExpiresAt: string;
  Timeline: { Time: string; PaymentStatus: PaymentStatus }[];
  Customer?: {
    Id: number;
    Email: string;
    IpAddresses: {
      City?: string;
      Ip: string;
      Country?: string;
      RiskScore?: number;
      ConnectionType: string;
      ISP?: string;
      DateCreated: string;
    }[];
  } | null;
  Metadata?: Record<string, string> | null;
  SelectedPaymentMethod?: PaymentMethod | null;
  ForebitCryptoCharge?: {
    Amount: number;
    CoinName: string;
    ExchangeRate: number;
    IsUnderpaid: boolean;
    Address: string;
    Transaction?: {
      Amount: number;
      ToAddress: string;
      Id: string;
      Confirmations: number;
      BlockNumber?: string;
      Network?: string;
      FromAddress?: string;
      TokenName?: string;
    } | null;
    WalletName: string;
  } | null;
  ContractCharge?: {
    Amount: number;
    ExchangeRate: number;
    IsUnderpaid: boolean;
    Address: string;
    Transaction: {
      Amount: number;
      ToAddress: string;
      Id: string;
      Confirmations: number;
      BlockNumber?: string;
      Network?: string;
      FromAddress?: string;
      TokenName?: string;
    };
    WalletName: string;
    CoinName: string;
  } | null;
  ForebitFee?: number;
  RedirectUrl?: string;
}

type PaymentStatus =
  | 'AWAITING_PAYMENT' | 'PENDING' | 'PROCESSING'
  | 'UNDERPAID' | 'COMPLETED' | 'FAILED'
  | 'CANCELLED' | 'EXPIRED';

type PaymentMethod = 'FOREBIT_CRYPTO' | 'CONTRACT_CRYPTO' | 'CONTRACT_TRX' | 'NONE';
```

### Verifying webhook signatures

Use the **Svix** library to verify webhook signatures. This is critical for security — never process a webhook without verifying the signature first.

Required headers from the webhook request: `svix-id`, `svix-timestamp`, `svix-signature`.

**Node.js:**

```javascript theme={null}
import { Webhook } from "svix";

const wh = new Webhook(process.env.FOREBIT_WEBHOOK_SECRET);

// Inside your webhook handler:
// payload = raw request body as a string
// headers = object with svix-id, svix-timestamp, svix-signature
const event = wh.verify(payload, headers);
```

**Python:**

```python theme={null}
from svix.webhooks import Webhook

wh = Webhook(os.environ["FOREBIT_WEBHOOK_SECRET"])

# payload = raw request body as bytes
# headers = dict with svix-id, svix-timestamp, svix-signature
event = wh.verify(payload, headers)
```

Install: `npm install svix` (Node.js) or `pip install svix` (Python).

***

## Full Integration Examples

### Node.js (Express)

```javascript theme={null}
import express from "express";
import { Webhook } from "svix";

const app = express();

const FOREBIT_API_KEY = process.env.FOREBIT_API_KEY;
const FOREBIT_BUSINESS_ID = process.env.FOREBIT_BUSINESS_ID;
const FOREBIT_WEBHOOK_SECRET = process.env.FOREBIT_WEBHOOK_SECRET;
const BASE_URL = "https://prod-payments-api.forebit.io";

// 1. Create a payment and redirect to checkout
app.post("/checkout", async (req, res) => {
  const { orderId, amount, email } = req.body;

  const response = await fetch(
    `${BASE_URL}/v1/businesses/${FOREBIT_BUSINESS_ID}/payments`,
    {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${FOREBIT_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        currency: "USD",
        amount,
        name: `Order #${orderId}`,
        customerEmail: email,
        redirectUrl: "https://yoursite.com/thank-you",
        notifyUrl: "https://yoursite.com/webhooks/forebit",
        metadata: { orderId },
      }),
    }
  );

  const result = await response.json();

  if (!response.ok) {
    return res.status(400).json({ error: result });
  }

  // Save result.data.id to your database linked to the order
  // Then redirect the customer to checkout
  res.json({ checkoutUrl: result.data.url });
});

// 2. Handle webhooks — use raw body for signature verification
app.post(
  "/webhooks/forebit",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const wh = new Webhook(FOREBIT_WEBHOOK_SECRET);

    let event;
    try {
      event = wh.verify(req.body.toString(), {
        "svix-id": req.headers["svix-id"],
        "svix-timestamp": req.headers["svix-timestamp"],
        "svix-signature": req.headers["svix-signature"],
      });
    } catch (err) {
      console.error("Webhook verification failed:", err.message);
      return res.status(400).send("Invalid signature");
    }

    const { EventType, ForPaymentEvents: payment } = event;

    switch (EventType) {
      case "PAYMENT_COMPLETED":
        // Fulfill the order using payment.Metadata.orderId
        console.log(`Payment ${payment.Id} completed for ${payment.EndAmount} ${payment.Currency}`);
        // Update your database: mark order as paid
        break;

      case "PAYMENT_EXPIRED":
        // Handle expired payment
        console.log(`Payment ${payment.Id} expired`);
        break;

      case "PAYMENT_UNDERPAID":
        // Handle underpaid payment
        console.log(`Payment ${payment.Id} underpaid`);
        break;
    }

    res.status(200).send("OK");
  }
);

// Use json parsing for all other routes
app.use(express.json());

app.listen(3000);
```

### Python (Flask)

```python theme={null}
import os
import requests
from flask import Flask, request, jsonify
from svix.webhooks import Webhook

app = Flask(__name__)

FOREBIT_API_KEY = os.environ["FOREBIT_API_KEY"]
FOREBIT_BUSINESS_ID = os.environ["FOREBIT_BUSINESS_ID"]
FOREBIT_WEBHOOK_SECRET = os.environ["FOREBIT_WEBHOOK_SECRET"]
BASE_URL = "https://prod-payments-api.forebit.io"


@app.route("/checkout", methods=["POST"])
def checkout():
    data = request.json
    order_id = data["orderId"]
    amount = data["amount"]
    email = data.get("email")

    resp = requests.post(
        f"{BASE_URL}/v1/businesses/{FOREBIT_BUSINESS_ID}/payments",
        headers={
            "Authorization": f"Bearer {FOREBIT_API_KEY}",
            "Content-Type": "application/json",
        },
        json={
            "currency": "USD",
            "amount": amount,
            "name": f"Order #{order_id}",
            "customerEmail": email,
            "redirectUrl": "https://yoursite.com/thank-you",
            "notifyUrl": "https://yoursite.com/webhooks/forebit",
            "metadata": {"orderId": order_id},
        },
    )

    result = resp.json()

    if resp.status_code != 200:
        return jsonify({"error": result}), 400

    # Save result["data"]["id"] to your database
    return jsonify({"checkoutUrl": result["data"]["url"]})


@app.route("/webhooks/forebit", methods=["POST"])
def webhook():
    wh = Webhook(FOREBIT_WEBHOOK_SECRET)

    try:
        event = wh.verify(
            request.get_data(as_text=True),
            {
                "svix-id": request.headers.get("svix-id"),
                "svix-timestamp": request.headers.get("svix-timestamp"),
                "svix-signature": request.headers.get("svix-signature"),
            },
        )
    except Exception as e:
        print(f"Webhook verification failed: {e}")
        return "Invalid signature", 400

    event_type = event["EventType"]
    payment = event["ForPaymentEvents"]

    if event_type == "PAYMENT_COMPLETED":
        order_id = payment.get("Metadata", {}).get("orderId")
        print(f"Payment {payment['Id']} completed — fulfill order {order_id}")
        # Update your database: mark order as paid

    elif event_type == "PAYMENT_EXPIRED":
        print(f"Payment {payment['Id']} expired")

    return "OK", 200
```

### Next.js (App Router)

```typescript theme={null}
// app/api/checkout/route.ts
import { NextResponse } from "next/server";

const FOREBIT_API_KEY = process.env.FOREBIT_API_KEY!;
const FOREBIT_BUSINESS_ID = process.env.FOREBIT_BUSINESS_ID!;

export async function POST(req: Request) {
  const { orderId, amount, email } = await req.json();

  const response = await fetch(
    `https://prod-payments-api.forebit.io/v1/businesses/${FOREBIT_BUSINESS_ID}/payments`,
    {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${FOREBIT_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        currency: "USD",
        amount,
        name: `Order #${orderId}`,
        customerEmail: email,
        redirectUrl: "https://yoursite.com/thank-you",
        notifyUrl: "https://yoursite.com/api/webhooks/forebit",
        metadata: { orderId },
      }),
    }
  );

  const result = await response.json();

  if (!response.ok) {
    return NextResponse.json({ error: result }, { status: 400 });
  }

  return NextResponse.json({ checkoutUrl: result.data.url });
}
```

```typescript theme={null}
// app/api/webhooks/forebit/route.ts
import { Webhook } from "svix";

const FOREBIT_WEBHOOK_SECRET = process.env.FOREBIT_WEBHOOK_SECRET!;

export async function POST(req: Request) {
  const body = await req.text();
  const headers = {
    "svix-id": req.headers.get("svix-id") ?? "",
    "svix-timestamp": req.headers.get("svix-timestamp") ?? "",
    "svix-signature": req.headers.get("svix-signature") ?? "",
  };

  const wh = new Webhook(FOREBIT_WEBHOOK_SECRET);

  let event: any;
  try {
    event = wh.verify(body, headers);
  } catch {
    return new Response("Invalid signature", { status: 400 });
  }

  const { EventType, ForPaymentEvents: payment } = event;

  if (EventType === "PAYMENT_COMPLETED") {
    const orderId = payment.Metadata?.orderId;
    // Fulfill the order in your database
  }

  return new Response("OK", { status: 200 });
}
```

***

## Best Practices

### Security

* **Always verify webhook signatures** using Svix before processing any webhook event. Never trust the payload without verification.
* **Keep your API key server-side only.** Never expose it in client-side code, browser JavaScript, or mobile apps.
* **Use HTTPS** for all webhook endpoints. Forebit will not deliver webhooks to HTTP URLs in production.
* **Store the webhook secret securely** in environment variables, never hardcoded.

### Payment creation

* **Always store the payment `id`** from the create response in your database, linked to your internal order. You need it to reconcile webhooks and query payment status.
* **Use `metadata`** to attach your internal order ID, user ID, or any reference data. This data is returned in webhooks and GET requests, making reconciliation easy.
* **Set `redirectUrl`** so the customer returns to your site after payment. Without it, they stay on the Forebit checkout page.
* **Set `notifyUrl`** per-payment if you have multiple webhook endpoints, or rely on the default configured in the dashboard.
* **Set `customerEmail`** so the customer receives email receipts and status updates.
* **Minimum amount is `0.5`** in your chosen currency.

### Webhook handling

* **Respond with `200` quickly.** Process the webhook asynchronously if your fulfillment logic is slow. Svix will retry on non-2xx responses.
* **Make your webhook handler idempotent.** You may receive the same event more than once due to retries. Use the payment `Id` to deduplicate.
* **Only fulfill orders on `PAYMENT_COMPLETED`.** Do not fulfill on `PENDING` or `PROCESSING` — these are intermediate states.
* **Handle `PAYMENT_EXPIRED` and `PAYMENT_CANCELLED`** to clean up pending orders in your system.
* **Use the raw request body** for signature verification. Parsing the JSON first and re-serializing it will break the signature.

### Error handling

* Check for non-200 responses from the API and handle them gracefully.
* API errors use RFC 7807 ProblemDetails format with `type`, `title`, `status`, and `detail` fields.
* If a payment creation fails, show the user an error and let them retry. Do not create duplicate payments — check your database first.

### Testing

* Use small amounts (minimum `0.5`) for test payments.
* Use the Svix CLI or dashboard to replay webhooks to your endpoint during development.
* Use a tool like ngrok to expose your local webhook endpoint during development.

***

## Supported Cryptocurrencies (Full List)

| Coin                   | Identifier            | Network  |
| ---------------------- | --------------------- | -------- |
| Bitcoin                | `BITCOIN`             | BTC      |
| Ethereum               | `ETHEREUM`            | ETHEREUM |
| Litecoin               | `LITECOIN`            | LTC      |
| Bitcoin Cash           | `BITCOIN_CASH`        | BTC      |
| USDC (ERC-20)          | `ETH_USD_COIN`        | ETHEREUM |
| USDT (ERC-20)          | `ETH_TETHER`          | ETHEREUM |
| Monero                 | `MONERO`              | —        |
| BNB                    | `BNB`                 | ETHEREUM |
| DAI (ERC-20)           | `ETH_DAI`             | ETHEREUM |
| Uniswap (ERC-20)       | `ETH_UNISWAP`         | ETHEREUM |
| MATIC (ERC-20)         | `ETH_MATIC`           | ETHEREUM |
| SHIB (ERC-20)          | `ETH_SHIBA_INU`       | ETHEREUM |
| APE (ERC-20)           | `ETH_APE_COIN`        | ETHEREUM |
| CRO (ERC-20)           | `ETH_CRONOS`          | ETHEREUM |
| BUSD (ERC-20)          | `ETH_BUSD`            | ETHEREUM |
| Tron                   | `TRON`                | TRON     |
| USDT (TRC-20)          | `TRX_TETHER`          | TRON     |
| USDC (TRC-20)          | `TRX_USD_C`           | TRON     |
| Solana                 | `SOLANA`              | SOLANA   |
| USDT (Solana)          | `SOL_TETHER`          | SOLANA   |
| USDC (Solana)          | `SOL_USD_COIN`        | SOLANA   |
| TON                    | `TON`                 | —        |
| Contract ETH           | `CONTRACT_ERC20_ETH`  | ETHEREUM |
| Contract USDT (ERC-20) | `CONTRACT_ERC20_USDT` | ETHEREUM |
| Contract USDC (ERC-20) | `CONTRACT_ERC20_USDC` | ETHEREUM |
| Contract TRX           | `CONTRACT_TRC20_TRX`  | TRON     |
| Contract USDT (TRC-20) | `CONTRACT_TRC20_USDT` | TRON     |
| Contract USDC (TRC-20) | `CONTRACT_TRC20_USDC` | TRON     |

**Networks:** `ETHEREUM`, `TRON`, `BTC`, `LTC`, `SOLANA`

***

## Quick Reference

```
Base URL:       https://prod-payments-api.forebit.io
Auth header:    Authorization: Bearer YOUR_API_KEY
Create payment: POST /v1/businesses/{businessId}/payments
Get payment:    GET  /v1/businesses/{businessId}/payments/{paymentId}
List payments:  GET  /v1/businesses/{businessId}/payments
Update note:    PUT  /v1/businesses/{businessId}/payments/{paymentId}/note

Webhook lib:    svix (npm install svix / pip install svix)
Fulfill on:     PAYMENT_COMPLETED event only
Min amount:     0.5 (in chosen currency)
```
