Qravio
QR code API for tickets

A unique QR code for every ticket you sell

Create a dynamic code at checkout that opens the attendee ticket page. Give it an end date so it stops after the event, and pause it the moment a ticket is refunded or resold.

curl
curl -X POST https://api.qravio.app/api/public/v1/qrcodes/bulk \
  -H "Authorization: Bearer $QRAVIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "name": "Order 88213 seat B12",
        "type": "website",
        "category": "dynamic",
        "content": {
          "url": "https://example.com/tickets/88213?seat=B12"
        },
        "destinations": [
          {
            "target_url": "https://example.com/tickets/88213?seat=B12"
          }
        ],
        "client_ref": "order-88213-B12",
        "end_at": "2026-11-15T23:59:00Z"
      },
      {
        "name": "Order 88213 seat B13",
        "type": "website",
        "category": "dynamic",
        "content": {
          "url": "https://example.com/tickets/88213?seat=B13"
        },
        "destinations": [
          {
            "target_url": "https://example.com/tickets/88213?seat=B13"
          }
        ],
        "client_ref": "order-88213-B13",
        "end_at": "2026-11-15T23:59:00Z"
      }
    ]
  }'

How the integration works

Your booking flow calls the API after payment with the order and seat as the client_ref, and emails the preview_url image with the confirmation. Set end_at to the close of the event. A refund triggers a PATCH that sets status to paused.

  1. 1Create an API key under Developers in your workspace.
  2. 2After payment, create one code per seat with POST /qrcodes/bulk, the order and seat as client_ref, and end_at set to the end of the event.
  3. 3Send the preview_url image in the confirmation email or wallet page.
  4. 4On a refund, PATCH the code with status "paused" so it opens nothing.

What you get

Codes that expire

end_at stops a code working after the event, so a screenshot shared next week opens nothing.

Void on refund

Setting status to paused turns a single ticket off without touching the rest of the order.

A cap on opens

scan_limit limits how many times a code can open its page, which discourages passing one screenshot around a group.

Know when people arrive

The scan webhook posts each scan to your server as it happens, with the QR id you stored against the order.

What each plan allows

Every call counts against the monthly quota, and a bulk request counts one call per item. Static codes use calls but not the dynamic QR allowance.

PlanAPI callsDynamic QRsWebhooks
Free, StarterNo API accessn/aNo
Pro3,000 a month300Scan, lead, scan limit
Agency25,000 a monthNo capAdds scan milestones

Prices are on the pricing page.

Tickets API FAQ

Does Qravio check tickets at the door?

No. A scan opens the page you chose. Door validation, marking a ticket used, is logic in your own app, and the scan webhook gives you the event to build it on.

Will a limited code lock out the attendee if they check it at home?

It can, because every open counts. Use scan_limit as a generous ceiling rather than a single-use rule, or leave it off and rely on end_at.

How many tickets can I issue?

Each ticket is one API call and one dynamic QR. Pro allows 300 dynamic QRs; Agency has no QR cap and 25,000 calls a month.

Start generating codes

Create an account, upgrade to Pro or Agency, and make a key under Developers in your workspace.