MarioSMS

Receive SMS Codes in Node.js: MarioSMS API Tutorial

Updated · MarioSMS team

Node 18+ ships fetch natively, so a MarioSMS integration needs zero dependencies: one call to rent a number, a polling loop to await the code, and an optional cancel. This works identically in TypeScript, plain Node scripts, and serverless functions.

You’ll need a MarioSMS account with balance and your API key from the app profile. Full endpoint reference: app.mariosms.com/api-docs. Authentication is a single X-API-Key header.

A minimal client

const BASE = 'https://app.mariosms.com/api/v1'
const KEY = process.env.MARIOSMS_API_KEY

async function api(path, { method = 'GET', body } = {}) {
  const res = await fetch(`${BASE}${path}`, {
    method,
    headers: {
      'X-API-Key': KEY,
      ...(body ? { 'Content-Type': 'application/json' } : {}),
    },
    body: body ? JSON.stringify(body) : undefined,
  })
  if (!res.ok) throw new Error(`MarioSMS API ${res.status}: ${await res.text()}`)
  return res.json()
}

Sanity-check the key:

console.log(await api('/balance')) // { balance: 100 }

Rent a number

An activation is one number for one verification. Pick a service and country (codes from GET /services and GET /countries, live prices from GET /prices):

const activation = await api('/activation', {
  method: 'POST',
  body: { country: 'us', service: 'tg' }, // Telegram, US number
})
console.log(activation.phone) // "12025551234"

Await the code

Enter the number wherever you’re verifying, then poll until the status is received:

const sleep = (ms) => new Promise((r) => setTimeout(r, ms))

async function waitForCode(id, timeoutMs = 5 * 60 * 1000) {
  const deadline = Date.now() + timeoutMs
  while (Date.now() < deadline) {
    const a = await api(`/activation/${id}`)
    if (a.status === 'received') return a.smsCode // full text in a.smsText
    await sleep(5000)
  }
  return null
}

const code = await waitForCode(activation.id)
console.log('OTP:', code)

Cancel and refund

Before an SMS arrives you can cancel for a full refund to your balance:

await api(`/activation/${activation.id}/cancel`, { method: 'POST' })
// { message: "activation cancelled", refund: 1.32 }

If your process dies mid-wait, nothing is lost: the platform auto-cancels and refunds any activation whose window expires without an SMS. You only ever pay for codes that actually arrive.

Tips

  • Keep the API key in an environment variable, never in the repo.
  • One activation = one code. Verifying two services means two activations.
  • For CI, wrap the whole flow with your test runner’s timeout rather than relying only on the polling deadline.
  • Automation is for activity you’re allowed to automate — QA, testing, legitimate account creation. See the acceptable use policy.