nearswaps

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>
OptionMeaningExample
data-toWho is paid: a NEAR account, or an address on the chain of data-asset. Required.shop.near
data-amountThe invoiced amount in that asset. This is what you receive, exactly. Required.25, 12.50
data-assetWhat you receive, from the table below. Default usdc.usdc-base
data-labelShown on the invoice and stored with the payment, at most 80 characters. Put your order number here.Order 1042
data-themelight for light pages (a deeper mint with white text). Dark by default.light
data-onpaidThe 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-assetYou receivedata-to must be
usdcUSDC on NEARa NEAR account or a 64-hex implicit account
usdtUSDT on NEARa NEAR account or a 64-hex implicit account
nearNEARa NEAR account or a 64-hex implicit account
usdc-baseUSDC on Base0x and 40 hex characters
usdc-solUSDC on Solanaa Solana address (base58, 32 to 44 characters)
usdc-arbUSDC on Arbitrum0x and 40 hex characters
usdc-ethUSDC on Ethereum0x 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:

  1. The invoice. Who is paid, in full, the amount, your label, and your page's origin once the browser confirms it.
  2. 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.
  3. 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.
  4. 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.
  5. The receipt. Delivered: the payout transaction, and a message to your page.

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:

FieldMust be
statusSUCCESS (delivered). Anything else is not paid yet, or not at all.
recipientyour data-to
destinationAssetthe asset id of your data-asset, for usdc nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1
swapDetails.amountOutthe amount delivered, in base units, at or above your invoice (25 USDC is 25000000, 6 decimals)
amountyour invoice in base units
kind, swapTypecheckout and EXACT_OUTPUT
labelyour 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 withYou receiveSmallest accepted
USDC on BaseUSDC on NEAR0.149983 USDC
USDC on BaseUSDT on NEAR0.150114 USDT
USDC on BaseNEAR0.0414 NEAR
USDC on BaseUSDC on Solana0.139988 USDC
USDC on BaseUSDC on Arbitrum0.149983 USDC
ETH, SOL or NEAR on NEARUSDC on NEAR or Base0.1 USDC
BTCUSDC on NEAR6.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?

No. Any NEAR account, or an address on the chain of the asset you choose, can be paid. There is no sign-up in v1.

Which coins can my buyers pay with?

BTC, ETH on Ethereum, Base and Arbitrum, SOL, ZEC, USDC on Ethereum, Solana, Base and Arbitrum, USDT on Ethereum, Tron and Solana, and NEAR, USDC and USDT on NEAR.

How do I know a payment arrived?

Ask 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?

A 0.5% nearswaps fee, included in the quote the buyer pays. You receive the full invoiced amount. The buyer also pays their own chain's network fee for the deposit.

What if the buyer sends too little or too late?

1Click refunds the deposit to the refund address the buyer gave, on the chain they paid from. The status call then answers REFUNDED and you are not paid.