Skip to main content

Quickstart

This guide walks you through your first Zet API integration — creating a wallet and buying crypto with NGN.

Prerequisites

Step 1: Get your API key

Reach out to zetdotmoney@gmail.com to request API access. Our team will provision your credentials. You’ll receive:
  • API Key (zet_live_...) — include in every request as the x-api-key header
  • API Secret (zet_secret_...) — used to verify webhook signatures (keep this secret!)
Never expose your API key or secret in client-side code. All Zet API calls should be made from your backend server.

Step 2: Create a wallet

Create a Smart Wallet for your user:
curl -X POST https://api.zet.money/v1/wallets \
  -H "Content-Type: application/json" \
  -H "x-api-key: zet_live_your_api_key" \
  -d '{
    "externalUserId": "user_abc123",
    "chain": "base",
    "metadata": {
      "email": "user@example.com"
    }
  }'
Response:
{
  "success": true,
  "data": {
    "id": "wal_01H8X3abc",
    "externalUserId": "user_abc123",
    "address": "0x1234567890abcdef1234567890abcdef12345678",
    "chain": "base",
    "isDeployed": {
      "base": false,
      "bsc": false
    },
    "createdAt": "2026-03-02T10:00:00Z",
    "metadata": {
      "email": "user@example.com"
    }
  }
}
The wallet is lazily deployed — the on-chain Safe contract deploys automatically on the first transaction, with gas sponsored by Zet.

Step 3: Get an on-ramp quote

Get a quote for buying USDC with 50,000 NGN:
curl -X POST https://api.zet.money/v1/onramp/quote \
  -H "Content-Type: application/json" \
  -H "x-api-key: zet_live_your_api_key" \
  -d '{
    "amount": "50000",
    "tokenSymbol": "USDC",
    "chain": "base"
  }'
Response:
{
  "success": true,
  "data": {
    "quoteId": "qt_01H8X3xyz",
    "fiatAmount": "50000",
    "fiatCurrency": "NGN",
    "cryptoAmount": "32.45",
    "tokenSymbol": "USDC",
    "chain": "base",
    "rate": "1540.50",
    "fees": {
      "providerFee": "50",
      "flatFee": "0",
      "swapFee": "20",
      "totalFee": "70"
    },
    "expiresAt": "2026-03-02T10:05:00Z"
  }
}

Step 4: Initiate the on-ramp

Use the quoteId to start the transaction:
curl -X POST https://api.zet.money/v1/onramp/initiate \
  -H "Content-Type: application/json" \
  -H "x-api-key: zet_live_your_api_key" \
  -d '{
    "quoteId": "qt_01H8X3xyz",
    "walletId": "wal_01H8X3abc",
    "reference": "order_12345"
  }'
Response:
{
  "success": true,
  "data": {
    "transactionId": "txn_01H8X3def",
    "reference": "order_12345",
    "status": "pending",
    "depositAccount": {
      "bankName": "Wema Bank",
      "bankCode": "035",
      "accountNumber": "0123456789",
      "accountName": "Zet / John Doe"
    },
    "amount": "50070",
    "expiresAt": "2026-03-02T10:30:00Z"
  }
}
Display the depositAccount details to your user so they can send the NGN via bank transfer.

Step 5: Handle the webhook

Once the user’s bank transfer arrives and crypto is delivered, Zet sends a webhook to your registered URL:
{
  "event": "onramp.completed",
  "timestamp": "2026-03-02T10:12:00Z",
  "data": {
    "transactionId": "txn_01H8X3def",
    "reference": "order_12345",
    "type": "onramp",
    "status": "completed",
    "amount": "32.45",
    "tokenSymbol": "USDC",
    "chain": "base",
    "transactionHash": "0xabc123...",
    "fiatAmount": "50000",
    "fiatCurrency": "NGN",
    "walletId": "wal_01H8X3abc"
  }
}
Verify the x-zet-signature header using your API secret:
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Next steps