Embed Docs

Accept Solana payments
on any website.

Drop one script tag and call Settlix.open(). No SDK, no wallet libraries, no framework required.

1Load checkout.js
2Buyer pays in the modal
3onSuccess fires

Quick Start

Two steps to a working checkout button.

1

Load the checkout script once — anywhere in your HTML

html
<script src="https://settlix.xyz/checkout.js"></script>
2

Trigger the checkout from any button

html
<button onclick="Settlix.open({ linkId: 'YOUR_LINK_ID' })">
  Pay with Settlix
</button>

Replace YOUR_LINK_ID with the ID from your Settlix dashboard.

Open live HTML demo

Live Demo

Enter your payment link ID and fire the checkout right here.

Sign in and create a payment link to get your Payment Link ID. Go to Dashboard

Event log
Events will appear here…

Full API Reference

All options accepted by Settlix.open().

javascript
Settlix.open({
  linkId: 'YOUR_LINK_ID',

  // Optional — pass any JSON you want echoed back
  metadata: {
    orderId: 'order_789',
    userId:  'user_456',
  },

  // Fires when payment is confirmed on-chain
  onSuccess: function(txSignature, metadata) {
    console.log('paid:', txSignature)
    console.log('order:', metadata.orderId)
  },

  // Fires on close, cancel, or failure
  onClose: function(metadata) {
    console.log('abandoned order:', metadata?.orderId)
  },
})

// Close programmatically (e.g. from your own UI)
Settlix.close()
OptionTypeDescription
linkIdstringRequired. Your payment link ID from the dashboard.
metadataobjectOptional. Any JSON — echoed back in onSuccess and onClose.
onSuccess(txSig, metadata) => voidCalled when payment is confirmed on-chain.
onClose(metadata) => voidCalled on close, cancel, or failure.

Order Tracking

How to map a payment back to a specific order and user.

Without metadata — you know a payment was made but not which order or which user triggered it. Two customers buying the same product produce identical webhook payloads except for txSignature and userWallet.
javascript
// Without metadata — you know SOMEONE paid, not WHO or WHAT ORDER
Settlix.open({ linkId: 'abc' })

// With metadata — you get back exactly what you put in
Settlix.open({
  linkId: 'abc',
  metadata: { orderId: 'order_789', userId: 'user_456', plan: 'pro' },
  onSuccess: function(txSignature, metadata) {
    // metadata.orderId → 'order_789'  ✓
    // metadata.userId  → 'user_456'   ✓
    fulfillOrder(metadata.orderId, txSignature)
  },
})

metadata is stored alongside the transaction in Settlix and included in every webhook delivery — so your backend can correlate without relying solely on the client-side callback.

Webhook Payload

Settlix sends a signed POST to your endpoint on every confirmed payment.

json
// Payment link payment
{
  "linkId":       "clxyz1234abcd",
  "txSignature":  "5Yf3...k9mZ",
  "userWallet":   "9xKp...wQ2r",
  "inputToken":   "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "inputAmount":  "25000000",
  "outputAmount": "25000000",
  "timestamp":    "2025-04-26T10:30:00.000Z",
  "metadata":     { "orderId": "order_789" }
}

// Invoice payment
{
  "invoiceId":    "clxyz5678efgh",
  "txSignature":  "5Yf3...k9mZ",
  "userWallet":   "9xKp...wQ2r",
  "inputToken":   "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "inputAmount":  "500000000",
  "outputAmount": "500000000",
  "timestamp":    "2025-04-26T10:30:00.000Z"
}

// Subscription payment (first payment or renewal)
{
  "subscriberId": "clxyz9012ijkl",
  "planId":       "clxyz3456mnop",
  "txSignature":  "5Yf3...k9mZ",
  "userWallet":   "9xKp...wQ2r",
  "inputToken":   "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "inputAmount":  "10000000",
  "outputAmount": "10000000",
  "timestamp":    "2025-04-26T10:30:00.000Z"
}

// All events include the signature header:
// X-Settlix-Signature: sha256=<hmac-hex>

Verifying the signature

Compute HMAC-SHA256(body, webhookSecret) and compare it to the hex value in X-Settlix-Signature. Reject the request if they don't match.

Content Security Policy

Add these directives if your site sets a CSP header.

http header
Content-Security-Policy:
  script-src  https://settlix.xyz;
  frame-src   https://settlix.xyz;
  connect-src https://settlix.xyz;

frame-src allows the checkout iframe. connect-src allows API calls made from inside the iframe.

TypeScript

Full type declaration — paste this into any global.d.ts if you skipped the Quick Start.

typescript
/// <reference types="https://settlix.xyz/checkout.d.ts" />
// or paste this into a global.d.ts file:

interface SettlixCheckout {
  open(opts: {
    linkId: string
    metadata?: Record<string, unknown>
    onSuccess?: (txSignature: string, metadata: Record<string, unknown> | null) => void
    onClose?:   (metadata: Record<string, unknown> | null) => void
  }): void
  close(): void
}

declare global {
  interface Window { Settlix: SettlixCheckout }
}

Async Script Loading

Queue calls made before the script finishes loading.

html
<!-- Optional: queue calls made before the script loads -->
<script>
  window.Settlix = { _q: [], open: function(o){ this._q.push(o) } }
</script>
<script src="https://settlix.xyz/checkout.js" async></script>

If you load the script with async, calls to Settlix.open() before the script executes will be queued and replayed automatically.

REST API

Settlix API
for your backend.

Create links, configure webhooks, and manage your account — all from your own server using a simple REST API and a Bearer token.

1Get an API key
2Authenticate with Bearer
3Call any endpoint

Authentication

All protected endpoints accept a Bearer token in the Authorization header.

http header
Authorization: Bearer sk_live_<your-key>

API keys are scoped to your merchant wallet — they can do everything your dashboard session can.

Keep keys secret. Treat them like passwords. If a key is compromised, revoke it immediately from your dashboard and create a new one.

Quick Start

Create a payment link and get a URL in one request.

bash
# Create a link from your server
curl -X POST https://settlix.xyz/api/links \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "amount": "25", "title": "Order #1234" }'

# Then open it client-side
Settlix.open({ linkId: "clxyz1234abcd", metadata: { orderId: "1234" } })

API Keys

Create and revoke API keys programmatically. Up to 10 keys per wallet.

GET/api/keys
bash
# List your API keys
curl https://settlix.xyz/api/keys \
  -H "Authorization: Bearer sk_live_..."
POST/api/keys
bash
# Create a new API key (name it for your app)
curl -X POST https://settlix.xyz/api/keys \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "My Shopify store" }'

# Response — save this key, it is shown ONCE
{
  "id": "clxyz...",
  "name": "My Shopify store",
  "key": "sk_live_a1b2c3...",
  "createdAt": "2025-04-26T10:00:00.000Z"
}

The raw key is returned once and never stored. Save it immediately.

DELETE/api/keys/:id
bash
# Revoke a key by ID — returns 204 No Content
curl -X DELETE https://settlix.xyz/api/keys/clxyz... \
  -H "Authorization: Bearer sk_live_..."

Invoices

Create and send invoices — clients pay via a dedicated invoice page.

bash
# List all invoices
curl https://settlix.xyz/api/invoices \
  -H "Authorization: Bearer sk_live_..."

# Create an invoice
curl -X POST https://settlix.xyz/api/invoices \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "clientName":  "Acme Corp",
    "clientEmail": "billing@acme.com",
    "token":       "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "dueDate":     "2025-06-01T00:00:00.000Z",
    "memo":        "Q2 retainer",
    "lineItems": [
      { "description": "Design work", "quantity": "1", "unitPrice": "500.00" },
      { "description": "Dev hours",   "quantity": "8", "unitPrice": "150.00" }
    ]
  }'

# Response — 201 Created
{
  "id":      "clxyz...",
  "linkId":  "clxyz...",
  "payPath": "/invoice/clxyz..."
}
FieldTypeDescription
clientNamestring?Optional. Shown in the invoice and email.
clientEmailstring?Optional. If set, invoice email is sent on creation and a receipt on payment.
tokenstringRequired. Settlement token mint address (USDC).
dueDateISO 8601?Optional. After this date the invoice is marked overdue.
memostring?Optional. Internal note shown on the invoice.
lineItemsarrayRequired. At least one item with description, quantity, and unitPrice.
GET/api/invoices/:id
bash
# Get a single invoice (public — no auth needed)
curl https://settlix.xyz/api/invoices/clxyz...

Public endpoint — no auth required. Used by the client to view and pay the invoice.

DELETE/api/invoices/:id
bash
# Archive an invoice — returns 204 No Content
curl -X DELETE https://settlix.xyz/api/invoices/clxyz... \
  -H "Authorization: Bearer sk_live_..."
POST/api/invoices/:id/send
bash
# Send (or resend) the invoice email to the client
# Returns 409 INVOICE_ALREADY_PAID if the invoice has been paid
curl -X POST https://settlix.xyz/api/invoices/clxyz.../send \
  -H "Authorization: Bearer sk_live_..."
Already paid? A receipt email is sent automatically when the client pays. Calling this endpoint on an already-paid invoice returns 409 INVOICE_ALREADY_PAID.

Subscriptions

Create recurring payment plans and manage subscribers.

Subscribers authorize an SPL token delegation from the /subscribe/:planId page. The relayer then charges them automatically at each renewal. Merchants get a webhook on every successful charge.

GET/api/subscription-plans
bash
# List your subscription plans
curl https://settlix.xyz/api/subscription-plans \
  -H "Authorization: Bearer sk_live_..."
POST/api/subscription-plans
bash
# Create a subscription plan
curl -X POST https://settlix.xyz/api/subscription-plans \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "token":       "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount":      "10.00",
    "interval":    "weekly",
    "title":       "Pro Plan",
    "description": "Weekly access to all features"
  }'

# Response — 201 Created
{ "id": "clxyz1234abcd" }

# Share this URL with subscribers:
# https://settlix.xyz/subscribe/clxyz1234abcd
FieldTypeDescription
tokenstringRequired. Settlement token mint address (USDC).
amountstringRequired. Amount charged per interval, e.g. "10.00".
interval"daily" | "weekly"Required. Billing frequency.
titlestring?Optional. Shown to subscribers at sign-up.
descriptionstring?Optional. Up to 300 characters.
PATCH/api/subscription-plans/:id
bash
# Pause a plan (stops new subscriptions, existing ones continue)
curl -X PATCH https://settlix.xyz/api/subscription-plans/clxyz1234abcd \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "active": false }'

# Reactivate
curl -X PATCH https://settlix.xyz/api/subscription-plans/clxyz1234abcd \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "active": true }'

Pausing a plan prevents new sign-ups but does not cancel existing subscribers.

DELETE/api/subscription-plans/:id
bash
# Archive a plan — returns 204 No Content
curl -X DELETE https://settlix.xyz/api/subscription-plans/clxyz1234abcd \
  -H "Authorization: Bearer sk_live_..."
GET/api/subscriptions
bash
# List all subscribers across your plans
curl https://settlix.xyz/api/subscriptions \
  -H "Authorization: Bearer sk_live_..."
POST/api/subscriptions/:id/cancel
bash
# Cancel a subscriber (merchant-initiated)
curl -X POST https://settlix.xyz/api/subscriptions/clxyz9012ijkl/cancel \
  -H "Authorization: Bearer sk_live_..."

Subscribers can also self-cancel from their /manage/:subscriberId page by connecting the wallet they subscribed with.

Renewal schedule

Renewals run at midnight UTC. The relayer attempts each charge up to 3 times (10 PM, 11 PM, 12 AM). If all attempts fail the subscriber is cancelled and notified by email.

Webhooks

Configure a webhook — Settlix POSTs to your URL on every confirmed payment.

PATCH/api/webhook
bash
# Configure your webhook endpoint
curl -X PATCH https://settlix.xyz/api/webhook \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "webhookUrl":    "https://yoursite.com/api/settlix-webhook",
    "webhookSecret": "your-32-char-secret"
  }'

Verifying the signature

javascript
// Node.js — verify incoming webhook
const crypto = require('crypto')

function verifySettlixWebhook(rawBody, signature, secret) {
  const expected = 'sha256=' +
    crypto.createHmac('sha256', secret).update(rawBody).digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  )
}

Always verify the signature

Compare the header value to sha256=HMAC(rawBody, webhookSecret) using a timing-safe comparison. Reject requests that don't match.

Errors

All errors follow a consistent JSON shape with a machine-readable code.

json
// Every error response follows this shape
{
  "error": "Human-readable message",
  "code":  "MACHINE_READABLE_CODE",
  "issues": [...]           // only on validation errors (400)
}

// HTTP status codes used by this API
// 201 — resource created (POST)
// 204 — deleted (DELETE)
// 400 — bad request / validation failed
// 401 — missing or invalid API key
// 403 — forbidden (you don't own this resource)
// 404 — resource not found
// 409 — conflict (e.g. invoice already paid)
// 410 — gone (link expired or sold out)
// 502 — upstream failure (e.g. email delivery)
// 500 — server error