---
title: Quickstart
description: A test key, a test sale and a signed webhook, in a few minutes.
group: start
order: 2
---

Everything here runs in [test mode](/docs/concepts/test-mode): the same responses, statuses and webhooks as live, against a test wallet and a simulated network. The code you write here is the code you ship.

## 1. Get a test key

Create an account, verify your email, then open **Developers > API keys** in the dashboard and create a key in **Test** mode. A test key starts with `scn_test_`. It is shown once, so put it straight into your environment.

```bash
export SIMCONNECT_KEY="scn_test_..." # the key you just copied
```

## 2. Fund the test wallet

In the dashboard, switch to **Test** and open **Wallet**, then use **Top up test wallet**. Each sale holds its flat fee on the wallet, the same in test and live. A sale the wallet cannot cover is refused with `402 WALLET_INSUFFICIENT_FUNDS`.

## 3. Send airtime

One request, with an `Idempotency-Key` so it is safe to repeat. `MTN-VTU` is MTN's airtime product; [List plans](/docs/api/list-data-plans) has every product code.

```bash
curl https://api.simconnectng.com/api/v1/airtime \
  -H "Authorization: Bearer $SIMCONNECT_KEY" \
  -H "Idempotency-Key: order_1042" \
  -H "Content-Type: application/json" \
  -d '{
    "product_code": "MTN-VTU",
    "amount": 500,
    "phone_number": "08012345678",
    "client_reference": "order_1042"
  }'
```

The call stays open until the sale is final and answers with the result:

```json
{
  "success": true,
  "data": {
    "reference": "txn_0192f4c1a7e84b6f9d2c3e5a7b9d1f30",
    "client_reference": "order_1042",
    "mode": "test",
    "status": "successful",
    "product_code": "MTN-VTU",
    "network": "mtn",
    "destination": "+234********78",
    "amount": 500.00,
    "price": 2.00,
    "completed_at": "2026-10-06T12:04:03Z"
  },
  "message": "Transaction successful",
  "code": "OK"
}
```

`amount` is the airtime sent and `price` the fee your wallet paid. Keep the `reference`: webhooks and [Get a transaction](/docs/api/get-transaction) use it. If your request times out, send it again with the same `Idempotency-Key` and body; you will get the same answer, never a second charge. To get an answer at once and the result by webhook, add `?wait=0`: the call answers `202` at once, while the sale is on its way.

In test mode the last four digits of the phone number choose the outcome: `0000` fails, `3333` stays `pending` before it is `successful`, `4444` stays `pending` before it fails, anything else is `successful`. [Test mode](/docs/concepts/test-mode) lists them all.

## 4. Take the webhook

Add an endpoint under **Developers > Webhooks**. When the sale is final you receive:

```json
{
  "id": "0192f4c2-8d1e-7a3b-9c4f-5e6a7b8c9d0e",
  "type": "transaction.successful",
  "mode": "test",
  "occurred_at": "2026-10-06T12:04:03Z",
  "data": {
    "reference": "txn_0192f4c1a7e84b6f9d2c3e5a7b9d1f30",
    "client_reference": "order_1042",
    "status": "successful",
    "amount": 500.00,
    "price": 2.00
  }
}
```

Check the `SimConnect-Signature` header before you trust it; [Webhooks](/docs/concepts/webhooks) shows how in a few lines, and lists the full body.

## 5. Go live

Create a live key (it starts with `scn_live_`), fund your live wallet, and swap the key. Nothing else changes.
