Swipelux

Fiat → Crypto

Convert USD to USDC via hosted checkout; verify via webhook then REST

Summary

Create a Customer, provision a wallet, create a USD→USDC transfer, redirect the user to the provided sourceInstructions.signedUrl to finish payment, then wait for a webhook and re-verify via REST before updating the UI. Fiat: USD only. Crypto: USDC only (today).

Problem → Solution mapping

Pain pointCapabilityMechanism
KYC + wallet provisioningCustomers + Wallet APIPOST /v1/customers then POST /v1/customers/{id}/wallets returns wallets[...]
Checkout without building UIHosted Payment LinkPOST /v1/transfers → sourceInstructions.signedUrl → redirect
Definitive payment stateWebhooks + REST re-verifySubscribe, validate HMAC, then GET /v1/transfers/{id} before updating UI

Architecture

Implementation steps

Create user

curl https://wallet.swipelux.com/v1/customers \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: YOUR_API_KEY' \
  --data '{
    "firstName":"John","lastName":"Doe","email":"john.doe@example.com","phone":"+1234567890",
    "birthDate":"1990-01-01",
    "residentialAddress":{"streetLine1":"123 Main St","city":"San Francisco","state":"CA","postalCode":"94101","country":"US"},
    "identifyingInformation":[{"type":"drivers_license","issuingCountry":"US",
      "frontSideImage":"data:image/png;base64,iVBORw0KGgoAAA...","backSideImage":"data:image/png;base64,iVBORw0KGgoBBB..."}]
  }'

Provision wallet

curl https://wallet.swipelux.com/v1/customers/cus_cK69MttD5nAUAbud1B/wallets \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: YOUR_API_KEY' \
  --data '{ "chains": ["base"] }'

Make a transfer (USD→USDC) and redirect

Choose from any of our supported fiat payment rails.

💡 Learn more: See our Rails guide to understand how different payment rails work and how routing is handled automatically.

curl https://wallet.swipelux.com/v1/transfers \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: YOUR_API_KEY' \
  --data '{
    "onBehalfOf":"cus_cK69MttD5nAUAbud1B",
    "amount":"50.0",
    "source":{"paymentRail":"apple_pay","currency":"USD"},
    "destination":{"currency":"USDC"}
  }'

Use the returned sourceInstructions.signedUrl to open hosted checkout where the user completes payment.

Wait & verify the webhook (then REST re-check)

Subscribe the webhook and store the secret:

curl https://wallet.swipelux.com/v1/webhooks \
  --request PATCH \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: YOUR_API_KEY' \
  --data '{ "url": "https://your-domain.com/webhook" }'

Verify signature and re-fetch transfer before updating UI:

const crypto = require('crypto');
const express = require('express');
const fetch = require('node-fetch');
const app = express();
 
app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
  const sig = req.header('X-Webhook-Signature') || '';
  const secretKey = process.env.WEBHOOK_SECRET_KEY; // from PATCH response
  const expected = crypto.createHmac('sha256', secretKey).update(req.body).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(sig, 'hex'), Buffer.from(expected, 'hex'))) {
    return res.status(401).end();
  }
  const evt = JSON.parse(req.body.toString('utf8'));
  if (evt.type === 'transfer.completed') {
    const trId = evt.data?.id;
    if (trId) {
      const r = await fetch(`https://wallet.swipelux.com/v1/transfers/${trId}`, {
        headers: {
          'X-API-Key': process.env.SWIPELUX_API_KEY,
          'Content-Type': 'application/json'
        }
      });
      const tr = await r.json();
      // Update order state only if tr.state === 'completed'
    }
  }
  res.sendStatus(200);
});

Limits & caveats

  • Fiat: USD only. Crypto: USDC only (today).
  • Always treat REST as source of truth; do not fulfill based on webhook alone.

On this page