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

# Quickstart

> Beginner-friendly guide: create an intent on your backend, launch checkout, and handle fulfillment safely.

This guide is written for first-time integrators.

By the end, you will:

1. Create a payment intent on your backend.
2. Return `client_secret` to your frontend.
3. Open KryptoPay checkout with the SDK.
4. Handle success and backend fulfillment.

## Before you start

* API base URL: `https://api.kryptopay.xyz`
* Keep API keys server-side only
* Frontend should only receive `client_secret`

## Step 1: Create intent on your backend

Use your API key from server code. Do not call this endpoint directly from browser code.

### cURL

```bash theme={null}
curl -X POST "https://api.kryptopay.xyz/v1/payment_intents" \
  -H "Authorization: Bearer kp_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_units": 2500000,
    "chain": "base",
    "token": "USDC",
    "expires_in_minutes": 15,
    "lane": "sdk",
    "metadata": { "order_id": "ord_1001" }
  }'
```

### Node.js (Express)

```js theme={null}
import express from "express";

const app = express();
app.use(express.json());

app.post("/api/create-intent", async (req, res) => {
  const { amountUnits, orderId } = req.body;

  const kpRes = await fetch("https://api.kryptopay.xyz/v1/payment_intents", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.KRYPTOPAY_API_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      amount_units: amountUnits,
      chain: "base",
      token: "USDC",
      expires_in_minutes: 15,
      lane: "sdk",
      metadata: { order_id: orderId }
    })
  });

  const data = await kpRes.json();
  if (!kpRes.ok) return res.status(kpRes.status).json(data);

  // Return only what frontend needs
  return res.json({ clientSecret: data.client_secret, intentId: data.id });
});
```

### Next.js route handler

```ts theme={null}
// app/api/create-intent/route.ts
import { NextResponse } from "next/server";

export async function POST(req: Request) {
  const body = await req.json();

  const kpRes = await fetch("https://api.kryptopay.xyz/v1/payment_intents", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.KRYPTOPAY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      amount_units: body.amountUnits,
      chain: "base",
      token: "USDC",
      expires_in_minutes: 15,
      lane: "sdk",
      metadata: { order_id: body.orderId },
    }),
  });

  const data = await kpRes.json();
  return NextResponse.json(data, { status: kpRes.status });
}
```

### Python (coming soon)

Python examples and server SDK helpers are planned. The HTTP flow is the same: call `POST /v1/payment_intents` server-side, then return `client_secret` to the client.

## Step 2: Open checkout in frontend

```ts theme={null}
import { openKryptoPayModal } from "@kryptopay/sdk";

openKryptoPayModal({
  clientSecret,
  merchantName: "Acme Store",
  onSuccess: (event) => {
    console.log("paid", event.payment_intent_id, event.tx_hash);
  },
  onError: (error) => {
    console.error(error.code, error.message);
  },
});
```

## Step 3: Fulfillment model

Treat frontend callbacks as user UX signals.

For fulfillment and accounting, use backend systems and your event pipeline so duplicate callbacks or page refreshes do not create duplicate business actions.

## Common mistakes

* Calling `POST /v1/payment_intents` from frontend code
* Exposing API key in JavaScript bundles
* Treating frontend success callback as final source of truth
* Forgetting to persist `order_id` or internal reference in `metadata`

## Example apps

Reference integrations are available at:

* [https://github.com/KryptoPaySDK/examples](https://github.com/KryptoPaySDK/examples)
