Skip to main content

Links

Links are the core resource. A link has a type (website, vCard, WiFi, etc.), a data payload describing its content, optional configuration (custom slug, scheduling, scan limits, password), and an auto-generated QR code.

All endpoints below require an API key with the scope noted on each one. Scan analytics for a link are covered on the Analytics page.


GET /links

Scope: links.read

Query parameters

ParamTypeDefaultDescription
pagenumber1Page number (1-based).
sizenumber20Items per page (max 1000).
searchstringCase-insensitive match on link name.
folderstringFilter by folder id.
qr_typestringComma-separated list of types, e.g. website,vcard.
statusstringComma-separated list of statuses.
only_favoritesbooleanWhen set, returns only favorited links.
sort_bystringOne of most_recent, name, last_modified, most_visited.
menustringFilter by the menu column (used internally by the Cafe feature).

Example

curl "https://api.prolinksqr.com/links?page=1&size=20&sort_by=most_recent" \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Response 200

{
"data": [
{
"dynamic_link_id": "summer-sale",
"full_dynamic_url": "https://qr-lb.co/summer-sale",
"name": "Summer Sale",
"type": "website",
"meta_data": { "url": "https://example.com/sale" },
"qr_options": {
"data": "https://qr-lb.co/summer-sale",
"width": 300,
"height": 300
},
"folder_id": null,
"created_at": "Jun 24, 2026",
"updated_at": "Jun 24, 2026"
}
],
"meta": { "currentPage": 1, "totalPages": 4 }
}
note

The examples above are trimmed for readability. List/Get responses actually return every column on the link, including scheduling, scan-limit, and password-protection fields. If password protection is enabled, the returned password field is the hashed password, not the plaintext value.


GET /minimal-links

Scope: links.read

A lighter-weight version of List links for populating pickers/dropdowns — returns only each link's name and dynamic_link_id. Supports the same page, size, search, folder, qr_type, status, only_favorites, and sort_by query parameters.

curl https://api.prolinksqr.com/minimal-links \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Response 200

{
"data": [{ "name": "Summer Sale", "dynamic_link_id": "summer-sale" }],
"meta": { "currentPage": 1, "totalPages": 1 }
}

GET /links/:id

Scope: links.read

:id is the link's dynamic_link_id (its slug).

curl https://api.prolinksqr.com/links/summer-sale \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Response 200

{
"data": {
"dynamic_link_id": "summer-sale",
"full_dynamic_url": "https://qr-lb.co/summer-sale",
"name": "Summer Sale",
"type": "website",
"meta_data": { "url": "https://example.com/sale" },
"qr_options": { "data": "https://qr-lb.co/summer-sale" }
}
}

POST /links

Scope: links.create

Body

FieldTypeRequiredDescription
namestringyesDisplay name of the link.
typestringyesOne of the link types below.
dataobjectyesType-specific payload — see link types.
linkConfigurationsobjectnoSlug, scheduling, scan limit, and password — see configuration.

Example

curl -X POST https://api.prolinksqr.com/links \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Summer Sale",
"type": "website",
"data": { "url": "https://example.com/sale" },
"linkConfigurations": {
"urlActive": true,
"customUrl": "summer-sale"
}
}'

Response 200

The new link's identifier (its dynamic_link_id) is returned:

{ "id": "summer-sale" }

The shape of data depends on type. Supported types and their fields:

website

FieldTypeRequired
urlstring (URL)yes

email

FieldTypeRequired
emailstring (email)yes
subjectstringno
bodystringno

sms

FieldTypeRequired
phonestringyes
messagestringno

vcard

FieldTypeRequired
firstName, lastNamestringyes
emailstring (email)yes
contact, phone, fax, website, company, department, street, state, city, zip, countrystringno

wifi

FieldTypeRequiredNotes
ssidstringyesNetwork name.
encryptionstringyesOne of WPA, WEP, nopass.
passwordstringno
hiddenbooleanno

location

FieldTypeRequired
latitudenumberyes
longitudenumberyes

event

FieldTypeRequiredNotes
description, locationstringyes
startDateTimestringyesParseable date/time.
timezonestringyesMax 64 chars.
endDateTimestringnoMust be ≥ startDateTime.
organizerName, registrationUrlstringnoregistrationUrl must be a valid URL.
eventTitlestringnoMax 100 chars.
imageobjectno{ "fileId": "..." } — cover image for the event.

image / pdf

FieldTypeRequiredNotes
filesarrayyesAt least one { "fileId": "..." }. Upload files first to obtain a fileId.
FieldTypeRequiredNotes
filesarrayyes1–20 items of { "fileId": "..." }. Upload files first to obtain a fileId.

landing

FieldTypeRequiredNotes
landingHTMLstringyesHTML for the landing page.

product

FieldTypeRequiredNotes
productName, productDescription, currencystringyes
subTotal, tax, totalNetnumberyesMust be ≥ 0.
discountobjectno{ "type": "amount"|"percent", "value": number }.
imagesobjectno{ "files": [{ "fileId": "..." }] }.
FieldTypeRequiredNotes
titlestringyes
designobjectyes{ "backgroundColor", "linkBackgroundColor", "textColor" }.
descriptionstringno
logoanyno
isRoundbooleanno
linksarraynoItems { "type": "custom"|"social", "value": "<url>", "title"?, "icon"? }. title is required for custom; icon for social.

multi-pdf

FieldTypeRequiredNotes
pageTitlestringyesMax 100 chars.
pdfsarrayyes1–10 items of { "label": "...", "fileId": "..." }.

smart-url

FieldTypeRequiredNotes
defaultUrlstring (URL)yesFallback destination.
rulesarraynoUp to 10 routing rules (see below).

Each rule:

FieldTypeRequiredNotes
conditionTypestringyesOne of location, time, date, device.
operatorstringyeslocation/device: is, is_not. time: between, not_between. date: after, before, between, not_between.
urlstring (URL)yesDestination when the rule matches.
countriesarraycond.Required for location.
timezonestringcond.Required for time and date.
timeFrom, timeTostringcond.Required for time.
dateFrom, dateTostringcond.Required for date depending on operator.
devicesarraycond.Required for device. Values: ios, android, windows, macos, linux, mobile, desktop.
FieldTypeRequired
namestringno

The optional linkConfigurations object controls slug, scheduling, scan limits, and password protection. Each feature has an *Active toggle; the related fields are only required when its toggle is true.

FieldTypeRequired whenNotes
folder_idstringPlace the link in a folder.
urlActivebooleanEnable a custom slug.
customUrlstringurlActive: trueLetters, numbers, -, _ only. Max 64 chars.
scheduleActivebooleanEnable active window.
startDate, endDatedatescheduleActive: trueendDate must be after startDate.
scheduleTimezonestringscheduleActive: trueMax 64 chars.
scanLimitActivebooleanEnable a scan cap.
scanLimitnumberscanLimitActive: trueMax scans before the link stops resolving.
passwordProtectedActivebooleanRequire a password to open.
passwordstringpasswordProtectedActive: trueMax 32 chars.

PUT /links/:id

Scope: links.update

A full update. The body uses the same shape as Create a link (name, type, data, linkConfigurations).

curl -X PUT https://api.prolinksqr.com/links/summer-sale \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Summer Sale (extended)",
"type": "website",
"data": { "url": "https://example.com/sale-extended" }
}'

Response 200

Returns the full updated link object (same shape as Get a link):

{
"data": {
"dynamic_link_id": "summer-sale",
"full_dynamic_url": "https://qr-lb.co/summer-sale",
"name": "Summer Sale (extended)",
"type": "website",
"meta_data": { "url": "https://example.com/sale-extended" },
"qr_options": { "data": "https://qr-lb.co/summer-sale" }
}
}

Patch QR options

PATCH /links/:id

Scope: links.update

Updates only the QR code styling for a link, leaving its content untouched. Send the QR options under a qrCode key.

FieldTypeRequiredNotes
qrCodeobjectyesQR options object — see Templates.
curl -X PATCH https://api.prolinksqr.com/links/summer-sale \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"qrCode": {
"dotsOptions": { "color": "#1E88D4", "type": "rounded" },
"backgroundOptions": { "color": "#ffffff" }
}
}'

Response 200

{
"data": {
"dynamic_link_id": "summer-sale",
"qr_options": { "dotsOptions": { "color": "#1E88D4" } }
}
}

DELETE /links/:id
POST /links/:id/archive

Scope: links.delete

Despite the "archive" naming, this permanently deletes the link — its row, its uploaded media, and its access logs are all removed and cannot be recovered. Both routes do the same thing.

curl -X DELETE https://api.prolinksqr.com/links/summer-sale \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Response 200

{ "message": "Link archived" }

Pause and resume

POST /links/:id/pause
POST /links/:id/resume

Scopes: links.pause (pause), links.resume (resume)

A paused link stops resolving until resumed.

curl -X POST https://api.prolinksqr.com/links/summer-sale/pause \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Response 200

{ "message": "Link paused" }

Favorite and unfavorite

POST /links/:id/favorite
DELETE /links/:id/favorite

Scope: links.update

Mark a link as a favorite (POST) or remove it from favorites (DELETE). Favorited links can be filtered in List links with only_favorites.

curl -X POST https://api.prolinksqr.com/links/summer-sale/favorite \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Response 200

{ "message": "Success" }

POST /links/:id/duplicate

Scope: links.create

Creates a copy of an existing link. Optionally give the copy a new name.

FieldTypeRequiredNotes
namestringnoMax 255 chars.
curl -X POST https://api.prolinksqr.com/links/summer-sale/duplicate \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Summer Sale (copy)" }'

Response 200

{ "message": "Link duplicated" }

POST /links/:id/save-template

Scope: templates.create

Saves the link's QR styling as a reusable template.

FieldTypeRequiredNotes
namestringnoMax 255 chars.
curl -X POST https://api.prolinksqr.com/links/summer-sale/save-template \
-H "Authorization: Basic key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Brand QR style" }'

Response 200

{ "message": "Template Saved" }