# Quickstart (/docs/quickstart)

This walks through the most common integration: your customer checks out on your site, pays on a Creddot hosted page, and comes back to your site while your server is told the order is paid.

<Steps>
<Step>

### Get your test keys [#get-your-test-keys]

In the [dashboard](https://business.creddot.com), open **Settings, API Keys and Webhooks** and create a **test** key with the `collections:create` and `transactions:read` permissions. You get two values:

- an **API key** starting with `ck_test_`
- an **API secret**, shown once. Store it in your server's environment, never in browser or mobile code.

```bash title=".env"
CREDDOT_API_KEY=ck_test_...
CREDDOT_API_SECRET=...
```

</Step>
<Step>

### Create a checkout session [#create-a-checkout-session]

When the customer clicks Pay, your server creates a session for the order. Amounts are in **kobo** (minor units), so `250000` is ₦2,500.00.

<Tabs items={['cURL', 'Node.js', 'PHP']}>
<Tab value="cURL">

```bash
curl https://api.creddot.com/api/v1/checkout/sessions \
  -H "x-api-key: $CREDDOT_API_KEY" \
  -H "x-api-secret: $CREDDOT_API_SECRET" \
  -H "x-idempotency-key: order-10042" \
  -H "content-type: application/json" \
  -d '{
    "amountMinor": "250000",
    "currency": "NGN",
    "reference": "ORDER-10042",
    "description": "Order 10042",
    "customerEmail": "ada@example.com",
    "redirectUrl": "https://yourshop.com/orders/10042/complete"
  }'
```

</Tab>
<Tab value="Node.js">

```js
const res = await fetch('https://api.creddot.com/api/v1/checkout/sessions', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.CREDDOT_API_KEY,
    'x-api-secret': process.env.CREDDOT_API_SECRET,
    'x-idempotency-key': `order-${order.id}`,
    'content-type': 'application/json',
  },
  body: JSON.stringify({
    amountMinor: String(order.totalKobo),
    currency: 'NGN',
    reference: `ORDER-${order.id}`,
    customerEmail: order.email,
    redirectUrl: `https://yourshop.com/orders/${order.id}/complete`,
  }),
});
if (!res.ok) throw new Error(`Creddot: ${res.status} ${await res.text()}`);
const session = await res.json();
// Send the customer to Creddot checkout
return Response.redirect(session.checkoutUrl, 303);
```

</Tab>
<Tab value="PHP">

```php
$ch = curl_init('https://api.creddot.com/api/v1/checkout/sessions');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'x-api-key: ' . getenv('CREDDOT_API_KEY'),
    'x-api-secret: ' . getenv('CREDDOT_API_SECRET'),
    'x-idempotency-key: order-' . $order['id'],
    'content-type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'amountMinor' => (string) $order['total_kobo'],
    'currency' => 'NGN',
    'reference' => 'ORDER-' . $order['id'],
    'customerEmail' => $order['email'],
    'redirectUrl' => 'https://yourshop.com/orders/' . $order['id'] . '/complete',
  ]),
]);
$session = json_decode(curl_exec($ch), true);
header('Location: ' . $session['checkoutUrl'], true, 303);
```

</Tab>
</Tabs>

The response includes `checkoutUrl`. Redirect the customer there. The session can be paid once and expires after 30 minutes unless you set `expiresAt`.

```json
{
  "id": "cmv8l2x9k0001s7...",
  "reference": "ORDER-10042",
  "amountMinor": "250000",
  "currency": "NGN",
  "checkoutUrl": "https://checkout.creddot.com/pl/cpl_...",
  "checkoutPath": "/pl/cpl_...",
  "expiresAt": "2026-11-02T12:30:00.000Z"
}
```

</Step>
<Step>

### The customer pays [#the-customer-pays]

Creddot checkout shows card, bank transfer and USSD (whichever you have turned on). After a successful payment the customer is sent to your `redirectUrl` exactly as you gave it, so put your order id in that URL.

</Step>
<Step>

### Confirm the payment on your server [#confirm-the-payment-on-your-server]

Never fulfil an order just because the customer reached your return page. Confirm it with Creddot, either way works:

- **Webhook (recommended):** Creddot sends `transaction.success` to your webhook URL. Its `data.merchantReference` is your `ORDER-10042`. See [Webhooks](/docs/guides/webhooks).
- **Ask on your return page:**

```bash
curl https://api.creddot.com/api/v1/checkout/sessions/ORDER-10042 \
  -H "x-api-key: $CREDDOT_API_KEY" \
  -H "x-api-secret: $CREDDOT_API_SECRET"
```

`status` is `PAID` once a payment succeeded, and `payment` holds its details. Check that `amountMinor` and `currency` match the order before you fulfil it.

</Step>
</Steps>

## Next steps [#next-steps]

- [Verify webhook signatures](/docs/guides/webhooks#verify-the-signature) before trusting them.
- Complete test payments without real money in [Test mode](/docs/test-mode).
- Read the [Go live checklist](/docs/guides/go-live).
