REST API for short links, branded QR codes, bio pages, and link packages. Business package
All endpoints live under:
https://qrsa.net/app/api/v1
Authenticate every request with your API key in the X-API-Key header (find it in
Settings → API Access). Programmatic API access is exclusive to the Business package
and includes 10,000 API requests per 30-day usage period.
curl -H "X-API-Key: YOUR_API_KEY" https://qrsa.net/app/api/v1/links/
Every response is JSON. Success: { "success": true, "data": { … } }.
Error: { "success": false, "error": "message", "code": "CODE" }.
Missing/invalid key returns 401. Rate limit: 60 requests/min per key.
List your links (paginated). Query: ?page=, ?search=,
?tag= (filter by a single tag). Each link object includes a tags array,
qr_code_url (PNG), short_url, and click_count.
Create a short link + QR. Body:
| Field | Required | Notes |
|---|---|---|
original_url | yes | Destination URL |
custom_slug | no | Custom short slug (must be unique) |
title | no | Label |
expires_at | no | ISO 8601; must be in the future; capped by plan |
template_id | no | Apply a saved QR template (design + logo) |
qr_color | no | Hex, e.g. #6c63ff |
qr_style | no | classic · rounded · dots · bars |
qr_frame | no | Branded frame: none, scan_btm, scan_top, round_btm, arrow, ticket, coffee, … (append _ar for Arabic text) |
logo_placement | no | center · background |
tags | no | Array of labels (Pro). Lowercased & de-duped; max 15 × 40 chars. Ignored on plans without tagging. |
curl -X POST https://qrsa.net/app/api/v1/links/ \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"original_url":"https://example.com","template_id":"<TEMPLATE_ID>"}'
Update original_url, custom_slug, title, expires_at, is_active, tags, QR design. (Sending tags replaces the full set.) The QR keeps working — it encodes a permanent ID, not the slug.
Click analytics for a link (totals, recent, device split).
Download the QR as a PNG (binary).
Delete several links at once. Body: { "slugs": ["abc123", "def456"] }.
Upload a center/background logo for the link's QR (multipart/form-data, field logo).
Replace the QR image with your own styled PNG (multipart/form-data, field image).
List your saved QR templates. Use a template's id as template_id when creating a link to apply its color, style, frame, and logo.
Create a template. Accepts name, qr_color, qr_style, qr_frame,
logo_placement, an optional image (multipart), and tags.
A template's tags are inherited by any link created from it.
Tag links to group and filter them. Tags are set via tags on
link create/update, lowercased and de-duped server-side. Links created through this API are
automatically tagged api, and links from a template inherit the template's tags.
List every distinct tag across your links with a link count. Returns
{ "tags": [ { "tag": "marketing", "count": 4 }, … ] } (empty on plans without tagging).
# create a tagged link
curl -X POST https://qrsa.net/app/api/v1/links/ \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"original_url":"https://example.com","tags":["marketing","q2"]}'
# list links in a tag group
curl -H "X-API-Key: YOUR_API_KEY" "https://qrsa.net/app/api/v1/links/?tag=marketing"
Build shareable link-in-bio pages at qrsa.net/@handle. Bio pages use the shared
link-slot balance and remain subject to the package's Bio-page limit. The Free package does not include Bio pages.
List your pages. Each includes public_url, page_qr_url, and avatar_url.
Create a page. Body:
| Field | Notes |
|---|---|
handle | Unique @handle (a–z, 0–9, _ , -). Auto-suggested from the title if omitted. |
page_type | business or social |
design_id | Design key, e.g. biz-minimal |
title, bio | Display name + tagline |
email, phone, whatsapp | Contact details (business) |
socials | Array: [{"platform":"instagram","url":"…","label":"…"}] |
qr_template | QR template id to style the page QR |
contact_qr_kind | none · phone · whatsapp |
links_layout | list or grid |
is_active | Publish/unpublish |
Check if an @handle is free before creating.
Upload the page avatar (multipart/form-data, field avatar).
Account-wide totals (links, clicks, plan, usage).
Your profile, plan, limits, and entitlements.
Update profile fields: name, company_name, phone.
Change password. Body: { "current_password": "…", "new_password": "…" }.
Rotate your API key (no body). The old key stops working immediately.
Current package benefits, shared slot balance, usage, owned packages, and available packages.
Get a signed annual-plan quote. Quantity is 1–5 years (upgrades use the remaining term only). Renewals and lower plans are paid now and start at the current expiry. Set keep_addons=false to omit add-on renewal. For extra links use ?kind=addon&slots=10 (10, 50 or 100). Add-ons are prorated to the current expiry and do not change plan features.
Body: { "quote_token": "TOKEN_FROM_QUOTE", "selection": { "links": [], "bios": [] } }. Quotes expire after 15 minutes. When requires_selection is true, submit the owned IDs to retain from selection_options. Unselected links are paused at activation, never deleted. The response returns requires_payment and a hosted-checkout redirect_url. Prices are calculated by the server.
List invoices, or download one as a PDF.
Public plan catalog (no API key) — the same source the pricing page uses.