backendUrl. There is deliberately no default: a Rhinestone-operated fallback would mean your users’ deposits ride our key.
Two ways to get one:
- Write your own. A route table and a header — see minimal proxy.
- Deploy Rhinestone’s. We’re open-sourcing the proxy we run for clients, so you can deploy it as-is. Coming soon.
Before v0.9.0
backendUrl was optional and defaulted to a Rhinestone-internal
service. If you never set it, you were using ours — set it now. See
migration.Minimal proxy
A proxy is an explicit route table plus a header. The allowlist is the security boundary — see the warning below.Refunds are not a route-table entry
POST /deposits/refund cannot be forwarded like the routes above. Every route in
that loop passes the browser’s body straight through with your API key attached —
which for a refund means anyone could return any of your recoverable deposits to an
address they chose.
It needs a handler that authorizes the specific refund, and derives the upstream
call from that authorization rather than from the request body:
- your own route — use
createRefundHandler, which checks the deposit belongs to the caller before spending the key - a proxy — verify a per-refund
x-user-tokenand take every upstream field from the token, ignoring the body
Required routes
Missing a route doesn’t degrade the flow — the request 404s and that part of the modal stops working.CORS and the version header
All three modals sendx-deposit-modal-version on every request. Browsers reject a request carrying a header the server didn’t allow on the preflight, so an explicit allow-list must include it:
cors() in Hono is fine — with no allowHeaders it reflects whatever the preflight asks for.
The header tells us which versions are live, so we can warn you about one with a known bug and reproduce issues against the build you’re running. Forwarding it upstream is optional. To read the value in your own app, for a bug report:
Webhooks
The widget’s lifecycle callbacks fire only while the modal is open, so a user who closes it mid-bridge leaves your app unaware the deposit completed. Anything that must happen regardless — crediting a balance, sending a receipt — belongs on a webhook handler. Configure it once withPOST /setup.