Quickstart

Get your first payment working in five minutes. This guide walks through the complete flow using the test environment.

Prerequisites

Base URL: https://api.apisettle.com/v1 All amounts are in USDC micro-units (1 USDC = 1,000,000).

1.Create a service

A service represents your API or product. It holds your default pricing and generates the API key you'll use for all vendor-side calls.

create-service.js
// Create a service (vendor project) to get your service_id
const res = await fetch('https://api.apisettle.com/v1/services', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'My API',
    pricing_model: 'per_request',
    quote_amount: '2000000',  // $2.00 default price
  }),
})
const { id: serviceId } = await res.json()

2.Create a quote

When a buyer requests your service, create a quote specifying the price. The quote token is a signed, tamper-proof payment request with a built-in expiry.

create-quote.js
// Create a payment request (quote)
const res = await fetch('https://api.apisettle.com/v1/quote', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    service_id: serviceId,
    quote_amount: '500000',   // $0.50
  }),
})
const { quote_token, quote_id } = await res.json()

Quotes expire after 10 minutes by default. Pass expires_in_seconds to customize.

3.Settle the payment

The buyer submits the quote token to settle. APISettle executes the on-chain transfer and returns a settlement token as proof of payment.

settle.js
// Settle the payment (consumer-side)
const res = await fetch('https://api.apisettle.com/v1/settle', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${CONSUMER_JWT}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    quote_token,
    payment_attempt_id: 'attempt_abc123',
  }),
})
const { settlement_id, settlement_token, tx_hash } = await res.json()

The payment_attempt_id is your idempotency key. Same ID = same result, never double-charged.

4.Redeem the settlement

Before delivering your service, redeem the settlement. This is an atomic, one-time operation — it cannot be replayed or double-spent.

redeem.js
// Redeem the settlement (vendor-side)
const res = await fetch(
  `https://api.apisettle.com/v1/settlements/${settlement_id}/redeem`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ settlement_token }),
  },
)
const { status, redeemed_at } = await res.json()
// status === "redeemed" → deliver the service

Full integration example

Here's how these steps fit together in a typical vendor endpoint. The pattern is simple: if the caller hasn't paid, return 402 with a quote. If they have, redeem and deliver.

handler.js
export default async function handlePaidRequest(req, res) {
  const settlementToken = req.headers['x-settlement-token']

  // No token yet — create a quote and ask for payment
  if (!settlementToken) {
    const quote = await createQuote({
      service_id: SERVICE_ID,
      quote_amount: '500000',
    })
    return res.status(402).json({
      quote_token: quote.quote_token,
      quote_id: quote.quote_id,
      amount: quote.quote_amount,
    })
  }

  // Token present — redeem it
  const settlementId = req.headers['x-settlement-id']
  const result = await redeemSettlement(settlementId, settlementToken)

  if (result.status !== 'redeemed') {
    return res.status(402).json({ error: 'payment_required' })
  }

  // Payment confirmed — deliver the service
  return res.status(200).json({ data: 'your response here' })
}

Next steps