Support/API Reference

API Reference

Authentication

All requests require a Bearer token in the Authorization header. Generate API keys in the Command Center.

Header
Authorization: Bearer rsend_live_sk_abc123...

Your merchant_idis derived from your API key — you don't need to pass it separately.

Create Payment Intent

POST /api/v1/merchant/payment-intent

Request

POST /api/v1/merchant/payment-intent
{
  "amount": "250.00",
  "currency": "USDC",
  "recipient": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
  "expires_in": 1800,
  "metadata": {
    "order_id": "ord_9f3k2",
    "customer_email": "buyer@example.com"
  }
}

Response 201 Created

201 Created
{
  "intent_id": "pi_7xk29m",
  "status": "pending",
  "amount": "250.00",
  "currency": "USDC",
  "recipient": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
  "expires_at": "2025-04-15T12:30:00Z",
  "created_at": "2025-04-15T12:00:00Z"
}

Errors

  • 400 — Invalid amount, unsupported currency, or missing fields.
  • 401 — Invalid or missing API key.
  • 429 — Rate limit exceeded (100 requests/min).

Get Intent Status

GET /api/v1/merchant/payment-intent/{id}

Response 200 OK

200 OK
{
  "intent_id": "pi_7xk29m",
  "status": "completed",
  "amount": "250.00",
  "currency": "USDC",
  "tx_hash": "0x1a2b3c4d5e6f...",
  "completed_at": "2025-04-15T12:05:32Z",
  "metadata": {
    "order_id": "ord_9f3k2",
    "customer_email": "buyer@example.com"
  }
}

Errors

  • 404 — Intent not found.

Register Webhook

POST /api/v1/merchant/webhook/register

Request

POST /api/v1/merchant/webhook/register
{
  "url": "https://yourapp.com/webhooks/rsend",
  "events": ["payment.completed", "payment.expired", "payment.cancelled"],
  "secret": "whsec_your_secret_here"
}

Response 201 Created

201 Created
{
  "webhook_id": "wh_m3x92p",
  "url": "https://yourapp.com/webhooks/rsend",
  "events": ["payment.completed", "payment.expired", "payment.cancelled"],
  "status": "active"
}

Errors

  • 400 — Invalid URL or unsupported event type.
  • 409 — Webhook URL already registered.

Test Webhook Delivery

POST /api/v1/merchant/webhook/test

Sends a test payment.completed event to your registered webhook URL. Use this to verify your endpoint works before going live.

Request

POST /api/v1/merchant/webhook/test
{
  "webhook_id": "wh_m3x92p"
}

Response 200 OK

200 OK
{
  "delivered": true,
  "status_code": 200,
  "response_time_ms": 142
}

Errors

  • 404 — Webhook ID not found.
  • 502 — Your endpoint returned an error or timed out.

List Transactions

GET /api/v1/merchant/transactions

Returns a paginated list of transactions. Supports filters via query params.

Query Parameters

  • page — Page number (default: 1).
  • limit — Items per page (default: 20, max: 100).
  • status — Filter by status: completed, pending, expired, cancelled.
  • from / to — Date range (ISO 8601).

Response 200 OK

200 OK
{
  "data": [
    {
      "tx_id": "tx_a1b2c3",
      "intent_id": "pi_7xk29m",
      "amount": "250.00",
      "currency": "USDC",
      "status": "completed",
      "tx_hash": "0x1a2b3c4d5e6f...",
      "created_at": "2025-04-15T12:00:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "has_more": false
  }
}

Webhook Events

RSends emits three webhook events:

  • payment.completed — Payment confirmed and forwarded.
  • payment.expired — Intent expired without payment.
  • payment.cancelled — Intent cancelled by merchant.

Payload Format

Webhook Payload
{
  "event": "payment.completed",
  "intent_id": "pi_7xk29m",
  "amount": "250.00",
  "currency": "USDC",
  "tx_hash": "0x1a2b3c4d5e6f...",
  "timestamp": "2025-04-15T12:05:32Z",
  "metadata": {
    "order_id": "ord_9f3k2"
  }
}

The X-RSends-Signature header contains the HMAC-SHA256 signature of the raw request body, signed with your webhook secret.

HMAC Verification

Always verify the X-RSends-Signatureheader before processing a webhook event. Here's how:

Node.js

verify-webhook.js
const crypto = require("crypto");

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body, "utf8")
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Usage in Express
app.post("/webhooks/rsend", (req, res) => {
  const signature = req.headers["x-rsend-signature"];
  const isValid = verifyWebhook(req.rawBody, signature, WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  const event = JSON.parse(req.rawBody);
  // Process event...
  res.status(200).json({ received: true });
});

Python

verify_webhook.py
import hmac
import hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        body,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

# Usage in Flask
@app.route("/webhooks/rsend", methods=["POST"])
def handle_webhook():
    signature = request.headers.get("X-RSends-Signature", "")
    is_valid = verify_webhook(request.data, signature, WEBHOOK_SECRET)

    if not is_valid:
        return {"error": "Invalid signature"}, 401

    event = request.get_json()
    # Process event...
    return {"received": True}, 200

Always Verify

Never process webhook events without verifying the HMAC signature. An attacker could send fake events to your endpoint to trigger false payment confirmations.