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/methodsPublic, 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_usdinteger required- Whole dollars, from 5 to 50,000. Not needed for a
kind: "deposit"method. coinstring required- From
/v1/payments/methods:BTC,XMR,USDT… networkstring required- From
/v1/payments/methods:bitcoin,monero,bsc… refund_addressstring- 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}
| status | What it means |
|---|---|
waiting | Nothing received yet. |
confirming | Seen on chain, waiting for requiredConfirmations. |
partial | Less than $5 confirmed: send the rest before partialDeadline, or it goes back to refundAddress. |
paid | Credited: creditedUsd, bonusUsd included. |
expired | Nothing arrived in time. Make another one. |
refunded | An 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
| Status | code | Why |
|---|---|---|
400 | invalid_input | Amount out of range, unknown coin or network, or a refund address that isn’t one. |
400 | limit_reached | Up to 3 invoices can be open at once: pay or let one expire. |
401 | unauthorized | Missing or wrong key. |
403 | forbidden | A reseller’s customer’s key. |
503 | unavailable | That network, or a reliable price, isn’t there right now: retry shortly. |