Crypto donation alerts in OBS: step-by-step setup
This guide takes you from nothing to a working on-stream alert: a donation link your viewers can pay in crypto, its alert widget in OBS Studio or Streamlabs, a test without real money, and, if you want, a thank-you message posted by your own bot. It takes about ten minutes. For what donation links are and what they cost, see crypto donations.
1. Create the donation link
In the dashboard, open Payment links, create a link and choose the type Donation. Give it a name your supporters will see, such as "Support my stream". A donation has no fixed price: set the minimum and maximum a supporter may give (by default 1 to 100,000 USD). Supporters pick one of the presets of 5, 10, 25, 50 or 100 USD that fall inside your limits, or type their own amount.
Put the link where your viewers look: the stream description, a chat command, a panel under the video. Supporters do not need an account; they type an optional name (up to 40 characters) and message (up to 200), then pay on the hosted checkout with the coin and network they choose.
2. Add the alert widget to OBS
Under the link in Payment links you find Stream alert widget (OBS browser source) with a copy button. That URL is the widget. It contains a long random token and works like a password, so do not show it on stream.
| Software | Steps |
|---|---|
| OBS Studio | In Sources, press + → Browser, name it, paste the widget URL into URL and set the width and height of your canvas, for example 1920 × 1080. |
| Streamlabs Desktop | Add a source → Browser Source, paste the widget URL and set the same size as your canvas. |
The page has a transparent background and draws the alert centred at the top, up to 560 pixels wide, so a full-canvas source is the easiest. Move or crop the source to put the alert elsewhere. Keep the source in every scene where alerts should show.
Place it with a sample alert
Add ?test=1 to the end of the widget URL. The widget then shows a sample alert every few seconds and fetches nothing, so you can size and position the source. Remove ?test=1 when you are done, or the real alerts will not appear.
3. Test a real donation without real funds
Switch the dashboard to test mode and create a second donation link there. Test links have their own widget URL; put it in a spare OBS scene. Then:
| Step | What happens |
|---|---|
| Open the test link, enter an amount, a name and a message | You land on the checkout, like a supporter would. |
| Choose any coin and network on the checkout | The invoice gets an amount to pay. No blockchain is used in test mode. |
| In Payments, open that invoice and press Simulate payment | The invoice becomes paid, and within about five seconds the alert pops up with your name, amount and message. |
| Optional: type a smaller amount next to Simulate payment | The invoice becomes underpaid and nothing shows on stream. Press it again with the field empty and the alert appears. |
More about test mode in the sandbox guide. When it works, switch the source back to the live widget URL.
When an alert appears
The widget checks for new paid donations every five seconds and shows each one for about eight seconds, one after the other, so a burst of donations queues up instead of overlapping. A donation counts once it is fully paid, which means confirmed on its blockchain: seconds on TON, Solana or XRP, about a minute on TRON, and longer on Bitcoin. The pricing page lists the confirmations for every coin. If you want quick alerts, suggest a fast network such as USDT on TON or USDT on TRON in your stream description.
4. Optional: thank supporters from your own bot
Payment-link invoices send the same webhooks as API invoices, to your account-wide webhook endpoints. A donation's invoice.paid event carries the supporter's name and message in metadata.donor_name and metadata.donor_message, and the link's name in description. Check the signature first (the webhook signatures guide has handlers for Node.js, PHP and Python), then for example post to your chat:
// Runs after the signature check (see the webhook signatures guide).
async function handleEvent(event) {
if (event.type !== "invoice.paid") return;
if (await db.seenEvent(event.id)) return; // retries repeat the same event id
const inv = event.data.invoice;
const name = inv.metadata?.donor_name; // only present if the supporter typed one
const message = inv.metadata?.donor_message;
if (name !== undefined || message !== undefined || inv.description === "Support my stream") {
// inv.amount is in USD; inv.pay_asset / inv.pay_amount say what was actually sent.
await chat.post(`Thank you ${name ?? "anonymous"} for ${inv.amount} USD!` + (message ? ` "${message}"` : ""));
}
await db.rememberEvent(event.id);
}Both fields are optional, so a supporter who left them empty has no metadata at all; match on the link name to catch those too. Treat the name and message as untrusted text: escape them before you put them on a web page or into a chat that renders markup. Answer 2xx within 10 seconds; failed deliveries are retried.
Troubleshooting
| What you see | Why | Fix |
|---|---|---|
| "Widget URL not found — copy it again from your dashboard" | The URL is mistyped or was replaced with a new one. | Copy the URL again from Payment links and paste it into the source. |
| Nothing appears after a donation | The payment is still confirming, it arrived short, or ?test=1 is still in the URL. | Look at the invoice in Payments: an alert shows only once it is paid in full. |
| Nothing appears after a test donation | The source points at the live widget URL, or the other way round. | Test links and live links have different widget URLs. |
| A donation from earlier never popped up | The widget only alerts for donations paid while it is open. | See all donations under the link in Payment links. |
| The widget URL leaked on stream | Anyone with the URL can see your alerts. | Press New widget URL under the link. The old URL stops working at once; paste the new one into OBS. |
Where the money goes
Each donation is credited to your easyway balance in the coin the supporter sent, after the platform fee, and is not converted. easyway holds the balance until you withdraw it to a wallet address you have whitelisted. Fees and minimum withdrawals per coin are on the pricing page; withdrawing from code is covered in the payouts guide.