Account

Payments API

Top up a balance from code, in crypto, through our own payment gateway: no third party, no account anywhere else.

The same invoices as Dashboard → Billing, made and followed with an API key of the account, or a reseller’s management key (Reseller API). What is paid in is credited to that account’s balance, with the same minimum and first top-up bonus as on the site (Billing). A reseller’s customer’s key can’t top up: the money would go to the reseller.

Coins and networks

GET /v1/payments/methods

curl https://api.unaligned.pw/v1/payments/methods

Public, no key. kind: "invoice": paid through an invoice, once, before it expires. kind: "deposit": paid to the account’s own fixed address on that network, for good, anything from $1 credited 1:1. You don’t have to tell them apart: POST /v1/payments answers either way.

Create an invoice

POST /v1/payments

amount_usd integer required
Whole dollars, from 5 to 50,000. Not needed for a kind: "deposit" method.
coin string required
From /v1/payments/methods: BTC, XMR, USDT…
network string required
From /v1/payments/methods: bitcoin, monero, bsc…
refund_address string
Your own address on that network, where an incomplete payment goes back after 60 minutes.
curl https://api.unaligned.pw/v1/payments \
  -H "Authorization: Bearer $UNALIGNED_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "amount_usd": 50, "coin": "USDT", "network": "bsc" }'

Send exactly amountCrypto of coin to address, on network, before expiresAt (milliseconds since 1970). The rate is locked for 30 minutes; a payment arriving later is credited at the rate of the moment.

The address takes this coin on this network only. Another coin, or the right coin on another network, is not credited.

USDT and USDC on Solana

These go to the account’s own fixed address instead of an invoice: the same call answers 200 with kind: "deposit" and that address. It never expires, takes both coins, and credits anything from $1; amount_usd is optional.

curl https://api.unaligned.pw/v1/payments \
  -H "Authorization: Bearer $UNALIGNED_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "coin": "USDT", "network": "solana" }'

Follow it

GET /v1/payments/{id}

statusWhat it means
waitingNothing received yet.
confirmingSeen on chain, waiting for requiredConfirmations.
partialLess than $5 confirmed: send the rest before partialDeadline, or it goes back to refundAddress.
paidCredited: creditedUsd, bonusUsd included.
expiredNothing arrived in time. Make another one.
refundedAn incomplete payment went back to refundAddress.

Poll it every 15 to 60 seconds until paid (or expired). GET /v1/payments?limit=10 lists the latest, newest first.

Fixed deposit addresses

GET /v1/payments/deposit/{network}

The same fixed address, and what arrived on it (deposits), at any time: made on first use and kept.

Example

const api = (path, body) =>
  fetch("https://api.unaligned.pw/v1" + path, {
    method: body ? "POST" : "GET",
    headers: {
      Authorization: "Bearer " + process.env.UNALIGNED_KEY,
      "Content-Type": "application/json"
    },
    body: body && JSON.stringify(body)
  }).then((r) => r.json());

const invoice = await api("/payments", { amount_usd: 50, coin: "USDT", network: "bsc" });
console.log(`Send ${invoice.amountCrypto} USDT (BEP-20) to ${invoice.address}`);

// Then, until it's done:
let status;
do {
  await new Promise((r) => setTimeout(r, 15000));
  ({ status } = await api(`/payments/${invoice.id}`));
} while (!["paid", "expired", "refunded"].includes(status));

Errors

StatuscodeWhy
400invalid_inputAmount out of range, unknown coin or network, or a refund address that isn’t one.
400limit_reachedUp to 3 invoices can be open at once: pay or let one expire.
401unauthorizedMissing or wrong key.
403forbiddenA reseller’s customer’s key.
503unavailableThat network, or a reliable price, isn’t there right now: retry shortly.