Get API Keys

The Crypto Payment API You Can Read in Ten Minutes

Two calls to take money, one webhook to trust it. Everything below is the real API.

Authentication

Every request from your server uses HTTP Basic auth: your project ID as the user name and your project secret as the password. Keep the secret on your server; it also signs your webhooks.

https://payments.rubysoft.io/api

HTTP
Authorization: Basic base64(PROJECT_ID:PROJECT_SECRET)

Create an Invoice

Use an invoice when the customer pays for one order. Pass your own 24-character order ID as payload, the price in USD, how far an amount may fall short (0 to 5%), the expiry time and the URL that receives this invoice's webhooks.

payloadYour order ID, 24 hexadecimal characters (a MongoDB ObjectId works)
meta[price]Price in USD
meta[tolerancePercent]Allowed shortfall, 0 to 5
meta[expiresAt]Expiry, ISO 8601, in the future
meta[webhookUrl]Where this invoice's events are sent
curl -G https://payments.rubysoft.io/api/invoice/load \
  -u "$PROJECT_ID:$PROJECT_SECRET" \
  --data-urlencode "payload=65f2c1a9e4b0d3f7a2c91e04" \
  --data-urlencode "meta[price]=120" \
  --data-urlencode "meta[tolerancePercent]=1" \
  --data-urlencode "meta[expiresAt]=2026-12-01T12:00:00Z" \
  --data-urlencode "meta[webhookUrl]=https://shop.example/webhooks/rubynex"

The response carries an addresses object keyed by network. Show your customer the networks you want to offer.

200 OK
{
  "id": "0b6f3c1e-8a52-4d7e-9c41-2f6a8d0e5b17",
  "payload": "65f2c1a9e4b0d3f7a2c91e04",
  "meta": {
    "type": "invoice",
    "status": "pending",
    "price": "120",
    "paid": "0",
    "expiresAt": "2026-12-01T12:00:00.000Z"
  },
  "addresses": {
    "tron": "T…",
    "ethereum": "0x…",
    "bsc": "0x…",
    "bitcoin": "bc1q…"
  }
}

Permanent Deposit Addresses

Use permanent addresses for top-ups: wallets, games, exchanges, subscriptions. Pass your customer's 24-character ID as payload and get the same addresses every time.

cURL
curl -G https://payments.rubysoft.io/api/charge/load \
  -u "$PROJECT_ID:$PROJECT_SECRET" \
  --data-urlencode "payload=66a0b7d2c5e8f1a3b6d904c7"

# the same customer ID always returns the same addresses

Invoice Statuses

pendingWaiting for payment
paidThe full price arrived
underpaidLess than the price arrived
overpaidMore than 1% above the price arrived
expiredNo payment before the expiry time

Webhooks

Each event is a POST with a JSON body and an X-Webhook-Signature header: the HMAC-SHA256 of the raw body, keyed with your project secret decoded from hex, written as hex. Answer with any 2xx status. Anything else is retried: invoice events every 15 seconds until delivered, payment events every 10 minutes, up to 150 times.

Events

invoice:<status>An invoice changed status
pending-paymentA payment was seen and is waiting for confirmations
confirmed-paymentA payment was confirmed and credited
failed-paymentA payment could not be processed
Webhook
POST /webhooks/rubynex
Content-Type: application/json
X-Webhook-Signature: 9c1fd2…e07a

{
  "id": "4e1a…c93f",
  "message": {
    "event": "invoice:paid",
    "data": { "id": "0b6f3c1e-…", "payload": "65f2c1a9e4b0d3f7a2c91e04" }
  },
  "attempt": 0,
  "timestamp": 1764590400
}

Verify the Signature

import crypto from 'node:crypto';
import express from 'express';

const secret = Buffer.from(process.env.RUBYNEX_SECRET, 'hex');

// keep the raw body: the signature covers its exact bytes
app.post('/webhooks/rubynex', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = crypto.createHmac('sha256', secret).update(req.body).digest('hex');
  const given = req.get('X-Webhook-Signature') ?? '';
  if (given.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected))) {
    return res.sendStatus(401);
  }
  const { message } = JSON.parse(req.body);
  if (message.event === 'invoice:paid') markOrderPaid(message.data.payload);
  res.sendStatus(200);
});

Confirmations by Network

NetworkCoinsConfirmationsTime to Credit
TRONTRXUSDT1about 3 s
EthereumETHUSDTUSDCDAI5about 1 min
BNB Smart ChainBNBUSDTUSDCDAI10about 8 s
PolygonPOLUSDTUSDCDAI20about 40 s
BaseETHUSDTUSDC10about 20 s
BitcoinBTC1about 10 min
XRP LedgerXRP1about 4 s
DogecoinDOGE3about 3 min

Limits Worth Knowing

  • Payments of $1 or less are ignored as dust
  • Invoice shortfall tolerance: up to 5%
  • An invoice is overpaid when more than 1% above its price arrives
  • A project's secret can be rotated once every 5 minutes

Ready for Your Keys?

We create your project and send you its ID and secret.

Get API Keys