Edit a QR after printing
A static QR code is a dead end the moment it's printed on a menu, a poster or a product box: the destination is baked into the pixels forever. This dynamic qr code api generates a code that points to a short redirect you control, so you can retarget the same printed image next month, next year, or the day after a campaign launches, without reprinting anything.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The problem with a QR code printed on paper
Once a QR code is on a physical surface, it's immutable. If the URL it encodes goes offline, gets restructured, or simply needs to point somewhere else for a seasonal promotion, the printed code becomes useless while the paper or plastic it's on stays in circulation for months. A restaurant that reprints its menu every time a delivery link changes, or a manufacturer that etches a QR into a mold that will produce thousands of identical units, both hit the same wall: the code and the destination are permanently welded together.
How a dynamic code breaks that link
POST /dev/qr-dynamic creates a code that encodes a fixed short URL under our control, which then redirects to whatever target you configure. The printed pixels never change. What changes is the redirect target behind them, which you can update as many times as needed after the code is already out in the world, on a truck, a business card, or a warehouse shelf.
What you get back
The task returns a QR code image plus the redirect identifier tied to it, delivered by signed webhook or a signed link valid for 24 hours. You provide the initial destination and any visual parameters the format supports; retargeting later is a separate lightweight call against the same code, not a new QR generation.
A short history worth knowing
QR codes were invented in 1994 by the Japanese company Denso Wave to track parts on an automotive assembly line, and their defining feature was always fast machine readability, not human elegance. The redirect layer isn't part of that original 1994 specification, it's a practical pattern built on top of it, and it's exactly what turns a one-shot printed code into something that behaves like a live piece of infrastructure.
Where this fits an automated pipeline
Packaging runs, event badges, vehicle decals and any physical asset with a long shelf life benefit from generating the code once through this endpoint and then updating the target programmatically as inventory moves, campaigns rotate, or products get recalled. Batch generation for a print run and later batch retargeting both go through the same asynchronous task model, so a marketing system can update thousands of physical codes' destinations in one pass without touching a single printed page.
What you can do with it
Seasonal packaging that outlives one campaign
Print a QR on packaging molds that will run for a year, and redirect it to a different landing page each season without changing the physical design.
Recall or safety updates on shipped products
Point an already-printed product QR to updated safety information the moment it's needed, without waiting on a reprint cycle.
Event badges reused year over year
Reuse the same printed badge stock across events by repointing the code to each year's schedule and check-in system.
Delivery menus that change vendors
Keep one printed table tent and swap the underlying delivery link whenever the restaurant changes its ordering platform.
FAQ
What makes this a dynamic qr code api instead of a regular generator?
The printed code encodes a fixed redirect URL that you can repoint to a new destination at any time, instead of encoding the final URL directly.
Can I change the destination after the QR is printed?
Yes, that's the entire purpose: update the redirect target through a separate call and the same physical code starts sending scanners to the new destination immediately.
Is there a limit to how many times I can retarget a code?
No fixed limit is imposed by the format itself; retargeting is a lightweight operation separate from the original QR generation task.
How much does generating a dynamic QR cost?
$0.002 per request plus $0.005 per QR generated, with no charge for a task that fails after retries.
Does this replace a free QR generator?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How do I get the QR code image back?
POST /dev/qr-dynamic returns a task_id immediately, and the finished image is delivered via signed webhook or a signed link valid for 24 hours.
Can I generate a large batch for a print run?
Yes, batches run asynchronously, so a print run of any size can be generated in one submission without blocking your application.
Is scan data stored or used for anything besides redirecting?
Redirect data is retained only for the stated retention period and is never used for training; it exists solely to route the scan.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev/qr-dynamic \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/dev/qr-dynamic", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"input": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/qr-dynamic",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"input": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/qr-dynamic", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"input":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"input":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/qr-dynamic", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"input": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.qr_dynamic",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |