QR Codes
Trackable QR codes for creator posts, with a permanent short link, scan stats and destination safety checks.
Amba QR gives every post its own QR code. A creator shows the code on screen ("screenshot this, tap it"), every scan is recorded, and the code points at a permanent short link on go.amba.host, so a printed or posted code keeps working when its destination changes.
QR codes belong to your Amba account. They need no project, no API key and no SDK: create them with the MCP tools or the API using your personal access token or a sign-in session. Codes are unlimited on every plan. The account needs a proven email address: an account an agent created stays unclaimed until its owner claims it (amba_developer_claim), and until then POST /v1/qr answers 403 QR_ACCOUNT_UNVERIFIED.
MCP tools
| Tool | Description |
|---|---|
amba_qr_create | Create a code; returns its short link and image links |
amba_qr_list | List your codes with scan and continue counts |
amba_qr_get | One code, with its final URL, safety verdict and destination history |
amba_qr_update | Change the destination, label, platform, sponsor, UTM mode, or turn it off |
amba_qr_delete | Delete a code (asks for confirmation first) |
amba_qr_stats | Daily scans, continues and unique visitors; country and device OS on Pro |
amba_qr_image | The framed SVG and a PNG link you can open without signing in for 7 days |
amba_qr_share | Share a read-only stats dashboard of some codes with a brand, by email |
amba_qr_shares_list | List your brand shares and when each was last viewed |
amba_qr_unshare | Turn a brand share link off (asks for confirmation first) |
amba_qr_profile_get | The display name scanners see, your QR plan and account kind |
amba_qr_profile_update | Set the display name scanners see |
amba_qr_billing_status | Your QR plan, subscription status and renewal date |
amba_qr_upgrade | A checkout link for QR Pro ($10/month) to give the account owner |
Example
What a scan does
The short link is https://go.amba.host/<slug>. A slug is 7 characters from 23456789abcdefghjkmnpqrstuvwxyz, which leaves out the characters that read alike on screens and in print (0, 1, i, l, o).
- Free plan: every scan opens the Amba disclosure page. It shows the destination's domain, your display name, "Paid partnership with <sponsor>" when the code is marked sponsored, "Checked by Amba", one Continue button and a small Report link. It carries no ads and never forwards on its own.
- Pro plan: a scan goes straight to the destination.
Amba records a scan when the short link opens and a continue when a visitor taps Continue. Link previews (chat apps, social crawlers) and other bots are recorded apart and left out of every count. Visitors are counted with a hash that rotates daily; Amba never stores a visitor's IP address.
UTM tags
Unless you set utm_mode: "off", Amba adds these tags to the destination:
| Tag | Value |
|---|---|
utm_source | amba_qr |
utm_medium | the code's platform |
utm_campaign | campaign, else the slug |
utm_content | the slug |
A tag the destination already carries keeps its value, so a brand's own utm_source or utm_campaign stays as the brand set it. final_url on every code shows the exact URL scanners land on.
platform is one of tiktok, instagram, youtube, x, snapchat, twitch, facebook, linkedin or other.
Destination safety
A QR code is a link strangers open on trust, so Amba checks every destination when you create a code and every time you change its destination. A destination must:
- start with
http://orhttps://, on the standard port; - use a public domain name (IP addresses,
localhostand private names are refused); - carry no
user:password@part; - be the final link: links from other link shorteners (bit.ly, tinyurl.com, t.co, goo.gl, ow.ly, is.gd, buff.ly, rebrand.ly, cutt.ly, shorturl.at, tiny.cc, lnkd.in, rb.gy, t.ly and similar) and from open redirectors (such as Google's
/urllinks) are refused, and retailer links such asamzn.toare fine; - point outside
amba.host(QR links and apps hosted on Amba are refused); - use no international domain name that mixes alphabets in one label or imitates a well-known brand.
A refused destination returns 400 QR_DESTINATION_REJECTED, with details.reason naming the rule: invalid_url, too_long, scheme, port, userinfo, ip_host, not_public_host, shortener, qr_host, amba_host or lookalike.
Amba also checks the destination against lists of known malware, phishing and unwanted-software sites, and its domain against a list of malicious domains. A listed destination returns 400 QR_DESTINATION_UNSAFE. While the check has not answered, the code's safety.verdict is pending and the code keeps working.
Amba re-checks the destination of every active code: daily for codes scanned in the last 30 days, weekly for the rest. A destination that has since been listed turns its codes off for review.
Visitors can report a code from the disclosure page. Three reports from different visitors within 24 hours turn the code off for review, whether it was on or paused, and every code that gets reports is flagged to Amba. A code Amba turned off has status disabled_safety; it cannot be edited, and scanners see a page saying the code is turned off. After review, Amba turns it back to the status it had.
Amba can also suspend QR codes on an account under review. A suspended account gets 403 QR_ACCOUNT_SUSPENDED when it creates a code or turns one back on.
Daily caps
Caps count a rolling 24 hours and answer 429 QR_DAILY_CAP with details.limit:
| Action | Free | Pro |
|---|---|---|
| New codes | 50 | no cap |
| New codes, account under 7 days old | 20 | 20 |
| Destination changes | 20 | no cap |
Deleted codes count toward the new-code cap. Changes that leave the destination alone (label, sponsor, status) are not capped. Creates and destination changes are also limited to 30 a minute per account (429 RATE_LIMIT_EXCEEDED with Retry-After).
Changing and turning off a code
The slug never changes. PATCH /v1/qr/:id (or amba_qr_update) with a new destination_url re-runs the safety checks and appends the change to the code's destination history, which GET /v1/qr/:id returns newest first (the latest 500 changes).
status: "disabled_owner"turns the code off; scanners see the turned-off page.status: "active"turns it back on.DELETE /v1/qr/:iddeletes the code. It leaves your list, scanners see the turned-off page, and its slug is never given to another code.- When an Amba account is deleted, each of its codes is turned off the same way. Amba keeps only the slug, so scanners see the turned-off page and the slug is never given to another code; the destination, label, history, scans and reports are deleted with the account.
Stats
GET /v1/qr/:id/stats?from=YYYY-MM-DD&to=YYYY-MM-DD (or amba_qr_stats) returns a daily series of scans, continues and unique visitors, in UTC days, and totals for the range. The default range is the last 30 days. Visitor ids rotate daily, so the range total is visitor_days: each day's unique visitors added up, with a visitor who returns on another day counted again.
- Free: the last 30 days. Older
fromdates are moved up and the response carrieshistory_limited: true.by_countryandby_device_osarenull. - Pro: the full history (up to 400 days per request), with breakdowns by country and device OS.
CSV export
On Pro, GET /v1/qr/:id/export.csv downloads the code's stats as CSV: one row per UTC day, country and device OS, with scans, continues and unique_visitors. from and to (YYYY-MM-DD) narrow the range; without them the file covers the code's whole history, up to 200,000 rows (400 QR_EXPORT_TOO_LARGE past that). The free plan answers 402 QR_PRO_REQUIRED.
Images
GET /v1/qr/:id/image?format=svg|png&size=<px> (or amba_qr_image) returns the code on a card: the Amba mark, the code, the go.amba.host/<slug> short link, the destination domain and "via amba". The PNG is the same design rendered size pixels wide (256 to 2048, default 1024). Amba keeps recent renders; fresh PNG renders are limited to 20 a minute per caller (429 RATE_LIMIT_EXCEEDED).
Creating, reading (GET /v1/qr/:id) and editing a code return image_urls.svg and image_urls.png: signed links that open without signing in for 7 days, for sharing with whoever makes the post.
On Pro, fg and bg (hex colours such as #1d3557) set custom colours. Phones read dark codes on light backgrounds, so fg must be the darker colour with a contrast ratio of at least 4:1 (400 QR_COLORS_LOW_CONTRAST otherwise). The free plan answers 402 QR_PRO_REQUIRED.
Plans and pricing
| Free | Pro | |
|---|---|---|
| Price | $0 | $10/month per account |
| QR codes | Unlimited | Unlimited |
| What a scan opens | Amba disclosure page | The destination |
| Stats history | Last 30 days | Full history |
| Country and device breakdowns | No | Yes |
| Brand shares | 1 active share | Unlimited |
| CSV export | No | Yes |
| Custom QR colours | No | Yes |
On the free plan, custom colours and CSV export answer 402 QR_PRO_REQUIRED, and a second active brand share answers 403 QR_SHARE_LIMIT. Both carry details.upgrade, naming the call that upgrades.
Upgrade to Pro
QR Pro is billed to your Amba account with its own subscription. Project plans are billed apart: a project upgrade leaves your QR plan as it is, and QR Pro leaves every project's plan as it is.
amba_qr_upgrade(orPOST /v1/qr/billing/checkout) returns a checkout link for the account owner to open. Pro applies as soon as checkout completes, and scans switch to the direct redirect within a minute.amba_qr_billing_status(orGET /v1/qr/billing) shows the plan, the subscription status,renews_at, andends_atonce a canceled subscription is running to the end of its paid period.POST /v1/qr/billing/portalreturns a billing portal link to change the card, read invoices or cancel.
The plan follows the subscription: Pro while it is active or trialing, and for 14 days while a failed renewal is retried; Free once it ends. Billing updates apply in the order they happened, whatever order they arrive in, so an ended subscription stays ended, and a new checkout puts the account back on Pro as soon as its payment goes through. Back on Free, every code keeps working and opens the disclosure page, shares made on Pro keep working, and stats older than 30 days stay stored for when Pro returns.
Sign up as a creator
Creators sign up with an email code, with no password and no project:
/verify returns a sign-in session (access_token, refresh_token) and, for a new account, its personal access token (pat, shown once). Use the PAT as the Bearer for /v1/qr and the MCP tools. An address that already has an Amba account with a proven email signs in and keeps its existing PAT (pat: null). The code expires in 10 minutes and five wrong guesses lock it.
display_name is the name scanners see on the disclosure page: a plain name of up to 80 characters, with no links, domains or "Amba". Change it later with amba_qr_profile_update or PATCH /v1/qr/me.
| Error | Meaning |
|---|---|
403 CREATOR_SIGNUPS_CLOSED | Creator signups are closed right now |
429 CREATOR_SIGNUPS_DAILY_CAP | Amba reached its daily limit on new creator accounts; try again later |
401 CREATOR_CODE_INVALID | The code is wrong, used, locked or expired; request a new one |
400 DISPOSABLE_EMAIL | Disposable email addresses are refused |
409 CREATOR_ACCOUNT_UNPROVEN | An Amba account that never proved this address uses it; sign in with a code from POST /v1/auth/developer/otp/request |
Share stats with a brand
A share is a read-only, Amba-branded dashboard of some of your codes for one brand contact. amba_qr_share (or POST /v1/qr/shares) emails the viewer a link to https://go.amba.host/s/<token>, and returns the same link to you. The dashboard shows only the codes in the share: scans, continues, unique visitors and the changes to where each code leads (the latest 500). It follows your plan: the last 30 days on Free; on Pro, up to 400 days at a time with country and device OS.
Brand shares open together with the brand dashboard page; until then POST /v1/qr/shares answers 503 QR_SHARES_NOT_AVAILABLE.
- The free plan keeps one active share at a time (
403 QR_SHARE_LIMIT); Pro has no limit. Any account creates up to 20 shares per 24 hours, and up to 3 for the same viewer. - Share names are plain text, with no links, domains or "Amba". Codes Amba turned off for safety cannot be shared (
409 QR_DISABLED_FOR_SAFETY), and a share shows such a code without its destination. amba_qr_shares_list(GET /v1/qr/shares) shows each share's codes and when the viewer last opened it. The link itself is shown only once, when you create the share.amba_qr_unshare(DELETE /v1/qr/shares/:id) turns a link off; the viewer then sees an "invalid or turned off" page. Deleting a code removes it from every share.
Dashboards on go.amba.host
Both dashboards run on the short host and work in any browser, on a phone or a laptop.
Brand dashboard, https://go.amba.host/s/<token>. The link in the share email opens a read-only page with one card per shared code: label, platform, a link to the post, the paid-partnership line when the code is marked sponsored, scans, people who continued (clicks on Pro), unique visitors, a daily chart, top countries and devices (Pro) and every change to where the code leads. Presets cover 7 days, 30 days and all history; when your plan limits history, the page says so. The link is the credential, so it needs no sign-in and no cookies. The page asks search engines not to index it and sends no referrer. A turned-off or unknown link shows a plain "does not exist" page. The footer reads "Verified by Amba. Counts exclude bots."
Creator dashboard, https://go.amba.host/me. Sign in with the 6-digit code Amba emails you; a new address creates your creator account. From there you create codes, see each code's stats, download the SVG or PNG, copy the link, edit the destination, turn a code off or on, and share codes with brands. When Pro is available for your account, the page shows an "Upgrade to Pro ($10/month)" button, and a "Manage billing" button once you are on Pro. The sign-in session lasts up to 24 hours and lives in a cookie that only go.amba.host/me receives (HttpOnly, Secure, SameSite=Lax). Every form carries a CSRF token, and sign-in attempts are rate limited per address and per network.
API reference
See QR Codes API for every endpoint, request field and error code.