Skip to content
RugWard
☰ Menu

RugWard Pay

REST API reference

Every RugWard Pay merchant endpoint with request and response examples, API key authentication, errors, limits and code in curl, Node.js, Python and PHP.

On this page

Basics#

Base URLhttps://rugward.com
FormatJSON in, JSON out. Send Content-Type: application/json with every body (otherwise 415). Bodies are limited to a few KB.
Authan API key in Authorization: Bearer rwp_… or x-api-key: rwp_…
AmountsUSD as a string with up to 2 decimals ("25", "25.50"); coin amounts are decimal strings
TimesUnix milliseconds (createdAt, expiresAt, paidAt)
Errors{"error": "human readable message"}, sometimes with "retry": true

Server to server only. Keep the API key on your server. Browsers cannot call the merchant API with a key (cross-origin requests are not allowed), and a key in a web page would be public.

API keys#

Create keys in the dashboard under API keys (sign-in required). A key looks like rwp_ followed by 40 letters and digits and is shown once: copy it to your server's secret store right away. RugWard keeps only a SHA-256 hash, so a lost key cannot be shown again: create a new one and revoke the old one. Up to 10 keys per merchant; the dashboard shows each key's prefix and when it was last used.

API keys and webhook in the dashboard
Create or revoke API keys and set up the webhook

What a key can and cannot do:

A key canA key cannot
create, list, read and cancel invoiceschange settings or receiving addresses
create, list and turn off payment linkscreate, list or revoke API keys
change or read the webhook or its secret
create test invoices

So a leaked key cannot redirect your money: receiving addresses can only be changed by signing in with your wallet.

Endpoints#

Method and pathAuthPurpose
POST /api/pay/merchant/invoiceskey or sessionCreate an invoice
GET /api/pay/merchant/invoiceskey or sessionList invoices, newest first, 50 per page
GET /api/pay/merchant/invoices/:idkey or sessionRead one invoice with quotes and payments (also re-checks the chain)
POST /api/pay/merchant/invoices/:id/cancelkey or sessionCancel an open invoice without payments
GET /api/pay/merchant/linkskey or sessionList payment links
POST /api/pay/merchant/linkskey or sessionCreate a payment link, or turn one off
GET /api/pay/proof/:idpublicPayment proof (paid or overpaid invoices only)

Settings, API keys, the webhook and unmatched payments are managed in the dashboard (wallet session only).

Create an invoice#

POST /api/pay/merchant/invoices

FieldTypeRequiredRules
amountUsdstring or numberyes1 to 50000, max 2 decimals
orderIdstringno1–64 chars: letters, digits, . _ - : # /
descriptionstringnomax 200 chars, shown to the buyer
redirectUrlstringnohttps:// URL (max 500 chars), shown after payment
expiresMinintegerno15 to 10080 (7 days); default 60
curl · create an invoice
curl -X POST https://rugward.com/api/pay/merchant/invoices \
  -H "Authorization: Bearer $RUGWARD_PAY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amountUsd": "25.00",
    "orderId": "1234",
    "description": "1 x T-shirt, size M",
    "redirectUrl": "https://shop.example/thanks?order=1234",
    "expiresMin": 60
  }'
201 Created
{
  "id": "Zx3kQ8pL2mN7vR1tY5wB9c",
  "url": "https://rugward.com/pay/i/Zx3kQ8pL2mN7vR1tY5wB9c",
  "status": "open",
  "expiresAt": 1793326882069,
  "assets": ["BTC", "ETH-8453", "USDC-8453", "USDT-56", "SOL", "USDC-SOL"]
}

Send the buyer to url. assets lists the asset ids the buyer can choose from (your enabled coins that have a receiving address).

The same request in other languages:

Node.js 18+ (server side only)
// Never put the API key in a browser page: call RugWard Pay from your server.
const res = await fetch("https://rugward.com/api/pay/merchant/invoices", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RUGWARD_PAY_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ amountUsd: "25.00", orderId: "1234", expiresMin: 60 }),
});
const body = await res.json();
if (!res.ok) throw new Error(body.error);
// Save body.id with your order, then send the buyer to body.url
console.log(body.id, body.url);
Python 3 (requests)
import os, requests

r = requests.post(
    "https://rugward.com/api/pay/merchant/invoices",
    headers={"Authorization": f"Bearer {os.environ['RUGWARD_PAY_KEY']}"},
    json={"amountUsd": "25.00", "orderId": "1234", "expiresMin": 60},
    timeout=15,
)
data = r.json()
if r.status_code != 201:
    raise RuntimeError(data.get("error"))
print(data["id"], data["url"])  # store the id, redirect the buyer to the url
PHP 8 (cURL)
<?php
$ch = curl_init("https://rugward.com/api/pay/merchant/invoices");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("RUGWARD_PAY_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode(["amountUsd" => "25.00", "orderId" => "1234", "expiresMin" => 60]),
]);
$data = json_decode(curl_exec($ch), true);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 201) { throw new Exception($data["error"] ?? "RugWard Pay error"); }
header("Location: " . $data["url"]); // send the buyer to the hosted checkout

Read an invoice#

GET /api/pay/merchant/invoices/:id. Reading an invoice also checks the blockchains for new payments, so this is the right call to confirm a payment before shipping (together with webhooks).

curl · read one invoice
curl https://rugward.com/api/pay/merchant/invoices/Zx3kQ8pL2mN7vR1tY5wB9c \
  -H "Authorization: Bearer $RUGWARD_PAY_KEY"
200 OK
{
  "invoice": {
    "id": "Zx3kQ8pL2mN7vR1tY5wB9c",
    "status": "paid",
    "amountUsd": "25.00",
    "orderId": "1234",
    "description": "1 x T-shirt, size M",
    "redirectUrl": "https://shop.example/thanks?order=1234",
    "createdAt": 1793323282069,
    "expiresAt": 1793326882069,
    "paidAt": 1793324100512,
    "assets": ["BTC", "ETH-8453", "USDC-8453", "USDT-56", "SOL", "USDC-SOL"],
    "test": false,
    "quotes": [
      {
        "id": 4711,
        "asset": "USDC-8453",
        "amount": "25.000629",
        "rateUsd": "1",
        "address": "0xYourMerchantAddress…",
        "expiresAt": 1793325082069
      }
    ],
    "payments": [
      {
        "txid": "0x…",
        "asset": "USDC-8453",
        "amount": "24.875626",
        "confirmations": 30,
        "required": 30,
        "confirmed": true,
        "seenAt": 1793324012000,
        "explorer": "https://basescan.org/tx/0x…"
      }
    ]
  }
}
  • quotes: one entry per coin the buyer picked (amount, rate, receiving address, rate-lock expiry).
  • payments: every transaction seen for this invoice, with confirmations, the required number and confirmed.
  • On Base splitter payments amount is what reached you (99.5%).

List invoices#

GET /api/pay/merchant/invoices?before=<createdAt>: 50 per page, newest first. To get the next page pass the createdAt of the last invoice you received.

curl · list invoices (50 per page, newest first)
curl "https://rugward.com/api/pay/merchant/invoices" \
  -H "Authorization: Bearer $RUGWARD_PAY_KEY"

# next page: pass the createdAt of the last invoice you received
curl "https://rugward.com/api/pay/merchant/invoices?before=1793323282069" \
  -H "Authorization: Bearer $RUGWARD_PAY_KEY"
200 OK
{
  "invoices": [
    {
      "id": "Zx3kQ8pL2mN7vR1tY5wB9c",
      "status": "open",
      "amountUsd": "25.00",
      "orderId": "1234",
      "description": "1 x T-shirt, size M",
      "createdAt": 1793323282069,
      "expiresAt": 1793326882069,
      "paidAt": null
    }
  ]
}

Cancel an invoice#

POST /api/pay/merchant/invoices/:id/cancel (no body). Works only while the invoice is open and no payment was seen; otherwise 409.

curl · cancel an open invoice
curl -X POST https://rugward.com/api/pay/merchant/invoices/Zx3kQ8pL2mN7vR1tY5wB9c/cancel \
  -H "Authorization: Bearer $RUGWARD_PAY_KEY"

# 200 {"ok":true}
# 409 {"error":"Only your open invoices without payments can be canceled."}

POST /api/pay/merchant/links with {amountUsd, description?, redirectUrl?} creates a reusable link; {"deactivate": "<link id>"} turns one off. GET lists up to 100 links with uses, active and createdAt. The merchant terms must be accepted first. See Payment links.

curl · create a reusable payment link
curl -X POST https://rugward.com/api/pay/merchant/links \
  -H "Authorization: Bearer $RUGWARD_PAY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amountUsd": "15", "description": "Monthly membership", "redirectUrl": "https://shop.example/welcome"}'

# 201 {"id":"k33JZ0ij5F2yLDprwrQgjN","url":"https://rugward.com/pay/l/k33JZ0ij5F2yLDprwrQgjN"}

# list your links
curl https://rugward.com/api/pay/merchant/links -H "Authorization: Bearer $RUGWARD_PAY_KEY"

# turn one off
curl -X POST https://rugward.com/api/pay/merchant/links \
  -H "Authorization: Bearer $RUGWARD_PAY_KEY" -H "Content-Type: application/json" \
  -d '{"deactivate": "k33JZ0ij5F2yLDprwrQgjN"}'

Errors#

Error response (any 4xx/5xx)
{ "error": "Amount in USD, e.g. 25 or 25.50." }

// some temporary errors also carry  "retry": true
HTTPMeaningWhat to do
400invalid input (the message says which field)fix the request
401missing or invalid API keycheck the key; it may have been revoked
403cross-site request refused, merchant terms not accepted, account suspended, or action not allowed for keysread the message
404not found or not yourscheck the id
409conflict (for example canceling a paid invoice, or 100 active links already)read the message
415body is not JSONsend Content-Type: application/json
429rate limit, or 500 invoices in the last hourwait and retry with backoff
451not available in your region—
503 with "retry": truea blockchain or price source is temporarily unreachableretry after a few seconds

Limits#

  • Request rate: about 20 requests per minute per IP address across all /api/pay/* endpoints, plus a cap of 30 per minute per endpoint group. Use webhooks instead of polling; if you poll, once a minute per open invoice is plenty.
  • Invoices: 500 per merchant per hour.
  • Payment links: 100 active per merchant; each link creates at most 100 invoices per hour.

Integration checklist#

  1. Create the invoice from your server when the customer checks out; save id with your order.
  2. Redirect the customer to url.
  3. On invoice.paid or invoice.overpaid (webhook), verify the signature, then re-read the invoice with GET /api/pay/merchant/invoices/:id and check status and amountUsd before shipping.
  4. Handle underpaid, late and expired (see Statuses).
  5. Make your handler idempotent: the same event can arrive more than once.

Last updated: October 30, 2026

REST API reference · RugWard Documentation | RugWard