Accept crypto payments with Node.js

Create USDT, USDC or ETH deposit addresses and verify TrezorPay callbacks in a Node.js (Express) app.

This guide uses Node.js 18+ (built-in fetch) and Express. No SDK and no API key are needed.

Create a payment address

create-address.js
const API = 'https://api.trezorpay.com'

export async function createAddress({ ticker, orderId, wallet }) {
  const callback = `https://shop.example/paid?order=${orderId}`
  const url = new URL(`${API}/${ticker}/create/`)
  url.searchParams.set('callback', callback)
  url.searchParams.set('address', wallet)
  url.searchParams.set('pending', '1')

  const body = await fetch(url).then((r) => r.json())
  if (body.status !== 'success') throw new Error(body.error)
  return body // { address_in, minimum_transaction_coin, ... }
}

// const { address_in } = await createAddress({ ticker: 'trc20/usdt', orderId: 42, wallet: 'T…' })

Receive and verify the callback

server.js
import { createVerify } from 'node:crypto'
import express from 'express'

const { pubkey } = await fetch('https://api.trezorpay.com/pubkey/').then((r) => r.json())
const seen = new Set() // use your database in production

const app = express()

app.get('/paid', (req, res) => {
  const signed = `https://${req.headers.host}${req.originalUrl}`
  const signature = req.headers['x-ca-signature']
  const valid = createVerify('sha256').update(signed).verify(pubkey, signature, 'base64')
  if (!valid) return res.status(401).end()

  const { uuid, pending, order, value_forwarded_coin, coin } = req.query
  if (pending === '0' && !seen.has(uuid)) {
    seen.add(uuid)
    console.log(`order ${order} paid: ${value_forwarded_coin} ${coin} sent to your wallet`)
  }
  res.send('*ok*')
})

app.listen(3000)

Behind a proxy, rebuild the URL exactly as we called it (scheme, host and query string), or the signature will not match. For post=1 or json=1 callbacks, verify the raw request body instead of the URL.

Next: callback fields and the API reference.

On this page