API
QR code API: create and manage dynamic QR links from code
Create, update, archive and measure dynamic QR code links from your own software with the KeptLink API. It is included in the Business plan.
Updated
In short
The KeptLink API lets your software create, update, archive and measure dynamic QR code links with an API key. It is included in the Business plan, with 5,000 calls per rolling 24 hours. Paid codes keep working even if you cancel, subject to safety checks.
Why software needs a dynamic QR code API
A printed QR code cannot change. The link behind a dynamic code can. That is why many teams manage their codes from software instead of by hand.
A static QR code stores the web address inside the pattern. Once it is printed, the address is fixed. A dynamic QR code stores a short link instead. A redirect sends each scan from the short link to your destination page. You can change the destination later, and the printed code still works. The static vs dynamic QR codes guide compares the two in detail, and the dynamic QR codes page shows how KeptLink handles them.
An API (application programming interface) lets one program send requests to another. With the KeptLink API, your software creates and edits short links the same way a person does in the dashboard. A few jobs where that helps:
- Event badges. Your registration system makes one link per attendee. When an attendee changes a session or a detail, your system updates that link. The badge stays the same.
- Direct mail. A print team creates a link for each postcard batch, then reads visit totals for each one after the mail lands.
- Equipment tags. A tag on a machine points to a maintenance log. When the vendor or the manual changes, a script updates the destination. Nobody climbs a ladder to replace a tag.
- Restaurant platforms. Each new location needs its own menu link. Your onboarding script creates it with the rest of the setup.
If you only need a fixed link or fixed text, a static code is enough. The dynamic route pays off when the destination may change or when you want visit totals.

- POST /api/v1/links Authorization: Bearer kl_live_… { "destination": "https://…" }Your softwareSends one request with an API key.
- keptlink.app/
k7m2xqa A new linkThe same safety checks as the dashboard. - Its QR codeThe response includes the code's address (qr_url).
What you can do with API v1
The API lives at https://app.keptlink.com/api/v1. Each request pairs a method (what you want to do) with a path (what you want to do it to). Here are the six endpoints.
| Method and path | What it does |
|---|---|
POST /api/v1/links |
Create a link |
GET /api/v1/links |
List links |
GET /api/v1/links/:id |
Get one link |
PATCH /api/v1/links/:id |
Update a link |
POST /api/v1/links/:id/archive |
Archive a link |
GET /api/v1/links/:id/analytics/summary |
Read visit totals |
In these paths, :id is the id of the link you want to work with. Everything is JSON, with field names in snake_case and times in ISO 8601 (UTC).
When you create a link, destination is the only required field. These optional fields help with real projects:
titleandtagskeep your links easy to find.codepicks your own short code on plans that allow it. Without it, KeptLink makes a random one.domain_idputs the link on one of your active custom domains. Without it, the link uses keptlink.app. See custom domains and the custom domain setup guide.utmadds UTM tags (source, medium, campaign, term and content) to the destination when a visitor is redirected.forward_querypasses the short link’s query string on to the destination.
The list endpoint returns up to 100 links per page and gives you a next_cursor to ask for the next page. You can filter by status, which is active or archived.
The visit summary takes days (the default is 30) or a from and to date. It returns visits, qr_visits, link_visits and visitor_days, plus all_time_visits. Keep the meaning in mind. A QR visit is very likely a scan, but it is not proof of one. visitor_days counts distinct visitors per day and adds the days up. It is approximate, and it is not a count of unique visitors over the whole range. For the dashboard view of the same data, see QR code tracking.
Two limits are worth knowing before you plan a job:
- API v1 manages links and visit totals. It does not return QR image files. Each link includes
qr_url, the address its QR code holds. If you need print files, read the SVG vs PNG vs PDF guide. - There is no bulk endpoint. Each call handles one link. For spreadsheets of links, see bulk QR codes.
The full list of fields, errors and responses is in the KeptLink API reference.
Sign in and stay inside the quota
The API uses a secret key. Owners and admins create keys in the dashboard under Workspace settings, then API keys. A key is shown once, so save it somewhere safe. It works for its own workspace only and can do what an editor can do. It cannot touch billing or members. If you revoke a key, it stops working on the next request.
Send the key in the Authorization header, a line of text that travels with each request. Here is a first call that creates a link. curl is a tool for sending web requests from a terminal.
curl https://app.keptlink.com/api/v1/links \
-H "Authorization: Bearer $KEPTLINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"destination": "https://example.com/menu", "title": "Menu"}'
The reply is the new link. It includes id, short_url and version. Save the id and the version, because you need them to update the link later.
The Business plan includes 5,000 API calls per rolling 24 hours. Rolling means a moving window: the quota does not reset at midnight. Every authenticated call counts as one, including reads. Calls from a workspace and its client workspaces count together. You can watch your usage in the dashboard under Workspace settings, then Usage.
Plan your jobs with that number in mind. A job that reads, updates and then reads again uses three calls per link, not one.
When you go over, the API answers 429 Too Many Requests and adds a Retry-After header. Its value is the number of seconds to wait. This short Python sample waits and tries again.
import os
import time
import requests
API = "https://app.keptlink.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['KEPTLINK_API_KEY']}"}
def get_link(link_id):
while True:
r = requests.get(f"{API}/links/{link_id}", headers=HEADERS)
if r.status_code != 429:
r.raise_for_status()
return r.json()
time.sleep(int(r.headers.get("Retry-After", "60")))
A quota that renews over 24 hours can ask you to wait a long time. For big jobs, count your calls first and spread them out instead of relying on retries.
Errors always have the same shape: { "error": { "code": "...", "message": "..." } }. The HTTP status tells you the type:
- 400: the request is invalid.
- 401: the key is missing or revoked.
- 403: not allowed, for example a plan without the API.
- 404: not found in this workspace.
- 409: a version conflict, or a short code that is taken.
- 429: you are over the quota.

Safe updates with expected_version
Picture two background jobs. Both read the same badge link. One changes the destination. The other changes the title a second later, using the old copy it read before. Without a check, the second job could undo the first one’s work.
KeptLink prevents this with a version number. Every link has a version. An update must include expected_version, the version you last read. If the link has changed since then, the API answers 409 and changes nothing.
Here is the flow:
- Read the link and note its
version. - Send your update with that number as
expected_version. - On success, you get the updated link back.
- On a
409, read the link again, check whether your change still makes sense, and try again.
An update looks like this:
curl -X PATCH https://app.keptlink.com/api/v1/links/LINK_ID \
-H "Authorization: Bearer $KEPTLINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"expected_version": 3, "destination": "https://example.com/new-menu"}'
Archiving accepts expected_version too, but it is optional there. An archived link stops redirecting. Visitors see a “link no longer active” page.
Plan for the 409 path from the start. Jobs that never hit it in testing often hit it in production, when several workers share the same set of links.
A new destination goes through the same safety checks as one typed into the dashboard. It does not go live the moment you send it. Until the check finishes, the link shows the new address as pending_destination_url. Edits then reach people who scan in about 1 to 2 minutes, not instantly.
How the KeptLink API compares
Start with what an API manages. A static image API renders a picture and keeps nothing. A dynamic API keeps a link record you can edit and measure. Then compare plan, quota and price. This table uses each company’s public pricing pages as of 2026-10-17.
| Provider | API access and scope |
|---|---|
| KeptLink | Business: $69/month billed monthly, or $660/year billed annually ($55/month). 5,000 API calls per rolling 24 hours. |
| QuickChart | Static QR image generation. Professional is $40/month for 10,000 images a month. |
| Hovercode | Business is $39/month for 600 dynamic codes a month. The API allows 60 writes a minute. |
| Uniqode | API access starts on Pro/Core at $49/month, billed annually. |
| QR Code Generator Pro | Advanced is $18.99/month for 3,000 static API requests a month. Professional is $49.99/month for 10,000 static API requests a month. Both are billed annually. Enterprise is for a custom dynamic API. |
Read each provider’s own pages before you buy, since prices change. The QuickChart QR API documentation covers its image inputs and formats, and the Hovercode API documentation covers its dynamic API and request limits.
Ask one more question before you build on any of them: what happens to printed codes if the plan ends? The next section gives KeptLink’s answer.
What happens to your codes if you cancel
Paid codes keep working even if you cancel, subject to safety checks. Printed signs, badges and tags keep sending people to their destination. Every link in the API has a permanent field that shows this.
Safety checks still apply. Every destination, whether it comes from the API or the dashboard, goes through the same safety pipeline. A link that fails a check can be blocked.
API calls are different from redirects. To keep creating and editing links through the API, you need a plan that includes it. Without one, the API answers 403.
Here is what Business includes.
| Business allowance | Amount |
|---|---|
| Price | $69/month billed monthly, or $660/year billed annually ($55/month) |
| Links | 5,000 |
| Workspaces | 25 |
| Team seats | 10 |
| Custom domains | 10 |
| Bulk rows | 1,000 per 24 hours |
| API calls | 5,000 per rolling 24 hours |
Links and API calls are separate limits. A small set of links can still use many calls if your software reads and updates them often. Check both numbers against your plan on the pricing page.
Teams that build for clients may also want the agencies page. To learn how long printed codes last, read do QR codes expire. When you are ready to build, the API reference lists every field.
Frequently asked questions
What is the difference between a static and a dynamic QR code API?
A static API puts the web address inside the image, so it can never change. A dynamic API creates a managed short link. You can change where that link goes after printing, and you can read visit totals for it.
How do I sign in to the KeptLink API?
Send your API key in the Authorization header as a Bearer token: Authorization: Bearer kl_live_... Owners and admins create keys in the dashboard under Workspace settings, then API keys. A key is shown once and works for its own workspace only.
What happens to API-created codes if I cancel?
Paid codes keep working even if you cancel, subject to safety checks. Each link has a permanent field in the API that shows this. API calls themselves need a plan that includes the API.
What are the API limits?
Business includes 5,000 API calls per rolling 24 hours. Over the limit, the API answers 429 Too Many Requests with a Retry-After header that tells you how many seconds to wait.
How does the API stop two programs from overwriting each other?
Every update must include expected_version, the link's current version. If the link has changed since you read it, the API answers 409 and changes nothing. Read the link again and decide what to do.
Can I get SVG, PDF or PNG files from the API?
No. API v1 manages links and visit totals. It does not return image files. Each link includes qr_url, the address its QR code holds, so you can use it with the QR tool you prefer.
Which plan includes the API?
Business, at $69 a month billed monthly or $660 a year billed annually ($55 a month). It also includes 5,000 links, 25 workspaces, 10 team seats, 10 custom domains and 1,000 bulk rows per 24 hours.