Accept crypto payments with a Stripe-like developer experience. Create customers, get permanent wallet addresses, and receive webhooks when deposits arrive.
https://api.totopay.net/api/v1Include your API key in the Authorization header:
Authorization: Bearer sk_live_YOUR_API_KEYsk_live_. Transactions use mainnet and are real.sk_test_. Use testnets. Simulate deposits for free.Customers represent end-users of your application. Each customer automatically receives unique crypto addresses on all supported networks.
Deposits are automatically detected when crypto is sent to a customer's address. A flat $2 service fee is deducted per transaction.
Configure webhook endpoints to receive real-time notifications about deposit events. Each delivery includes an HMAC-SHA256 signature for verification.
Retrieve your account balance summary including total received, fees, and breakdown by currency.
Use sk_test_ API keys to work in test mode. All data is isolated from production. Use the simulate endpoint to test your integration.
Every webhook delivery includes an X-Webhook-Signature header. Verify it using HMAC-SHA256 with your endpoint secret to ensure the request came from TotoPay.
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),
);
}
// In your Express handler:
app.post('/webhooks/totopay', (req, res) => {
const sig = req.headers['x-webhook-signature'];
if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(400).send('Invalid signature');
}
const { event, data } = req.body;
if (event === 'deposit.completed') {
console.log('Deposit confirmed:', data.transaction_hash);
// Credit user, update order, etc.
}
res.status(200).send('OK');
});import hmac, hashlib, json
def verify_webhook(payload: dict, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
json.dumps(payload).encode(),
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(signature, expected)
# In your Flask handler:
@app.route('/webhooks/totopay', methods=['POST'])
def handle_webhook():
sig = request.headers.get('X-Webhook-Signature')
if not verify_webhook(request.json, sig, WEBHOOK_SECRET):
return 'Invalid signature', 400
event = request.json['event']
if event == 'deposit.completed':
data = request.json['data']
print(f"Deposit confirmed: {data['transaction_hash']}")
return 'OK', 200deposit.detectedA new deposit has been detected on-chain (0 confirmations).deposit.confirmingThe deposit has at least 1 confirmation but is not yet fully confirmed.deposit.completedThe deposit has reached the required number of confirmations.deposit.failedThe deposit could not be processed (e.g. chain reorg).customer.createdA new customer was created via the API.POST /api/v1/customers — you'll get wallet addresses for all networks.POST /api/v1/webhook-endpoints to listen for deposit.completed.sk_test_ keys and the simulate deposit endpoint.TotoPay API v1 — Questions? Contact support@totopay.net