Learn · NEAR trading
Accept crypto payments with one script tag
Add one script tag to your page. It draws a Pay button; the buyer pays with the coin they already hold, on any chain, and NEAR Intents delivers exactly your invoiced amount in the asset you chose. Before you ship anything, check the payment with the public status call. The 0.5% nearswaps fee is included in the quote.
Last checked
The one tag
Put this where the button should appear. It is the whole integration on the page:
<script src="https://nearswaps.com/checkout.js"
data-to="shop.near" data-amount="25" data-asset="usdc"
data-label="Order 1042"></script>
| Option | Meaning | Example |
|---|---|---|
data-to | Who is paid: a NEAR account, or an address on the chain of data-asset. Required. | shop.near |
data-amount | The invoiced amount in that asset. This is what you receive, exactly. Required. | 25, 12.50 |
data-asset | What you receive, from the table below. Default usdc. | usdc-base |
data-label | Shown on the invoice and stored with the payment, at most 80 characters. Put your order number here. | Order 1042 |
data-theme | light for light pages (a deeper mint with white text). Dark by default. | light |
data-onpaid | The name of a function on window to call when the pay page reports the payment. | onPaid |
What you can receive, and the address data-to must be:
data-asset | You receive | data-to must be |
|---|---|---|
usdc | USDC on NEAR | a NEAR account or a 64-hex implicit account |
usdt | USDT on NEAR | a NEAR account or a 64-hex implicit account |
near | NEAR | a NEAR account or a 64-hex implicit account |
usdc-base | USDC on Base | 0x and 40 hex characters |
usdc-sol | USDC on Solana | a Solana address (base58, 32 to 44 characters) |
usdc-arb | USDC on Arbitrum | 0x and 40 hex characters |
usdc-eth | USDC on Ethereum | 0x and 40 hex characters |
Several tags on one page are fine; each draws its own button. From your own code, without a tag on the page, load checkout.js once and call:
NearswapsCheckout.open({ to: "shop.near", amount: "25", asset: "usdc", label: "Order 1042" });
The button and the pay page
The tag draws a mint "Pay 25 USDC" pill with the nearswaps mark, right after the tag. It carries its own inline styles: no iframe and no stylesheet are added to your page.
A click opens https://nearswaps.com/pay in a popup window (a new tab on phones) with the invoice in the address and your page's origin. The pay page is never framed by another site. It shows:
- The invoice. Who is paid, in full, the amount, your label, and your page's origin once the browser confirms it.
- Pay with. BTC, ETH, SOL, ZEC, USDC and USDT on their own chains, plus NEAR, USDC and USDT on NEAR, each with a quote of what the buyer sends.
- The deposit address. The buyer gives a refund address on the chain they pay from (or connects a NEAR wallet to pay from NEAR) and gets a one-time deposit address from 1Click with the exact amount, a QR code, an "Open in wallet" link where the chain has one, and a 30-minute deadline. With Phantom, Solflare, MetaMask, Rabby or another browser wallet the pay page fills the refund address and sends the exact amount with one confirmation; otherwise the buyer sends by hand to the address shown.
- The status. The page follows the deposit every 5 seconds: waiting, seen, processing, delivered, or refunded. It picks up again after a reload for 24 hours.
- The receipt. Delivered: the payout transaction, and a message to your page.
When the payment is delivered
The pay page posts a message to your page's origin only, and checkout.js turns it into a nearswaps:paid event on the button. It bubbles to document. If you named data-onpaid, that function is called with the same details.
<script src="https://nearswaps.com/checkout.js"
data-to="shop.near" data-amount="25" data-asset="usdc"
data-label="Order 1042" data-onpaid="onPaid"></script>
Then, in your own script:
document.addEventListener("nearswaps:paid", (e) => {
const { depositAddress, amount, asset, label, to, statusUrl } = e.detail;
// Show "thanks", then ask your server to check the payment:
fetch("/orders/1042/paid", { method: "POST", body: depositAddress });
});
window.onPaid = (detail) => console.log("paid", detail.depositAddress);
amount is the invoiced amount as text ("25"), asset the data-asset code, statusUrl the status call below for this payment. Your page needs an http or https origin for the message to arrive: a file opened from disk has none.
Verify before you ship
The event is a convenience. The status call is the proof. Before you ship anything, ask it from your server.
GET https://nearswaps.com/api/intents?status=<depositAddress>
It is public and read-only. Check every one of these against your order:
| Field | Must be |
|---|---|
status | SUCCESS (delivered). Anything else is not paid yet, or not at all. |
recipient | your data-to |
destinationAsset | the asset id of your data-asset, for usdc nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1 |
swapDetails.amountOut | the amount delivered, in base units, at or above your invoice (25 USDC is 25000000, 6 decimals) |
amount | your invoice in base units |
kind, swapType | checkout and EXACT_OUTPUT |
label | your data-label, if you set one |
The other statuses: PENDING_DEPOSIT (waiting), KNOWN_DEPOSIT_TX (deposit seen), PROCESSING, INCOMPLETE_DEPOSIT (less than asked was sent), REFUNDED and FAILED. Accept each deposit address for one order only, and keep it with the order.
In Node 18 or later:
const USDC_ON_NEAR = "nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1";
const r = await fetch("https://nearswaps.com/api/intents?status=" + encodeURIComponent(depositAddress));
const s = await r.json();
const paid = r.ok
&& s.status === "SUCCESS" && s.kind === "checkout" && s.swapType === "EXACT_OUTPUT"
&& s.recipient === "shop.near"
&& s.destinationAsset === USDC_ON_NEAR
&& s.amount === "25000000"
&& BigInt(s.swapDetails?.amountOut ?? 0) >= 25000000n;
Or the one-liner from the nearswaps-checkout repository, Node only, no packages. It prints one fact per line and exits 0 when paid, 1 otherwise:
node verify-payment.mjs <depositAddress> --to shop.near --amount 25 --asset usdc
Add --label "Order 1042" to check the label too.
Fees
nearswaps' fee is 0.5%, included in the quote: the buyer's amount carries it, and you receive the full invoiced amount. The quote is exact-output, so your amount is fixed and the buyer's amount moves with the price.
- The buyer also pays their own chain's network fee for the deposit, in their wallet.
- The amount to send is about 1% above the least that fills the payment, to cover price moves while the deposit confirms. 1Click sends what is not used back to the buyer's refund address.
- Paid out as USDC on Ethereum, the buyer pays about 0.32 USDC more for Ethereum's withdrawal.
Every fee on nearswaps is in nearswaps fees and referral links.
Refunds
Refunds are 1Click's, to the buyer's refund address on the chain they paid from. A deposit that arrives after the 30-minute deadline, is below the amount asked, or cannot be filled at the quoted price is sent back there. The status call then answers REFUNDED and you are not paid.
A delivered payment is in your account. To refund a buyer after that, send it back yourself.
Limits and minimums
- Invoices from 1 USDC. When the buyer pays with Bitcoin, from about 7 USDC.
- At most 5,000 USD per payment, at 1Click's price.
- 30 minutes from the deposit address to the deposit. Bitcoin takes about 13 minutes after it confirms, so a slow Bitcoin confirmation can be refunded.
- Labels: at most 80 characters.
- Each refund address can get at most 20 deposit addresses a day (UTC, shared with nearswaps' swap and bridge), and the site gives out at most 120 an hour in all.
The smallest payments 1Click accepted in quotes on 9 Nov 2026 (they move with fees and prices; the pay page shows the current one):
| Buyer pays with | You receive | Smallest accepted |
|---|---|---|
| USDC on Base | USDC on NEAR | 0.149983 USDC |
| USDC on Base | USDT on NEAR | 0.150114 USDT |
| USDC on Base | NEAR | 0.0414 NEAR |
| USDC on Base | USDC on Solana | 0.139988 USDC |
| USDC on Base | USDC on Arbitrum | 0.149983 USDC |
| ETH, SOL or NEAR on NEAR | USDC on NEAR or Base | 0.1 USDC |
| BTC | USDC on NEAR | 6.206565 USDC |
What v1 does not do
- No partial payments: one deposit pays one invoice in full.
- No fiat: buyers pay in crypto, you receive crypto.
- No webhook: the status call is the webhook. Ask it from your server.
- No merchant accounts: any address can be paid, with no sign-up.
- No refunds beyond 1Click's own, above.
For buyers
Check the address matches the shop. Anyone can make a pay link to any address. Before you send, the invoice at the top of the pay page shows who is paid, in full, and the page that asked: make sure both are the shop you mean to pay. Send only the amount shown, only to the deposit address shown, before the deadline.
Questions people ask
Do I need an account to accept payments?
Which coins can my buyers pay with?
How do I know a payment arrived?
GET https://nearswaps.com/api/intents?status=<depositAddress> from your server and check status SUCCESS, your recipient, your asset and an amount delivered at or above the invoice. The browser event alone is not proof.What does it cost?
What if the buyer sends too little or too late?
REFUNDED and you are not paid.