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