Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.proof.community/llms.txt

Use this file to discover all available pages before exploring further.

Prerequisites

  • You have completed onboarding and received a client_token and widget_id.
  • You have a backend server whose IP is registered with Proof.
  • You have a partner_user_id (your internal, stable user identifier) and the user’s email.
  • You know which network and currency the user wants to transact in (e.g. TRC20 + USDT).

Step 1 — Request a session from your backend

Your frontend calls your own backend. Your backend calls POST /widget/session with the client_token (kept server-side) and the user’s real IP in client_ip.
# Your backend → Proof API
curl -X POST https://DOMAIN/widget/session \
  -H "Authorization: Bearer <client_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "partner_user_id": "user-123",
    "user_email": "user@example.com",
    "network": "TRC20",
    "currency": "USDT",
    "amount": "100",
    "type": "buy",
    "client_ip": "203.0.113.42"
  }'
Response:
{
  "merchant_transaction_id": "550e8400-e29b-41d4-a716-446655440000",
  "widget_id": "fb359d09-fff6-4b1f-906c-b9062b135065",
  "address": "TRx1a2b3c4d5e6f...",
  "signature": "v2:a1b2c3d4e5f6...",
  "init_token": "eyJhbGciOi...",
  "init_token_type": "sdk_partner_authorization",
  "currency": "USDT",
  "network": "TRC20",
  "amount": "100",
  "fix_currency": true,
  "fix_network": ["TRC20"],
  "fix_amount": true,
  "fiat_currency": "EUR",
  "type": "buy"
}
Save merchant_transaction_id — you use it everywhere downstream (polling, WebSocket, webhook).
Your backend returns the session parameters to the frontend (minus the client_token, which never leaves your server). For the full request and response field reference, see POST /widget/session.

Step 2 — Embed the widget

Your frontend receives the session parameters from your backend and passes them directly to proofWidget.run(). No client_token is needed on the frontend.
<div id="proof-widget"></div>

<script src="https://widget.proof.community/widget.2.0.js"></script>
<script>
  // `session` comes from your own backend endpoint, not from Proof directly
  proofWidget.run({
    widgetId:              session.widget_id,
    host:                  document.getElementById("proof-widget"),
    address:               session.address,
    signature:             session.signature,
    initToken:             session.init_token,
    initTokenType:         session.init_token_type,
    merchantTransactionId: session.merchant_transaction_id,
    currency:              session.currency,
    network:               session.network,
    amount:                session.amount,
    fixCurrency:           session.fix_currency,
    fixNetwork:            session.fix_network,
    fixAmount:             session.fix_amount,
    fiatCurrency:          session.fiat_currency,
    type:                  session.type,
    onStatusChange: function(data) {
      console.log("Widget status:", data.status);
    }
  });
</script>
The widget renders inside #proof-widget. The user completes identity verification (first time) and payment inside the widget.

Step 3 — Track transaction status

All status calls use your client_token and must go through your backend. Pick one of three delivery channels:

Polling (from your backend)

# Your backend → Proof API
curl https://DOMAIN/widget/transactions/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer <client_token>"
Poll every 5–10 seconds while status is pending or processing. Stop on completed, failed, or cancelled. See GET /widget/transactions/{id}.

WebSocket (from your backend)

// Node.js — server-side subscription
const WebSocket = require("ws");
const ws = new WebSocket(
  "wss://DOMAIN/ws?tx_id=550e8400-e29b-41d4-a716-446655440000",
  { headers: { Authorization: "Bearer <client_token>" } }
);
ws.on("message", (data) => {
  const msg = JSON.parse(data);
  if (msg.event === "tx.update") console.log(msg.status);
});
One connection subscribes to one merchant_transaction_id. See WebSocket for details and reconnection patterns.

Outbound webhook

If you provided a webhook_url at onboarding, Proof POSTs the normalized transaction event to that URL on every status change. See Partner Webhook.

Full example

// POST /your-api/widget-session
// Called by your frontend; client_token never leaves this file
async function createWidgetSession(req, res) {
  const userIp =
    req.headers["x-forwarded-for"]?.split(",")[0].trim() ||
    req.socket.remoteAddress;

  const session = await fetch("https://DOMAIN/widget/session", {
    method: "POST",
    headers: {
      "Authorization": "Bearer <client_token>",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      partner_user_id: req.body.userId,
      user_email:      req.body.userEmail,
      network:         "TRC20",
      currency:        "USDT",
      amount:          "100",
      type:            "buy",
      client_ip:       userIp
    })
  }).then(r => r.json());

  // Return session params — client_token is not included
  res.json(session);
}

Next steps

Transaction Status

Polling, WebSocket, and webhook delivery in detail.

Off-Ramp (Sell)

Enable sell flow for your users.

Mobile

iOS and Android setup for camera and payments.

Error Handling

Real error codes and how to handle them.