Advance Bit Coingateway

Developer guide · REST API v1

Take crypto payments from your own site

One call makes an invoice; your customer pays on a hosted page or by QR; a signed webhook tells your server the moment it confirms on Solana. Every payment goes straight to your own wallet: the gateway never holds it.

Quick start

  1. Add a store in the dashboard with the Solana wallet your money should go to. A public address only: never a seed phrase.
  2. Create an API key for that store (Dashboard → API keys). It is shown once; keep it on your server.
  3. Make an invoice and send your customer to its pay_page.
  4. Get told when it's paid: a signed invoice.confirmed webhook, or poll GET /api/v1/invoices/:id.
curl -X POST https://gateway.advancebitcoin.org/api/v1/invoices \
  -H "Authorization: Bearer abcpay_live_..." \
  -H "Content-Type: application/json" \
  -d '{"amount": 250, "order_id": "order-1042", "success_url": "https://yourshop.com/thanks"}'

Reply 201:

{
  "id": "fe4bd314-4288-4fbc-9378-c6a402a52bc6",
  "status": "pending",
  "amount": 250.017,
  "token_mint": "3BWcLccJqqiy2k3QsfnmZpsrKTH1jjVCNTFkVQ8dcY6d",
  "order_id": "order-1042",
  "description": null,
  "fiat_amount": null,
  "fiat_currency": null,
  "test_mode": false,
  "reference": "H8Doj858tCc96ZWsg3m3XX5fWcyGMgWQviTtjSFD2Dtx",
  "recipient": "<your store wallet>",
  "pay_page": "https://gateway.advancebitcoin.org/pay/fe4bd314-4288-4fbc-9378-c6a402a52bc6",
  "pay_url": "solana:<your store wallet>?amount=250.017&spl-token=3BWc...&reference=H8Do...",
  "expires_at": "2026-10-02T12:15:00.000Z",
  "created_at": "2026-10-02T12:00:00.000Z"
}

The amount gets a few extra digits (250.017): every open invoice has a unique amount, so even a payment sent by hand, without the QR, is matched to the right invoice.

Keys and test mode

Send the store's key on every call as Authorization: Bearer abcpay_…. Only a hash of each key is stored; revoke one any time on the API keys page.

Test mode is a switch in the dashboard. Test stores run on Solana devnet with free test coins, and their keys start abcpay_test_. Invoices, links and webhooks from them carry "test_mode": true: check it and never ship an order for a test payment. Test SOL comes from faucet.solana.com and test USDC from faucet.circle.com; switch the paying wallet to devnet (Phantom: Settings → Developer Settings → Testnet Mode).

Invoices

POST /api/v1/invoices

FieldTypeWhat it does
amountnumberAmount in token units. Required unless you send fiat_amount.
fiat_amountnumberA dollar price instead of amount (see Prices in dollars). Send with fiat_currency: "USD".
token_mintstring | nullOmit for the store's default ($ABC on live stores). null = SOL. Or any SPL mint: USDC EPjFWdd5…Dt1v, USDT Es9vMFrz…wNYB.
order_idstringYour own reference, echoed back in the webhook.
descriptionstringWhat it's for; shown to the customer on the pay page and receipt.
success_url / cancel_urlstringWhere to send the customer after paying / if they leave.

GET /api/v1/invoices/:id

Checks the chain first, so the status is current. Adds amount_paid, tx_signature, payer_wallet and customer_note.

POST /api/v1/invoices/:id/cancel

Cancels a pending invoice. A confirmed one can never be cancelled.

Statuses: pending → confirmed, or expired after 15 minutes unpaid, or cancelled. A payment that lands in the last seconds is still credited for 24 hours after expiry.

Prices in dollars

Send fiat_amount with fiat_currency: "USD" and the customer pays the matching amount of the token at today's price, fixed for the invoice's 15 minutes. USDC and USDT count as exactly $1. SOL uses the middle of four public price sources (Coinbase, Kraken, Jupiter, CoinGecko); with none answering, no invoice is made rather than a wrong one. Amounts round up, never short. Dollar pricing in $ABC switches on by itself once $ABC trades with real depth.

curl -X POST https://gateway.advancebitcoin.org/api/v1/invoices \
  -H "Authorization: Bearer abcpay_live_..." \
  -H "Content-Type: application/json" \
  -d '{"fiat_amount": 25, "fiat_currency": "USD", "token_mint": null, "description": "Logo design"}'
// token_mint null = paid in SOL; the reply's amount is the SOL for $25 right now

Website button

No developer? Put a “Pay with crypto” button on any website (WordPress, Shopify custom code, Wix, Squarespace or plain HTML) by pasting one line where the button should appear. It shows the link's price and opens its secure checkout in a new tab. Copy it, with your link's id filled in, from Dashboard → Payment links → Website button.

<script src="https://gateway.advancebitcoin.org/pay-button.js" data-abc-link="YOUR_LINK_ID" async></script>

Optional: data-label="Buy now" and data-theme="gold", "dark" or "light". The button never touches payments, wallets or cookies; the public facts it shows come from GET /api/link/:slug.

Webhooks

Set a webhook URL on the store. When a payment confirms we POST invoice.confirmed, signed with the store's webhook secret as X-ABC-Signature: sha256=<hex HMAC of the raw body>. If your server doesn't answer 2xx we try again for about a day (1 min, 5 min, 30 min, 2 h, 12 h), so make your handler safe to run twice. Confirmation runs every minute even when nobody has the pay page open.

{
  "event": "invoice.confirmed",
  "invoice": {
    "id": "fe4bd314-4288-4fbc-9378-c6a402a52bc6",
    "order_id": "order-1042",
    "amount": 250.017,
    "token_mint": "3BWcLccJqqiy2k3QsfnmZpsrKTH1jjVCNTFkVQ8dcY6d",
    "status": "confirmed",
    "tx_signature": "5xQ...",
    "payer_wallet": "7Np4...",
    "reference": "H8Do...",
    "description": null,
    "fiat_amount": null,
    "fiat_currency": null,
    "customer_note": null,
    "link_id": null,
    "test_mode": false
  }
}
import crypto from "node:crypto";
import express from "express";

const app = express();

// keep the raw body: the signature covers those exact bytes
app.post("/webhooks/abc", express.raw({ type: "application/json" }), (req, res) => {
  const expected = "sha256=" + crypto
    .createHmac("sha256", process.env.ABC_WEBHOOK_SECRET)
    .update(req.body)
    .digest("hex");
  const got = String(req.get("X-ABC-Signature") || "");
  const valid = got.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
  if (!valid) return res.sendStatus(401);

  const { event, invoice } = JSON.parse(req.body);
  // a test payment is play money: never ship an order for it
  if (event === "invoice.confirmed" && !invoice.test_mode) {
    // mark invoice.order_id as paid (safe to run twice: retries can repeat)
  }
  res.sendStatus(200);
});

Agent payments (x402)

Charge per API call. AI agents and apps pay with the open x402 standard: your API answers 402 Payment Required with a price, the agent signs a USDC transfer to your store wallet, and the gateway, as the x402 facilitator, checks it, pays the network fee and confirms it on Solana. Point any x402 library at https://gateway.advancebitcoin.org/api/x402 and send your API key on verify and settle.

FieldTypeWhat it does
NetworksCAIP-2solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (live stores), solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 (test stores)
TokensUSDC, USDT or $ABC on mainnet; test USDC on devnet. Smallest price $0.001 (1 $ABC).
Pay toMust be your store's wallet, which must already hold a USDC account.
FeesThe gateway pays the network fee. Payments asking for an unusually high fee are refused.
import { paymentMiddleware, x402ResourceServer } from "@x402/express";
import { ExactSvmScheme } from "@x402/svm/exact/server";
import { HTTPFacilitatorClient } from "@x402/core/server";

const facilitator = new HTTPFacilitatorClient({
  url: "https://gateway.advancebitcoin.org/api/x402",
  createAuthHeaders: async () => {
    const auth = { Authorization: `Bearer ${process.env.ABC_API_KEY}` };
    return { verify: auth, settle: auth, supported: {} };
  },
});
const server = new x402ResourceServer(facilitator)
  .register("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", new ExactSvmScheme());

app.use(paymentMiddleware({
  "GET /weather": {
    accepts: [{ scheme: "exact", price: "$0.01", network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", payTo: "<your store wallet>" }],
    description: "Weather for one city",
  },
}, server));

The full setup, an agent-side example and your paid calls are on Dashboard → Agent payments. To see one happen, the gateway runs its own paid API (a token safety check): be the agent and pay for one call, or point any x402 client at https://gateway.advancebitcoin.org/api/agent/token-check?mint=<mint>.

Checkout and wallets

/pay/:id is the hosted pay page; /l/:slug is a payment link. Both QR codes are Solana Pay transaction requests (/api/pay/:id/tx, /api/link/:slug/tx): the wallet asks the gateway for the exact payment, and a wallet that can't pay (not enough of the token, or of SOL for the fee) is told why before anything is signed. A basic transfer QR is offered for older wallets.

Errors and limits

FieldTypeWhat it does
400Something in the request is wrong; error says what.
401Missing, wrong or revoked API key.
404Not found, or it belongs to another store.
429Too many requests (30 a minute per key for creating invoices or links). Retry-After says when.
503Temporarily unavailable. Safe to retry; nothing was created.

Live state of every part of the gateway: /status. Questions: abc@advancebitcoin.org.