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.

Base URL
https://api.northvault.io/v1
Sandbox: use sk_test_… keys against the same base URL. Test-mode objects are fully isolated and free.

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.

shell
curl https://api.northvault.io/v1/charges \
  -u sk_live_3f9aK2…:
# the colon prevents curl asking for a password
All requests must use HTTPS. Plain-HTTP requests and requests with invalid keys return 401 unauthorized.

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.

shell
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.

CodeMeaning
200Success
400Invalid request — missing or malformed parameter
401Invalid or missing API key
402Charge declined after full cascade
404Resource doesn't exist
429Rate limited — back off and retry
5xxNorthvault-side problem (rare — see status page)
error object
{
  "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.

POST/v1/charges

Parameters

amount required

Integer, in the smallest currency unit (cents). 8900 = $89.00.

currency required

Three-letter ISO code. 130+ supported.

source required

A token (tok_…) created with your publishable key, or a saved card (card_…).

cascade optional, default true

Retry soft declines across your acquirer cascade automatically.

three_ds optional — auto | required | off

auto triggers 3-D Secure 2 only when the issuer or risk score requires it.

metadata optional

Key-value pairs echoed back on the object and in webhooks.

request
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
response · 200
{
  "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" }
}
GET/v1/charges/:id Retrieve a charge
GET/v1/charges?limit=25&starting_after=ch_… List charges (cursor pagination)

Refunds

Refund a charge in full or in part. Refunds settle back through the acquirer that approved the original charge.

POST/v1/refunds
request
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.

GET/v1/payouts
response · 200
{
  "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.

GET/v1/disputes
POST/v1/disputes/:id/evidence
request
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.

EventFires when
charge.approvedA charge succeeds (after any cascade)
charge.declinedAll cascade attempts declined
charge.refundedA refund settles
payout.paidA payout arrives at your bank
dispute.createdA new chargeback is filed
dispute.closedA dispute is won or lost
verify signature · node
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:

TokenBehaviour
tok_visaApproves on first attempt
tok_cascadeDeclines on MID 1, approves on MID 2
tok_decline_allDeclines on every cascade step (402)
tok_3ds_challengeForces a 3DS2 challenge flow
tok_disputeApproves, then files a dispute after 1 minute