Developers

A QR code API. And an MCP server.

Make verified picture codes from your own software or from an AI agent. One call takes an image and a link and returns a code that scans, activated on your plan, with analytics. Included in the Business plan; the quarter plan can read codes and stats.

Authentication

Base URL https://ariaqr.com/api/v1, JSON in and out. Create a key on your account page, under API & MCP, and send it as a Bearer token. The secret is shown once; revoke and re-create any time. Keys need an active plan: on the quarter plan they read codes, stats, pages and leads; creating or changing anything needs Business. The Node.js and Python helper below is reused by every example on this page, and handles the errors listed under Errors and limits.

# Every request sends the key as a Bearer token.
curl -i https://ariaqr.com/api/v1/codes \
  -H "Authorization: Bearer aq_your_key_here"

Create a code

POST /api/v1/codes runs the same engine and the same verification as the site. By default the code is activated on your plan and comes back ready to print. The image must be square (1:1, within 2%), PNG, JPEG or WebP, up to 10 MB.

curl -X POST https://ariaqr.com/api/v1/codes \
  -H "Authorization: Bearer aq_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/artwork.png",
    "url": "https://example.com/menu",
    "edge": "soft"
  }'
HTTP/1.1 201 Created

{
  "job_id": "…",
  "verified": true,
  "activated": true,
  "code": "a7Bx9Q",
  "short_url": "aqr.li/a7Bx9Q",
  "preview_url": "https://ariaqr.com/api/preview/…",
  "download_url": "https://ariaqr.com/api/download/…",
  "stats_url": "https://ariaqr.com/stats/a7Bx9Q?k=…",
  "pay_url": null
}

Other kinds use kind and fields, with the same field names as the generator: whatsapp, vcard, wifi, upi, email, phone, sms, maps, event, text. Send image_base64 instead of image_url if the image is not online. Set activate: false to generate without spending an activation; the response then carries a pay_url. Add team_id to make the code in a team workspace.

GET /api/v1/codes lists your codes, newest first, as { "codes": [ … ] }. Each entry has the code, short_url, destination, kind, active, created_at, expires_at and stats_url.

Get stats for a code

GET /api/v1/codes/{code} returns the code with its analytics: scans, clicks, unique visitors, 90 days of daily counts, and breakdowns by country, region, city, device and browser. Counts are pseudonymous; there is no per-person data. An unknown code, or one that is not on your account, is a 404.

curl https://ariaqr.com/api/v1/codes/a7Bx9Q \
  -H "Authorization: Bearer aq_your_key_here"
{
  "code": "a7Bx9Q",
  "short_url": "aqr.li/a7Bx9Q",
  "destination": "https://example.com/menu",
  "kind": "website",
  "summary": "https://example.com/menu",
  "active": true,
  "tier": "paid",
  "activation": "plan",
  "created_at": "2026-10-06T09:12:44.000Z",
  "expires_at": null,
  "stats_url": "https://ariaqr.com/stats/a7Bx9Q?k=…",
  "stats": {                      // trimmed: the full object also has regions, postals, langs, heat, points, recent…
    "total": 214, "scans": 198, "clicks": 16, "previews": 3,
    "unique": 171, "repeatRate": 0.12, "last7": 74, "prev7": 51,
    "days": [{ "day": "2026-10-05", "scans": 31, "clicks": 2, "unique": 27 }],
    "countries": [{ "key": "US", "label": "United States", "count": 96, "pct": 48.5 }],
    "cities": [{ "key": "Austin", "label": "Austin", "count": 22, "pct": 11.1 }],
    "os": [{ "key": "iOS", "label": "iOS", "count": 120, "pct": 60.6 }],
    "browsers": [{ "key": "Safari", "label": "Safari", "count": 104, "pct": 52.5 }]
  }
}

Change where a code goes

PATCH /api/v1/codes/{code} with { "destination": "https://…" } points the printed code somewhere else, no reprint. The new address is safety-checked first; one that fails comes back as a 400 with the reason. The response is the updated code, in the same shape as the list entries.

curl -X PATCH https://ariaqr.com/api/v1/codes/a7Bx9Q \
  -H "Authorization: Bearer aq_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "destination": "https://example.com/spring-menu" }'

Landing pages

Landing pages are built, edited and published through the MCP server, with tools such as create_page, update_page, publish_page and page_stats. Building and publishing pages through the MCP server needs Business; on the quarter plan the read tools, such as list_pages and page_stats, still work. The REST API reads back what a page collects, below. The page builder works with Claude and ChatGPT too: Build landing pages with Claude or ChatGPT.

List a page’s leads

GET /api/v1/pages/{id}/leads returns what a landing page’s forms collected, newest first, with the 30-day conversion and leads per printed code. Query: limit (1 to 500, default 50), since_days (1 to 365) and format=csv for the whole list as a CSV file. Only the page’s owner can read it; any other page id is a 404.

# JSON, newest first
curl "https://ariaqr.com/api/v1/pages/your_page_id/leads?limit=100&since_days=30" \
  -H "Authorization: Bearer aq_your_key_here"

# every lead as CSV
curl -o leads.csv "https://ariaqr.com/api/v1/pages/your_page_id/leads?format=csv" \
  -H "Authorization: Bearer aq_your_key_here"
{
  "page": { "id": "…", "title": "Corner Café menu", "live": true },
  "total_kept": 42,
  "last_30d": { "leads": 18, "views": 640, "conversion_pct": 2.8, "from_qr": 14 },
  "by_code": [{ "code": "a7Bx9Q", "scans": 410, "leads": 14, "conversion_pct": 3.4 }],
  "leads": [{
    "id": "…",
    "received": "2026-10-05T18:41:09.000Z",
    "form": "Book a table",
    "source": "qr",
    "code": "a7Bx9Q",
    "city": "Austin",
    "country": "United States",
    "answers": { "Name": "Jordan Lee", "Email": "jordan@example.com", "Guests": "4" }
  }],
  "retention_days": 365
}

MCP server

Streamable HTTP at https://ariaqr.com/api/mcp, same Bearer key. Code tools: create_code, list_codes, get_code_stats, set_destination. Landing-page tools: page_guide, list_templates, list_pages, get_page, create_page, update_page, add_photo, set_address, publish_page, unpublish_page, page_stats, list_leads, set_lead_webhook (publishing needs the quarter plan or Business; lead forms need Business).

Claude (claude.ai and the Claude apps) and ChatGPT add servers by URL and can’t send a header, so use a connector URL, made under Account → API → Connector URLs: https://ariaqr.com/api/mcp/k/aqc_…, with no sign-in. Its token only works with the MCP server, never the REST API; it has the same plan check and rate limit as a key, and stops working the moment you revoke it. Connector URLs made from an API key still work for now, but replace them. Step-by-step for each app: Build landing pages with Claude or ChatGPT.

// Cursor: ~/.cursor/mcp.json (or any MCP client that sends headers)
{
  "mcpServers": {
    "ariaqr": {
      "url": "https://ariaqr.com/api/mcp",
      "headers": { "Authorization": "Bearer aq_…" }
    }
  }
}
# Claude Code
claude mcp add --transport http ariaqr https://ariaqr.com/api/mcp \
  --header "Authorization: Bearer aq_…"

Then ask: “Make an AriaQR code from this product photo that opens our booking page, and tell me how many scans it got this week.” Or: “Make a landing page for my café and publish it.”

Errors and limits

Errors are JSON, { "error": "…" }, with the matching HTTP status. Handle 401, 402 and 429 as the helper under Authentication does: a 429 says how many seconds to wait, and a retry then goes through.

StatusWhenExample message
400Bad input: no image, a non-square or too-large image, a missing url, a destination that is not a full URL or fails the safety check.Image must be square (1:1). Yours is 1200×800.
401No key, a wrong key or a revoked key.Missing or invalid API key. Send `Authorization: Bearer aq_…`.
402The account has no active quarter or Business plan, or no activations left, or a create or change call on the quarter plan (it can only read).API access needs an active quarter plan or Business plan. https://ariaqr.com/pricing
403A team_id you are not a member of.You are not a member of that team.
404A code or landing page that is not on this account.No such code on this account.
429More than 60 requests in a minute on one key.Rate limit: 60 requests a minute. Retry in 12s.
500 / 503Something failed on our side. Safe to retry; a failed build is never charged.Your final code could not be built just now. Try again in a minute; nothing extra will be charged.
  • 60 requests a minute per key.
  • Images up to 10 MB, PNG, JPEG or WebP, and square. Use the site to place a code inside a larger picture.
  • Each activation counts against the plan’s allowance. Generating with activate: false does not.
  • A create call can take up to a few minutes while the code is built and verified; give your client a long timeout.

Changelog

Changes to the REST API and the MCP server that you would notice, newest first.

  1. · MCP

    The quarter plan can publish landing pages: up to 5 new pages a quarter, without form blocks. publish_page explains when a form block or the allowance stops a publish. Lead forms stay on Business.

  2. · Docs and spec

    This page now has runnable cURL, Node.js and Python examples, and the whole REST API is described in OpenAPI 3.1 at /openapi.json.

  3. · MCP

    publish_page waits for the new address to open and returns link_opens_now, so the link you are handed works when you tap it. Business includes up to 100 new landing pages a month.

  4. · REST and MCP

    New: GET /api/v1/pages/{id}/leads returns what a landing page’s forms collected, with 30-day conversion and leads per printed code; ?format=csv exports the whole list. New MCP tools list_leads and set_lead_webhook. Page guide updated for lead forms and 15 form templates.

  5. · MCP

    Landing pages publish to aqr.li addresses. The in-chat page preview looks like a phone. Profile blocks take a cover banner, and animated GIFs stay animated.

  6. · REST

    Business accounts can create API keys and call the API.

  7. · MCP

    Landing-page tools added to the MCP server: page_guide, list_templates, list_pages, get_page, create_page, update_page, add_photo, set_address, publish_page, unpublish_page, page_stats. Claude and ChatGPT can now connect by URL.

  8. · REST

    New codes use the short domain: short_url comes back as aqr.li/<code>.

  9. · REST and MCP

    Codes on a team follow team membership: someone removed from a team loses API and MCP access to that team’s codes.

  10. · REST and MCP

    The square-image rule is spelled out: create_code and POST /api/v1/codes need a square image (1:1, within 2%) and answer a 400 that gives the size otherwise.

  11. · First release

    REST: POST and GET /api/v1/codes, GET and PATCH /api/v1/codes/{code}. MCP server with create_code, list_codes, get_code_stats and set_destination. Bearer keys with a limit of 60 requests a minute.

Questions

What does the AriaQR API do?+

It makes a verified picture QR code from an image URL and a destination in one call, activates it on your plan, and returns the preview, the 2048px download, the short link and an analytics link. It can also list your codes, read scan analytics and change where a code points.

What is the AriaQR MCP server?+

An MCP (Model Context Protocol) endpoint at https://ariaqr.com/api/mcp that exposes the same capabilities as tools, plus the landing-page builder, so Claude, ChatGPT, Cursor and other agents can make and manage codes and pages for you. Authenticate with an API key as a Bearer token, or, in Claude and ChatGPT, add a connector URL (https://ariaqr.com/api/mcp/k/ followed by a connector token) made under Account → API → Connector URLs. The token only works with the MCP server, not the REST API, and you can revoke it any time.

How do I get an API key?+

Start Business for full access, or the quarter plan to read codes, stats, pages and leads, then create a key on your account page. The secret is shown once. Keys can be revoked any time.

What are the limits?+

60 requests a minute per key, images up to 10 MB, and every activation counts against your plan’s allowance. Generation without activation is free and unlimited within the rate limit.