Developer quickstart

Create exact-output payment intents, send payers to the hosted checkout, and receive signed webhooks and receipts. Test keys start with sk_test_ and never move real funds.

1. Create a payment intent

curl https://api.routed.wtf/v1/payment-intents \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: inv-1048-attempt-1" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": { "value": "1000.00", "currency": "USD" },
    "settlement": { "asset_id": "usdc-base", "address": "0xYourWallet" },
    "external_reference": "INV-1048",
    "expires_in_seconds": 86400
  }'

Redirect the payer to hosted_url. Every mutation requires an Idempotency-Key; retries with the same key return the original response with Idempotent-Replayed: true.

2. Handle webhooks

Events are signed with HMAC-SHA256. Verify the Route-Signature header (t=…,kid=…,v1=…) over `${t}.${rawBody}` and reject timestamps older than 5 minutes. Deliveries are at-least-once and ordered per endpoint; dedupe on the event id.

import { verifyWebhook } from '@routewtf/sdk';

const event = verifyWebhook(rawBody, req.headers['route-signature'], process.env.WEBHOOK_SECRET);
if (event.type === 'payment_intent.settled') markInvoicePaid(event.data.external_reference);

3. Verify receipts

Receipts are ES256 detached JWS over RFC 8785 canonical JSON. Fetch the key set from /.well-known/receipt-keys.json and verify offline, or call POST /v1/receipts/verify.

Reference

  • OpenAPI 3.1: https://api.routed.wtf/v1/openapi.json
  • SDKs: TypeScript (packages/sdk-js) and Python (packages/sdk-python) in the repository.
  • Sandbox: test-mode orders can be advanced from the status page or with POST /sandbox/orders/:id/simulate-deposit.

Questions? Read the help page or contact support.