FOR DEVELOPERS AND AI TOOLS

# Make and change QR codes from AI apps and your own code

HueQR has an MCP server, so Claude, ChatGPT and Cursor can create dynamic QR codes, change where they go and read their scans when you ask. It also has a REST API for your own scripts and apps. Both come with [Pro and Organisation](https://hueqr.com/pricing) and work on the same codes you see in the app.

## Connect an AI app with MCP

MCP (Model Context Protocol) is how AI apps use other products for you. Add HueQR once, then ask in plain words: "make a QR code for our spring menu and file it under Harbor Yoga", "point the window poster code at the new booking page", "which of my codes got the most scans this month?"

https://hueqr.com/mcp

### Claude and ChatGPT

In the app's connector settings, add a custom connector and paste the address above. You are sent to HueQR to sign in and press Allow. That is all: no key to copy. You can remove the app's access anytime in HueQR under API and MCP.

### Claude Code

claude mcp add --transport http hueqr https://hueqr.com/mcp

### Cursor and other tools with a config file

{
 "mcpServers": {
 "hueqr": { "url": "https://hueqr.com/mcp" }
 }
}

A tool that cannot open a sign-in page can send an [API key](https://hueqr.com/developers#keys) instead, as the header `Authorization: Bearer hq_live_...`

### What the AI app can do

- Create a code, or up to 50 at once, in a saved brand template
- Change where a code goes, rename it, pause it, resume it or delete it
- Set smart rules: "send iPhones to the App Store and Android to Google Play", "show the lunch menu from 12 to 4"
- Show a code's QR image and its scans by day, phone and city
- List and add client workspaces, and list your domains and templates

Every link is checked for safety, exactly as in the app. A read-only connection can look but not change anything.

## API keys

The account owner makes keys in the app under **API and MCP**. A key is shown once, so copy it then. Each key is read and write or read only, and can be limited to one client workspace. Revoking a key stops it at once.

Send the key as a bearer token on every request. Keep keys on your server: anyone holding one can change your codes.

curl https://hueqr.com/api/v1/codes \\
 -H "Authorization: Bearer hq\_live\_..."

## REST API

The base address is `https://hueqr.com/api/v1`. Requests and answers are JSON. Lists page with `next_cursor`. The same reference is available as [OpenAPI 3.1](https://hueqr.com/api/v1/openapi.json).

### Create a code

curl -X POST https://hueqr.com/api/v1/codes \\
 -H "Authorization: Bearer hq\_live\_..." \\
 -H "Content-Type: application/json" \\
 -d '{
 "name": "Spring menu",
 "destination": "https://example.com/menu",
 "placement": "Window poster"
 }'

{
 "id": "4b1f0c1e-...",
 "name": "Spring menu",
 "type": "website",
 "status": "live",
 "destination": "https://example.com/menu",
 "short\_url": "https://hueqr.com/Xk3pQ",
 "domain": "hueqr.com",
 "placement": "Window poster",
 "client\_id": null,
 "created\_at": "2026-11-06T09:30:00Z",
 "updated\_at": "2026-11-06T09:30:00Z"
}

### Change where it goes, after printing

curl -X PATCH https://hueqr.com/api/v1/codes/4b1f0c1e-... \\
 -H "Authorization: Bearer hq\_live\_..." \\
 -H "Content-Type: application/json" \\
 -d '{ "destination": "https://example.com/summer-menu" }'

### Every endpoint

- GET `/codes`

 List codes, newest first

 QUERY

 limit

 1 to 100, default 25.

 cursor

 next\_cursor from the last page.

 client\_id

 Only one client's codes.

 status

 live, paused or blocked.

 type

 Only one type of code.

 q

 Only names containing this text.

 RETURNS { data: Code\[\], next\_cursor }

- POST `/codes`WRITE KEY

 Create a code

 BODY

 name

 A name to recognise the code by. Required.

 type

 What it opens: website, vcard, wifi, text, links, email, sms, phone. Default website.

 destination

 Website codes: the link it sends people to.

 placement

 Where it will be printed, to compare placements in analytics.

 client\_id

 File it under this client workspace. It then uses the client's domain.

 domain

 A connected domain for the short link. Default: the client's domain, else hueqr.com.

 template\_id

 Use a saved brand template's design. Default: plain black.

 design

 Or send a design object (colors, shapes) to style it directly.

 content

 Non-website types: the Wi-Fi details, text, links, email, SMS or phone number.

 utm

 true to add UTM tags to the destination.

 rules

 Website codes: smart rules to set up with the code, in the same shape as PUT /codes/{id}/rules.

 RETURNS The new Code, with its short\_url.

- POST `/codes/bulk`WRITE KEY

 Create up to 100 codes

 BODY

 codes

 A list of codes, each with the same fields as POST /codes.

 RETURNS { created, failed, results: \[{ index, ok, code | error }\] }

- GET `/codes/{id}`

 Get one code

 RETURNS Code

- PATCH `/codes/{id}`WRITE KEY

 Change a code

 BODY

 destination

 A new link. Printed codes keep working.

 name

 A new name.

 placement

 A new placement.

 status

 live or paused.

 client\_id

 Move it to a client, or null for none.

 RETURNS The updated Code.

- DELETE `/codes/{id}`WRITE KEY

 Delete a code

 RETURNS { id, deleted: true }. Anything printed with it stops working.

- GET `/codes/{id}/qr`

 Get the QR image

 QUERY

 format

 svg, png, pdf, eps. Default svg.

 size

 PNG width in pixels, 128 to 4096. Default 1024.

 RETURNS The image file, in the code's saved design.

- GET `/codes/{id}/scans`

 Get scan analytics

 QUERY

 days

 1 to 90, default 30.

 RETURNS { scans, unique\_scanners, previous\_period\_scans, by\_day, devices, cities }

- GET `/codes/{id}/rules`

 Get smart rules

 RETURNS { code\_id, default\_destination, timezone, rules: \[{ id, conditions, destination, enabled, description }\] }

- PUT `/codes/{id}/rules`WRITE KEY

 Set smart rules

 BODY

 rules

 The full list, in order: the first enabled rule that matches a scan wins. Each is { conditions: \[...\], destination, enabled }. An empty list removes every rule.

 RETURNS The rules as saved. Website codes only.

- GET `/places`

 Find place ids for location rules

 QUERY

 q

 The start of a country, region or city name.

 RETURNS { data: \[{ id, name, in, level }\] }

- GET `/clients`

 List client workspaces

 RETURNS { data: Client\[\] }

- POST `/clients`WRITE KEY

 Add a client workspace

 BODY

 name

 The client's name. Required.

 website

 Their website, for brand match.

 domain

 A connected domain for their codes.

 RETURNS The new Client.

- GET `/domains`

 List domains

 RETURNS { data: \[{ hostname, status, default }\] }

- GET `/templates`

 List brand templates

 RETURNS { data: \[{ id, name }\] }

- GET `/usage`

 Get plan usage

 RETURNS { plan, codes, scans\_this\_month, clients, requests\_per\_minute }

## Smart rules

Smart rules send some scans somewhere else: by device, place, time of day, weekday, phone language, date or how many scans the code has had. They are checked in order and the first one that is on and matches wins. A scan that matches no rule goes to the code's main destination. A code can have up to 20 rules, on website codes only.

`PUT /codes/{id}/rules` replaces the whole list, so to change one rule, read the list, change it and send it all back. An empty list removes every rule.

curl -X PUT https://hueqr.com/api/v1/codes/4b1f0c1e-.../rules \\
 -H "Authorization: Bearer hq\_live\_..." \\
 -H "Content-Type: application/json" \\
 -d '{
 "rules": \[
 {
 "conditions": \[{ "type": "device", "device": "ios" }\],
 "destination": "https://apps.apple.com/app/id123"
 },
 {
 "conditions": \[
 { "type": "weekday", "days": \["sat", "sun"\] },
 { "type": "time", "from": "10:00", "to": "15:00" }
 \],
 "destination": "https://example.com/brunch"
 }
 \]
 }'

Every condition on a rule has to match, and a rule uses each type once at most. Times, weekdays and dates are read in your account's timezone, which the rules come back with.

device

{ "type": "device", "device": "ios" | "android" | "desktop" }

location

{ "type": "location", "places": \["US", "CA-ON", "CA-ON/toronto"\] } with place ids from the places search. Countries are exact; regions and cities are approximate.

time

{ "type": "time", "from": "12:00", "to": "16:00" } in the account's timezone. A window may pass midnight.

weekday

{ "type": "weekday", "days": \["sat", "sun"\] }

language

{ "type": "language", "languages": \["es", "pt"\] } matched against the phone's first language.

dates

{ "type": "dates", "from": "2026-12-01", "to": "2026-12-31" } inclusive; either end may be left out.

scans

{ "type": "scans", "first": 100 } for the first 100 scans, or { "type": "scans", "after": 100 } from then on.

Location rules use place ids. Find them with `GET /places?q=toronto`, which answers with ids like `CA-ON/toronto`. Every rule's link gets the same safety check as the code's own.

## Errors and limits

An error is always `{ "error": { "code", "message" } }` with a matching status. The message is written for a person, so it is safe to show.

| Status | Code | What it means |
| --- | --- | --- |
| 400 | invalid_request | A field is missing or has a value that is not allowed. |
| 401 | unauthorized | No key, or a key that is wrong or revoked. |
| 403 | plan_required | The account is not on Pro or Organisation. |
| 403 | read_only_key | A read-only key tried to change something. |
| 404 | not_found | No code, client or template with that id on this account. |
| 422 | invalid_code | The code could not be made as sent. The message says why. |
| 400 | invalid_rules | A smart rule is not complete or not valid. The message names the rule and says why. |
| 422 | link_blocked | The link was flagged as unsafe, so it was refused. |
| 422 | code_limit | The batch would go over the plan's number of codes. |
| 429 | rate_limited | Too many requests in a minute. Wait and try again. |

Each key can make 60 requests a minute on Pro, and 300, 600, 1,200 on Organisation 500, 1,000, 2,500. The API and the MCP server never sit in the path of a scan, so a busy script cannot slow your codes down.

Not in the API yet: PDF codes are made in the app. Tell us what you need at [hello@hueqr.com](mailto:hello@hueqr.com).

---

Source: https://hueqr.com/developers
