GET /v1/account
Get account. MCP tool get_account.
The signed-in Scanlo account: plan, how many QR codes and hubs it uses and may have, and how far back its scan stats go. Call this first, and to explain why a create was refused.
Everything you do with QR codes in the Scanlo dashboard, an assistant or a script can do too: create a code or a hub, change where it points, switch it off, and read its scans. One remote MCP server for Claude, ChatGPT and other assistants, and a REST API with the same operations. Both are on every plan, including free.
https://mcp.scanlo.iohttps://api.scanlo.io/v1Add the MCP server address, then sign in to Scanlo when the assistant asks. You choose which account it can use on a Scanlo consent screen, and you can take access away at any time under My profile, Connected apps. Disconnecting inside the assistant only makes it forget its token; removing it in Scanlo is what ends its access.
claude mcp add --transport http scanlo https://mcp.scanlo.ioThen ask, for example:
| Tool | What it does | Changes data |
|---|---|---|
| get_account | The signed-in Scanlo account: plan, how many QR codes and hubs it uses and may have, and how far back its scan stats go. Call this first, and to explain why a create was refused. | No |
| list_codes | Every QR code and hub on the account, with its short URL, destination, status and a link to its QR image (SVG). | No |
| create_code | Create a tracked QR code that sends every scan to one link. Types: review (a Google or other review page), booking (a booking page), payment (one payment link). For several payment or review options behind one code, use create_hub. The destination is checked for safety; plan limits apply. | Yes |
| get_code | One QR code or hub: where it points, its status, its QR image URL and, for a hub, every button with its id (pass those ids to update_hub to keep each button's tap history). | No |
| update_code | Change a QR code (not a hub; use update_hub): its destination, name or placement, or switch it off and on. A printed code keeps its pixels; only where it leads changes. Switching off shows scanners a "no longer available" page and frees a plan slot. Changes reach the printed code within about a minute. | Yes |
| get_scan_stats | Scans of one QR code or hub, or of the whole account when code_id is left out: total and per day, plus where they came from (scan or a tap on a website embed). Standard adds countries, devices, referrers, per-placement totals and bot filtering. Hub button taps are in get_hub_stats. | No |
| create_hub | Create a hub: one printed QR code that opens a page of buttons, e.g. Venmo, PayPal and Zelle on a payment hub, or Google and Yelp on a review hub. Types: payment, review, tip, donation. Each button is tracked separately. Hubs have their own plan limit (free: one hub in total). | Yes |
| update_hub | Change a hub: its buttons, page title and description, name or placement, the "Powered by Scanlo" footer (Standard only), or switch it off and on. Its type (payment, review, tip, donation) is fixed: for another type, create a new hub. links replaces the whole set: call get_code first and pass each kept button's id, or its tap history starts again. Changes reach the printed code within about a minute. | Yes |
| get_hub_stats | For one hub: how many people scanned it and how many tapped a button, so you can see how many scanners went on to pay or review. Standard adds the taps per button (which payment app wins). | No |
There is no delete tool. A printed code should not disappear because an assistant misread a request, and a code that has been scanned cannot be deleted at all. Switching a code off is the strongest change an assistant can make.
Base URL https://api.scanlo.io. JSON in, JSON out. Every endpoint is one of the MCP tools above, with the same arguments and the same answers.
The API takes an OAuth 2.1 access token, the same kind an assistant gets. There are no API keys yet. Any standard OAuth client library can get a token:
https://api.scanlo.io/.well-known/oauth-protected-resource. It lists the authorization server, and that server's metadata lists every endpoint below.Authorization: Bearer <token>.curl https://api.scanlo.io/v1/account \
-H "Authorization: Bearer $SCANLO_TOKEN"curl -X POST https://api.scanlo.io/v1/codes \
-H "Authorization: Bearer $SCANLO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "review",
"name": "Front desk reviews",
"destination_url": "https://g.page/r/your-place/review",
"placement": "front desk"
}'The answer carries the short URL, a link to the QR image as SVG and the code's page in the dashboard, where the print files are.
An error is a status code and a body of { "error": "..." }, written so you can show it to the person as is.
Get account. MCP tool get_account.
The signed-in Scanlo account: plan, how many QR codes and hubs it uses and may have, and how far back its scan stats go. Call this first, and to explain why a create was refused.
List QR codes. MCP tool list_codes.
Every QR code and hub on the account, with its short URL, destination, status and a link to its QR image (SVG).
Create QR code. MCP tool create_code.
Create a tracked QR code that sends every scan to one link. Types: review (a Google or other review page), booking (a booking page), payment (one payment link). For several payment or review options behind one code, use create_hub. The destination is checked for safety; plan limits apply.
| Field | In | Type | Description |
|---|---|---|---|
| type | body | "review" | "booking" | "payment" | What the code is for. |
| name | body | string, up to 80 chars | Internal name, shown only in the dashboard. |
| destination_url | body | string, up to 2048 chars | Where a scan goes. https:// is added if missing. |
| placement? | body | string, up to 80 chars | Where the code is placed, e.g. "front desk" or "receipt". Placement reports group by it. |
Get QR code. MCP tool get_code.
One QR code or hub: where it points, its status, its QR image URL and, for a hub, every button with its id (pass those ids to update_hub to keep each button's tap history).
| Field | In | Type | Description |
|---|---|---|---|
| id | path | uuid | Id of the code or hub, from GET /v1/codes. |
Update QR code. MCP tool update_code.
Change a QR code (not a hub; use update_hub): its destination, name or placement, or switch it off and on. A printed code keeps its pixels; only where it leads changes. Switching off shows scanners a "no longer available" page and frees a plan slot. Changes reach the printed code within about a minute.
| Field | In | Type | Description |
|---|---|---|---|
| id | path | uuid | Id of the code or hub, from GET /v1/codes. |
| destination_url? | body | string, up to 2048 chars | New destination for every scan. |
| name? | body | string, up to 80 chars | Internal name, shown only in the dashboard. |
| placement? | body | string, up to 80 chars | Where the code is placed, e.g. "front desk" or "receipt". Placement reports group by it. |
| active? | body | boolean | false switches the code off; true switches it back on (needs a free slot). |
Get scan stats. MCP tool get_scan_stats.
Scans of one QR code or hub, or of the whole account when code_id is left out: total and per day, plus where they came from (scan or a tap on a website embed). Standard adds countries, devices, referrers, per-placement totals and bot filtering. Hub button taps are in get_hub_stats.
| Field | In | Type | Description |
|---|---|---|---|
| id | path | uuid | Id of the code or hub, from GET /v1/codes. |
| days? | query | integer, 1 to 90 | How many days back. Default 30. Free plan sees at most 30, Standard 90. |
| include_bots? | query | boolean | Count link previews and scanners too. Default true. Only Standard can exclude them. |
Get scan stats. MCP tool get_scan_stats.
Scans of one QR code or hub, or of the whole account when code_id is left out: total and per day, plus where they came from (scan or a tap on a website embed). Standard adds countries, devices, referrers, per-placement totals and bot filtering. Hub button taps are in get_hub_stats.
| Field | In | Type | Description |
|---|---|---|---|
| days? | query | integer, 1 to 90 | How many days back. Default 30. Free plan sees at most 30, Standard 90. |
| include_bots? | query | boolean | Count link previews and scanners too. Default true. Only Standard can exclude them. |
Create hub. MCP tool create_hub.
Create a hub: one printed QR code that opens a page of buttons, e.g. Venmo, PayPal and Zelle on a payment hub, or Google and Yelp on a review hub. Types: payment, review, tip, donation. Each button is tracked separately. Hubs have their own plan limit (free: one hub in total).
| Field | In | Type | Description |
|---|---|---|---|
| type | body | "payment" | "review" | "tip" | "donation" | What the hub is for. |
| name | body | string, up to 80 chars | Internal name, shown only in the dashboard. |
| title? | body | string, up to 80 chars | Heading on the hub page, e.g. the business name. |
| placement? | body | string, up to 80 chars | Where the code is placed, e.g. "front desk" or "receipt". Placement reports group by it. |
| links | body | array of object, up to 10 | The buttons, in display order. Free plan: up to 2. |
| links[].provider | body | string | Provider key. Allowed per hub type: payment: paypal, venmo, cashapp, zelle, stripe, square, gofundme; review: google, facebook, trustpilot, yelp, bbb, tripadvisor, angi, g2, capterra; tip: paypal, venmo, cashapp, zelle, stripe, square, gofundme; donation: paypal, venmo, cashapp, zelle, stripe, square, gofundme. "custom" (any link) needs the Standard plan. |
| links[].label | body | string, up to 80 chars | Button text, e.g. "Pay with Venmo". |
| links[].url | body | string, up to 2048 chars | Where the button goes: the business's own profile or payment link. |
Update hub. MCP tool update_hub.
Change a hub: its buttons, page title and description, name or placement, the "Powered by Scanlo" footer (Standard only), or switch it off and on. Its type (payment, review, tip, donation) is fixed: for another type, create a new hub. links replaces the whole set: call get_code first and pass each kept button's id, or its tap history starts again. Changes reach the printed code within about a minute.
| Field | In | Type | Description |
|---|---|---|---|
| id | path | uuid | Id of the hub, from GET /v1/codes. |
| links? | body | array of object, up to 10 | The full new set of buttons, in display order. Buttons left out are removed. |
| links[].provider | body | string | Provider key. Allowed per hub type: payment: paypal, venmo, cashapp, zelle, stripe, square, gofundme; review: google, facebook, trustpilot, yelp, bbb, tripadvisor, angi, g2, capterra; tip: paypal, venmo, cashapp, zelle, stripe, square, gofundme; donation: paypal, venmo, cashapp, zelle, stripe, square, gofundme. "custom" (any link) needs the Standard plan. |
| links[].label | body | string, up to 80 chars | Button text, e.g. "Pay with Venmo". |
| links[].url | body | string, up to 2048 chars | Where the button goes: the business's own profile or payment link. |
| links[].id? | body | uuid | Id of an existing button to keep. |
| title? | body | string, up to 80 chars | Heading on the hub page. |
| description? | body | string, up to 300 chars | Text under the heading (Standard only). |
| show_scanlo_branding? | body | boolean | The "Powered by Scanlo" footer. Only Standard can turn it off. |
| name? | body | string, up to 80 chars | Internal name, shown only in the dashboard. |
| placement? | body | string, up to 80 chars | Where the code is placed, e.g. "front desk" or "receipt". Placement reports group by it. |
| active? | body | boolean | false switches the hub off; true switches it back on (needs a free slot). |
Get hub stats. MCP tool get_hub_stats.
For one hub: how many people scanned it and how many tapped a button, so you can see how many scanners went on to pay or review. Standard adds the taps per button (which payment app wins).
| Field | In | Type | Description |
|---|---|---|---|
| id | path | uuid | Id of the hub, from GET /v1/codes. |
| days? | query | integer, 1 to 90 | How many days back. Default 30. Free plan sees at most 30, Standard 90. |
| include_bots? | query | boolean | Count link previews and scanners too. Default true. Only Standard can exclude them. |
A field ending in ? is optional. Questions or a missing operation: contact us.