Skip to main content
Back to blog

QR Code Generation — SMS and WhatsApp Deep Links From One API Call

Devotel Orbit's QR code endpoints turn a phone number or URL into a scannable PNG in one authenticated GET request — rendered in-cluster, validated before encoding, with click-to-chat deep links for SMS and WhatsApp built in.

Orbit Editorial Team

A QR code still earns its keep when the point of contact is print: packaging inserts, event badges, counter cards, direct mail. Scan the code and the phone opens a pre-addressed SMS composer or a WhatsApp chat with a drafted message — the friction of typing an eleven-digit number disappears. Devotel Orbit ships three endpoints for exactly that job, plus a no-code console in the dashboard. This post covers what each endpoint encodes, what gets validated before an image comes back, and the patterns teams build on top of them.

Three endpoints, three payload shapes

All three live under /api/v1/qr and take an authenticated GET:

  • `GET /qr/sms` — encodes an sms:<phone>?body=<message> URI. Both iOS and Android hand it to the native SMS composer, pre-addressed to your number with the body already drafted.
  • `GET /qr/whatsapp` — encodes https://wa.me/<phone>?text=<message>, the standard WhatsApp click-to-chat deep link. Scanning opens the chat thread with your business number and the message ready to send.
  • `GET /qr/generate` — encodes any arbitrary payload: a URL, plain text, a mailto: address, a tel: link. This is the generic path for anything that isn't an SMS or WhatsApp entry point.

Each endpoint takes size (image edge in pixels, 50–1024, default 300) and format. The default format=png returns raw image/png bytes, which you can drop straight into an <img> tag or pipe into a print-production file. format=json returns the standard response envelope with qr_data_url as a base64 data URL — the shape the dashboard console uses for live previews.

Validated before it is ever encoded

The SMS and WhatsApp endpoints run the phone number through the same libphonenumber validation the rest of the platform uses. An undialable shape gets a 400 INVALID_PHONE; a valid one is normalised to E.164 before it goes anywhere near the image. The API rejects phone=+12 the same way the Dashboard's Developer → QR Code Tools page shows the validation message instead of a broken preview.

The generic /qr/generate path has its own guard: payloads that start with a script-execution scheme — javascript:, data:, vbscript:, file:, about:, blob: — are rejected with 400 rather than rendered. Some scanner apps preview encoded text as tappable, and a small number will execute a javascript: URI in a hosted webview, so that class of payload never becomes an image.

The one input that stays the caller's responsibility is message text within the 1024-character ceiling: a message longer than the ceiling returns a validation error, and genuinely long copy belongs behind a short URL, not inside a QR.

Rendered in-cluster, not proxied

QR image rendering runs on the platform itself — the payloads never leave the cluster, and there is no third-party image service in the path. That matters once you remember what these payloads carry: live phone numbers and drafted message text. Keeping rendering server-side also removes an upstream provider from the synchronous request, which is one less dependency between you and the response. Rendered PNGs are edge-cached on private cache headers for repeat scans within the TTL.

The no-code path

If you need one code rather than ten thousand, the Dashboard's Developer → QR Code Tools page wraps all three endpoints: pick SMS, WhatsApp, or a custom URL, type the destination, and the preview renders as you type (debounced, routed through the same hardened endpoints the public API exposes). Download the PNG, or copy the exact encoded deep link to inspect what a scanned device opens. Available to owner, admin, and developer roles.

Where teams put these to work

  • Support entry on physical goods. A QR on the packing slip opens a WhatsApp thread with "Order #…" prefilled; the reply lands in the same Orbit inbox every other channel uses.
  • Two-way SMS from print. A mailer QR opens the SMS composer addressed to your inbound number; the inbound message arrives through the standard inbound pipeline, webhooks and all.
  • Campaign measurement. Encode distinct pre-filled bodies per placement ("box-back", "receipt-footer") and report on which physical surface actually produced conversations.
  • Batch generation for print production. Loop the /qr/* endpoints in your CI or asset pipeline: one request per code, PNG bytes back, straight into the layout.

For more than a handful of codes, the API is the path — the dashboard console is deliberately one-code-at-a-time, while the endpoints take a URL parameter pair per request and hand PNG bytes straight back.

Frequently asked questions

What image format and sizes come back?

PNG always, square. Ask for any edge length from 50 to 1024 pixels with size; the default is 300. For print, request 1024 and let your layout tool scale down.

Can I get the data URL instead of raw bytes?

Yes — pass format=json and the response envelope returns qr_data_url as a base64 data URL, plus the normalised phone and encoded deep link on the SMS and WhatsApp paths.

What phone formats are accepted on /qr/sms and /qr/whatsapp?

Human-typed shapes are normalised through libphonenumber before encoding, so (415) 555-1234 and +1 415 555 1234 both work. Inputs that cannot dial a real destination return 400 INVALID_PHONE rather than a QR that scans to garbage.

Why does a javascript:-prefixed payload get rejected by /qr/generate?

Some scanner apps execute javascript: URIs in a preview webview. The endpoint refuses script-execution schemes outright; plain text, http(s), mailto:, tel:, sms:, and wa.me links all render normally.

Is there a rate limit?

The endpoints sit behind the standard authenticated read rate limit, which is sized for dashboard previews and batch generation alike. For sustained high-volume generation, your account's rate-limit configuration is the reference.

Resources

QR Code Generation — SMS and WhatsApp Deep Links From One API Call — Orbit by Devotel