Solana Payment Gateway API: A Developer Walkthrough

Published Sep 2, 2026 · 8 min read

This is the end-to-end walkthrough of integrating Solpaygate from the developer's chair. Read it top to bottom and you should have a mental model of the full flow: how a session is created, what the hosted payment page does, and how the webhook lands in your backend.

The three moving parts

Every integration has the same shape:

  1. Your backend creates a payment session on Solpaygate.
  2. The customer's browser opens the hosted /pay page and completes payment.
  3. Solpaygate posts a webhook to your backend when the payment confirms.

That's it. No smart contracts. No custody code. You're wiring three endpoints — one outbound to us, one served to the customer, one inbound from us.

Creating a session

When a customer clicks Checkout on your site, your backend calls:

POST https://api.solpaygate.com/api/company/{companyId}/payment-session
Content-Type: application/json
X-Api-Key: sk_live_...

{
  "userId": "user_42",
  "orderId": "order_7c9f",
  "description": "Pro plan — monthly",
  "returnUrl": "https://example.com/thanks?order=order_7c9f"
}

The response:

{
  "token": "sess_a1b2c3d4...",
  "url": "https://app.solpaygate.com/pay?token=sess_a1b2c3d4...",
  "expiresAt": "2026-09-02T15:00:00Z"
}

The session's TTL is 30 minutes. Store the token against your order — you'll match webhooks by orderId anyway, but keeping the token makes debugging a specific customer's flow trivial.

Opening the pay URL

Redirect the customer's browser to url, or open it in a new tab. The hosted page lets them pick SOL, USDC, or USDT, shows a QR code and copy-paste address, and displays the confirmation state in real time.

Under the hood, when the customer picks a currency we generate a fresh deposit address (never reused). The customer sends the amount from any wallet; when the transfer confirms, we auto-sweep it to your master wallet within seconds. The customer never touches your master address, and you never hold custody of an intermediate wallet.

If your flow calls for a specific amount up front — a fixed-price order — you can skip the hosted page and use the direct endpoint instead:

POST /api/company/{companyId}/payment-direct
X-Api-Key: sk_live_...

{
  "userId": "user_42",
  "orderId": "order_7c9f",
  "currency": "USDC",
  "expectedAmount": 29.00,
  "description": "Pro plan — monthly"
}

The response returns the deposit address and expected amount without hosting anything for you:

{
  "paymentId": "pay_9x8y7z",
  "address": "9nB2...W1kV",
  "currency": "USDC",
  "network": "solana",
  "expectedAmount": 29.00,
  "expiresAt": "2026-09-02T14:15:00Z",
  "description": "Pro plan — monthly"
}

Use it when you want to render the QR yourself, embed the address inside a native app, or drive an in-person POS terminal.

Handling the webhook

When the payment reaches the confirmed commitment, Solpaygate POSTs to your configured webhookUrl:

{
  "paymentId": "pay_9x8y7z",
  "orderId": "order_7c9f",
  "status": "confirmed",
  "amount": "29.00",
  "currency": "USDC"
}

Your handler should verify the HMAC signature, look up the order, mark it paid, and return 200. Return anything else and we retry with exponential backoff for 24 hours. Design the handler to be idempotent — the same paymentId can arrive twice under network flakiness. The full detail for signature verification and retry design lives in our webhooks guide.

A minimal Node handler:

app.post('/webhooks/solpaygate', express.raw({type:'application/json'}), (req, res) => {
  if (!verifySig(req.body, req.header('X-Solpaygate-Signature'))) {
    return res.sendStatus(401);
  }
  const evt = JSON.parse(req.body);
  if (evt.status === 'confirmed') {
    markOrderPaid(evt.orderId, evt.paymentId, evt.amount, evt.currency);
  }
  res.sendStatus(200);
});

Testing on devnet

Point your test integration at devnet by flipping the network toggle on your company in the dashboard. Use a Solana wallet loaded with devnet SOL and devnet USDC (the SPL faucet gives you both). Then run a full round-trip:

Only flip to mainnet after your reconciliation script has run against a few devnet payments end-to-end. Most integrations settle on either sessions or direct payments as their default; our sessions vs links write-up is the shortcut to picking the right one for your flow.

Ready to accept crypto payments?

Solpaygate lets your business accept SOL, USDT, and USDC on Solana with a single API call. Non-custodial, no smart contract to deploy.

Start for free