API Reference
The Northvault API is a predictable REST API: resource-oriented URLs, JSON request and response bodies, and standard HTTP status codes. Every account gets a full sandbox — the same API surface with test keys, so you can integrate before underwriting completes.
https://api.northvault.io/v1
Authentication
Authenticate with your secret key via HTTP Basic auth — the key is the username, the password is empty. Keys are issued in the dashboard under Developers → API keys. Never ship a secret key in client-side code; use the publishable key (pk_…) for tokenization only.
curl https://api.northvault.io/v1/charges \ -u sk_live_3f9aK2…: # the colon prevents curl asking for a password
Idempotency
Pass an Idempotency-Key header on any POST to safely retry without double-charging. Keys are stored for 24 hours; replays return the original response.
curl https://api.northvault.io/v1/charges \ -u sk_live_3f9aK2…: \ -H "Idempotency-Key: order-8421-attempt-1" \ -d amount=8900 -d currency=usd -d source=tok_visa
Errors
Northvault uses conventional HTTP codes and returns a machine-readable error object.
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Invalid request — missing or malformed parameter |
| 401 | Invalid or missing API key |
| 402 | Charge declined after full cascade |
| 404 | Resource doesn't exist |
| 429 | Rate limited — back off and retry |
| 5xx | Northvault-side problem (rare — see status page) |
{ "error": { "type": "card_error", "code": "card_declined", "decline_code": "do_not_honor", "message": "The card was declined by all acquirers in the cascade.", "cascade_attempts": 3 } }
Charges
A charge represents a single payment attempt against a tokenized card. With cascade=true, a decline is automatically retried across your acquirer stack.
Parameters
Integer, in the smallest currency unit (cents). 8900 = $89.00.
Three-letter ISO code. 130+ supported.
A token (tok_…) created with your publishable key, or a saved card (card_…).
Retry soft declines across your acquirer cascade automatically.
auto triggers 3-D Secure 2 only when the issuer or risk score requires it.
Key-value pairs echoed back on the object and in webhooks.
curl https://api.northvault.io/v1/charges \ -u sk_live_3f9aK2…: \ -d amount=8900 \ -d currency=usd \ -d source=tok_visa \ -d cascade=true \ -d "metadata[order_id]"=8421
{ "id": "ch_1QspeedrunXYZ", "object": "charge", "amount": 8900, "currency": "usd", "status": "approved", "acquirer": "stronghold_bank", "cascade_step": 2, "risk_score": 0.07, "fee": 336, "net": 8564, "metadata": { "order_id": "8421" } }
Refunds
Refund a charge in full or in part. Refunds settle back through the acquirer that approved the original charge.
curl https://api.northvault.io/v1/refunds \ -u sk_live_3f9aK2…: \ -d charge=ch_1QspeedrunXYZ \ -d amount=4450 # omit for full refund
Payouts
Payouts sweep your available balance to your bank on your settlement schedule (default daily, T+1). They're created automatically — the API is read-only.
{ "object": "list", "data": [{ "id": "po_5519", "amount": 5636083, "currency": "usd", "status": "in_transit", "arrival_date": 1781136000, "destination": "ba_chase_6712" }] }
Disputes
When a cardholder disputes a charge you'll receive a dispute.created webhook. Submit evidence before respond_by or the case is forfeited.
curl https://api.northvault.io/v1/disputes/dp_2210/evidence \ -u sk_live_3f9aK2…: \ -d "receipt"=file_8M2… \ -d "shipping_tracking"="1Z999AA10123456784" \ -d "customer_communication"=file_9K1…
Cascading
Cascading is Northvault's automatic decline-recovery engine. When an acquirer soft-declines (insufficient funds is not retried; "do not honor", timeouts and issuer-unavailable are), the charge is re-attempted on the next MID in your configured order — within the same API call, typically adding <300ms.
- Order is configured per-merchant in Dashboard → Routing & MIDs.
- The response reports cascade_step and the winning acquirer.
- Hard declines (stolen card, fraud) stop the cascade immediately — retrying those damages MID health.
- Velocity guard caps same-card retries at 3 per hour regardless of configuration.
Webhooks
Subscribe to events in the dashboard. Every delivery is signed — verify the NV-Signature header (HMAC-SHA256 of the raw body with your endpoint secret) before trusting the payload.
| Event | Fires when |
|---|---|
| charge.approved | A charge succeeds (after any cascade) |
| charge.declined | All cascade attempts declined |
| charge.refunded | A refund settles |
| payout.paid | A payout arrives at your bank |
| dispute.created | A new chargeback is filed |
| dispute.closed | A dispute is won or lost |
const sig = req.headers['nv-signature']; const expected = crypto .createHmac('sha256', process.env.NV_WEBHOOK_SECRET) .update(rawBody) .digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) return res.status(400).end();
Deliveries retry with exponential backoff for 24h until your endpoint returns 2xx.
Test cards
In sandbox, use these tokens to simulate every path:
| Token | Behaviour |
|---|---|
| tok_visa | Approves on first attempt |
| tok_cascade | Declines on MID 1, approves on MID 2 |
| tok_decline_all | Declines on every cascade step (402) |
| tok_3ds_challenge | Forces a 3DS2 challenge flow |
| tok_dispute | Approves, then files a dispute after 1 minute |