Merchant guide

Step-by-step guide: registration, API, checkout, server notifications, withdrawals — ArtCloud Crypto Pay (Solana).

Save as PDF: Ctrl+P (Cmd+P on Mac) → Save as PDF.

1. What is ArtCloud Crypto Pay

ArtCloud Crypto Pay landing page

ArtCloud Crypto Pay is a hosted payment platform for online merchants. You create a payment request through the API (application programming interface), send the buyer to our checkout page, and receive a signed server notification when funds arrive.

On production today we support Solana only: native SOL, USDT (SOLANA-USDT), and USDC (SOLANA-USDC). Other networks are available only by separate agreement with the operator.

  • Hosted checkout — no need to build a wallet UI yourself
  • Merchant dashboard — invoices, balances, withdrawals
  • Signed server notifications (HMAC) for reliable order fulfillment

2. Registration

Merchant registration form

Open the registration page and fill in email, display name, password, and Merchant ID. Merchant ID is a unique Latin identifier for your store (API field slug) — choose it once; it cannot be changed later.

  1. Go to /cabinet/register (or click «Get started» on the landing page)
  2. Enter Merchant ID — e.g. myshop (letters, digits, hyphens)
  3. Accept the Terms of Service and Privacy Policy — required
  4. Optional: webhook URL during signup; you can set it later in Settings

After registration you get the free plan and can sign in to the merchant dashboard immediately.

3. Sign in

Merchant dashboard sign-in form

Open /cabinet (or /cabinet/login — same page). Enter the email and password from registration. After sign-in you land on Overview.

4. Merchant dashboard overview

Dashboard overview tab

The dashboard is at /cabinet. After login the sidebar shows: Overview, Invoices, Transactions, Wallets, Payouts, Rates, Billing, Settings.

  • Overview — volume, conversion, alerts (low fee deposit, open invoices)
  • Invoices — list and manual invoice creation
  • Transactions — paid and partially paid payments
  • Wallets — SOL / USDT / USDC balances and fee deposit (SOL for gas)
  • Payouts — manual withdrawals and history
  • Rates — fiat/crypto reference rates
  • Billing — SaaS plan and platform invoices
  • Settings — API keys, webhook URL, password

5. Settings: API key and notifications

Settings — API key and webhook

Open Settings in the sidebar. Here you configure integration credentials and the default notification URL.

  • API key — new keys start with ac_live_ (legacy bp_live_ keys remain valid). Use header X-Artcloud-Api-Key (current) or legacy X-Braiora-Api-Key / X-Shkeeper-Api-Key — all accepted. When you rotate the key, the full value is shown once — save it immediately.
  • Webhook URL — default address for server notifications (callback). Can be overridden per invoice via callback_url in the API request.
  • Webhook secret — used to verify HMAC signature on incoming notifications. Shown in Settings after save.

6. Create a payment via API

Two equivalent ways exist: compatibility endpoint (SHKeeper-shaped) and modern POST /v1/invoices. Base URL on production: https://pay.braiora.com

Compatibility (recommended for existing integrations):

Create SOLANA-USDT payment request
API=https://pay.braiora.com
KEY=ac_live_YOUR_KEY   # legacy bp_live_ keys also work

curl -sS -X POST "$API/api/v1/SOLANA-USDT/payment_request" \
  -H "Content-Type: application/json" \
  -H "X-Artcloud-Api-Key: $KEY" \ # legacy: X-Braiora-Api-Key / X-Shkeeper-Api-Key
  -d '{
    "external_id": "order-1001",
    "amount": "25.00",
    "fiat": "USD",
    "callback_url": "https://merchant.example/hooks/artcloud"
  }'

Response includes wallet address, crypto amount, checkout_url (link to checkout page), and artcloud_invoice_id (legacy braiora_invoice_id also present with the same value). Supported {crypto} values today: SOL, SOLANA-USDT, SOLANA-USDC.

Modern endpoint (optional crypto — buyer can choose on checkout if omitted):

curl -sS -X POST "$API/v1/invoices" \
  -H "Content-Type: application/json" \
  -H "X-Artcloud-Api-Key: $KEY" \ # legacy: X-Braiora-Api-Key / X-Shkeeper-Api-Key
  -d '{
    "external_id": "order-1001",
    "amount": "25.00",
    "fiat": "USD",
    "callback_url": "https://merchant.example/hooks/artcloud",
    "crypto": "SOLANA-USDT"
  }'

7. Buyer pays on the checkout page

Checkout payment screen

Redirect the buyer to checkout_url from the API response (or checkoutUrl in the modern format). The page shows the exact amount, QR code, and Solana address.

  1. Buyer sends the exact crypto amount to the shown address
  2. Status updates automatically as confirmations arrive
  3. When paid, your server receives a notification (see next section)

8. Server notifications and signature verification

When an invoice becomes paid, overpaid, or partially paid, ArtCloud Crypto Pay sends a POST request with JSON to your webhook URL (Settings) or per-invoice callback_url.

Headers: X-Artcloud-Signature (current) plus legacy X-Braiora-Signature / X-Shkeeper-Signature — all carry the same HMAC-SHA256 hex of the raw request body, keyed with your webhook secret.

Typical notification body
{
  "id": "<engine id>",
  "invoice_id": "<invoice uuid>",
  "external_id": "order-1001",
  "status": "paid",
  "paid": true,
  "crypto": "SOLANA-USDT",
  "amount": "...",
  "fiat": "USD",
  "balance_fiat": 25,
  "wallet": "..."
}

Node.js example with idempotency (process each external_id + status once):

import crypto from "node:crypto";
import express from "express";

const app = express();
const processed = new Set(); // use DB in production

function verifySignature(secret, rawBody, signature) {
  if (!signature) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  const sig = Buffer.from(signature.trim(), "utf8");
  const exp = Buffer.from(expected, "utf8");
  // timingSafeEqual throws on length mismatch — check first
  if (sig.length !== exp.length) return false;
  return crypto.timingSafeEqual(exp, sig);
}

app.post(
  "/hooks/artcloud",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const sig =
      req.header("X-Artcloud-Signature") ??
      req.header("X-Braiora-Signature") ??
      req.header("X-Shkeeper-Signature");
    if (!verifySignature(process.env.WEBHOOK_SECRET, req.body, sig)) {
      return res.status(401).send("invalid signature");
    }
    const event = JSON.parse(req.body.toString("utf8"));
    const key = `${event.external_id}:${event.status}`;
    if (processed.has(key)) return res.sendStatus(200);
    if (event.paid) {
      // fulfill order event.external_id
      processed.add(key);
    }
    res.sendStatus(200);
  },
);

9. Invoice statuses in the dashboard

Invoices list with statuses
  • Open / pending — waiting for payment
  • Partial — received less than required (policy depends on your confirmation settings)
  • Paid — full payment received; notification sent
  • Overpaid — more than invoice amount (may be credited per policy)
  • Failed / expired — invoice no longer accepts payment

Use Transactions for paid and partial payments; Invoices shows the full list including open ones.

10. Fee deposit (SOL for gas)

Wallets — fee deposit card

Solana network fees (gas) for sweeps and withdrawals are paid from a shared fee deposit wallet — not from your USDT/USDC balance. Top it up with SOL.

  • Wallets tab → Fee deposit (SOL) card — full address, copy, QR in modal
  • Overview shows a warning when balance is low (~0.01 SOL) or critical (~0.005 SOL)
  • Without SOL on the fee deposit, withdrawals may fail even if token balance is sufficient

11. Withdrawals (manual payouts)

Payouts form and history

Open Payouts, choose asset (SOL / SOLANA-USDT / SOLANA-USDC), enter amount and destination address. The form shows platform fee preview. History lists status: pending, submitted, completed, failed.

Autopayout (automatic withdrawal when balance exceeds a threshold) can be configured in wallet policy settings. On staging it may execute automatically; treat it carefully — set destination and minimum only when you intend automatic drains.

12. Billing and plans

Billing tab

Self-serve registration starts on the free plan. Paid plans (starter, pro) may be offered via invite link. Billing tab shows current plan, subscription status, and platform invoices for SaaS fees.

Platform invoices are paid like any merchant invoice — via checkout in SOLANA-USDT. A suspended banner appears if subscription is past due beyond grace period.

13. API reference (OpenAPI)

Interactive API documentation

Full interactive reference with try-it-out: https://pay.braiora.com/api/docs

Key merchant routes: POST /v1/invoices, GET /v1/invoices/:id, POST /api/v1/{crypto}/payment_request. Cabinet routes use JWT after POST /v1/auth/login.

14. Troubleshooting

  • 401 on API — check API key header and that the key was not rotated without updating your server
  • No notification received — verify webhook URL in Settings, firewall allows POST from pay.braiora.com, handler returns 200
  • Invalid signature — use raw body (not parsed JSON) for HMAC; compare X-Artcloud-Signature or legacy X-Braiora-Signature / X-Shkeeper-Signature
  • Payment stuck pending — wait for Solana confirmations; check invoice policy (confirmations count) in Wallets → manage
  • Withdrawal failed — top up fee deposit SOL; check destination address and minimum amount
  • Balances show «updating» — engine sync in progress; refresh after a few minutes