Docs

Havala API Documentation

Take crypto without running nodes or holding keys. You create a fiat-denominated invoice; Havala leases a one-time deposit address, follows the confirmations on chain, and posts you a signed event when the money is final.

Quick Start

One signed POST creates an invoice. The amount goes up as minor units of a fiat currency and the buyer picks the coin later, at checkout โ€” so nothing here commits you to a chain.

Base URL

https://api2.havala.io

Authentication

Every gateway call under /api/v1 is signed. Three headers carry it:

  • X-API-Key โ€” the merchant point's API key. It selects the point, and every lookup is scoped to that point.
  • X-Signature โ€” t={unix_seconds},v1={hex}, where v1 is HMAC-SHA256 of the canonical string keyed on the point's API secret. Timestamps drift by at most 300 seconds.
  • Idempotency-Key โ€” required on POST, PUT, PATCH and DELETE. The same key replays the first response for 24 hours instead of creating a second invoice.
TypeScriptCreate an invoice
import { createHash, createHmac, randomUUID } from "node:crypto";

// Serialise once: the signature covers these exact bytes.
const body = JSON.stringify({
  orderId: "order-8814",
  amount: "12500",   // minor units of currency โ€” 12500 is USD 125.00
  currency: "USD",   // you price in fiat; the buyer picks the crypto at checkout
  returnUrl: "https://merchant.example.com/checkout/success",
});

// Canonical string: {t}\nPOST\n{path}\n{idempotencyKey}\n{sha256(body)}
// The idempotency line belongs to write methods; a GET signs four lines, not five.
const t = Math.floor(Date.now() / 1000);
const idempotencyKey = randomUUID();
const bodyHash = createHash("sha256").update(body).digest("hex");

const v1 = createHmac("sha256", process.env.HAVALA_API_SECRET)
  .update([t, "POST", "/api/v1/invoices", idempotencyKey, bodyHash].join("\n"))
  .digest("hex");

const response = await fetch("https://api2.havala.io/api/v1/invoices", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": process.env.HAVALA_API_KEY,
    "X-Signature": `t=${t},v1=${v1}`,
    "Idempotency-Key": idempotencyKey,
  },
  body,
});

// Every gateway response is wrapped: { success, data, timestamp, requestId }.
const { data: invoice } = await response.json();
// => { id: "clyv3n8x40001qh7m2k9d5b1t", referenceId: "INV-260826-041C", status: "OPEN", โ€ฆ }

Build with AI

These docs are machine-readable โ€” bring your assistant.