How to use ForeverLink
ForeverLink is a numbered inventory of links you can reprint-proof. You generate IDs (1…N), print the public ForeverLink URL on a QR, NFC tag or sticker, and change the HTTPS destination later — from the panel, CSV, the Scale API, or the support chat.
Public URL of every ID:
https://foreverlink.app/r/{your-org}/{number}
Example: https://foreverlink.app/r/acme/42
The public URL name never changes (so printed pieces keep working). Only the destination changes.
---
1. Create your account
- Open Register or pick a plan on Pricing.
- Choose Starter ($19/mo, 500 IDs), Growth ($49/mo, 5,000) or Scale ($99/mo, 25,000 + API). White Label is a $999 one-time license.
- Pick an organization name. The public URL name becomes part of every printed URL. You cannot rename it later.
- Confirm email / password. 2FA (Google Authenticator / Authy) is optional — enable it later in Settings.
- Complete Paddle checkout (card required). You get a 15-day trial. Cancel before it ends and you are not charged.
- Until billing is
trialingoractive, public QR codes will not redirect.
---
2. First 15 minutes
- Sign in at
/login→ you land on Inventory. - Open Generate range and create IDs
1to100(or whatever you will print). - Open Assign range and set a destination for
1–20, plus a label likeshop-front. - Open ID
#1and download the SVG QR. That QR encodes the ForeverLink URL, not the final website. - Scan it. You should land on the destination. If you see “not configured”, the ID has no
httpsdestination or it is inactive. - Change the destination on
#1and scan again — same QR, new page.
---
3. Inventory
The inventory is the list of every stock ID in the active organization.
- Search by number, label, destination or notes.
- Filter: all / never clicked / no destination / active / inactive.
- Sort by number or clicks.
- Each row is one public URL:
/r/{org}/{number}.
Click a row to edit that ID.
---
4. New ID
New ID creates a single stock number.
- Leave the number empty to use the next free ID, or type a specific number that does not exist yet.
- Optional: destination (
https://…), label, notes, status (active / inactive). - Save. The ID counts against your plan
max_linkslimit.
Use this for a one-off sticker. Use Generate range for a print run.
---
5. Generate range
Creates empty IDs in an inclusive range (example: 1 to 1000).
- Existing numbers are skipped (safe to re-run).
- New IDs start active with no destination.
- The range cannot push you past the plan limit.
Do this before you send files to the printer.
---
6. Assign range
Writes the same destination, label and status across a from–to range that already exists.
Typical uses:
- Point IDs
1–50at this month’s menu. - Relabel a client batch when they leave (
old-client→ new URL). - Turn a campaign off: set status
inactiveon that range.
Destinations must be http:// or https:// with a host, max 2048 characters.
---
7. Edit one link
Open the ID from inventory.
You can change:
| Field | Meaning |
|---|---|
| Destination | Where the scan goes. Empty = public page says “not configured”. |
| Label | Batch / client / location. Used to search and bulk-deactivate. |
| Notes | Internal only. Never shown to the person who scans. |
| Status | active redirects. inactive does not. |
The page also shows:
- Total clicks and last click
- Last 14 days
- Change history (who, when, before → after)
Download the production QR (SVG) here. Always print this QR, never a QR of the final Google / menu URL.
---
8. Import and export CSV
Export downloads the current inventory (optional label filter).
Import upserts rows. Typical columns: number, target_url, label, notes, status.
- Invalid URLs are rejected.
- Import writes a revision on each change (
source = import). - Stay under
max_links.
Use Excel or your print ERP, then import.
---
9. Clicks and history
Every successful public redirect increments click_count and a daily counter.
Inventory alerts:
- Active IDs with no destination (printed but dead)
- IDs that were never scanned
History records destination, label, status and notes changes, with source: manual, import, range, API or chat.
---
10. Team
Roles:
| Role | Can |
|---|---|
| Owner | Everything, including billing and PIN / API keys |
| Admin | Settings, team, PIN, API keys, inventory |
| Operator | Assign destinations, generate/assign ranges, import |
Add a member under Team with a temporary password (min. 12 characters). They must sign in and can enable 2FA.
If you belong to more than one organization, switch it in Settings.
---
11. Settings
- Rename the organization display name (not the public URL name).
- Enable 2FA.
- Set the Support PIN (6–8 digits). WhatsApp / Telegram / web chat will ask for the public URL name or email + this PIN once, then they can only see this org.
- Rotate the PIN or “Unlink all chat sessions” to kick every linked phone.
- API keys (Scale and White Label only): create, copy once, revoke.
---
12. Billing
Open Billing.
- Trial: 15 days, card on file.
- Statuses:
pending_payment,trialing,active,past_due,suspended,canceled,whitelabel_setup. - Public redirects work while
trialing,active,past_dueorwhitelabel_setup. - Suspended / unpaid orgs show a blocked page instead of the destination.
- Customer Portal (Paddle) is linked from Billing.
- The chat bot cannot change your card.
---
13. Support tickets
In the app: Support. Subject + message.
From chat: after the PIN, ask the bot to open a ticket. Platform staff reply in the admin console.
---
14. Chat (WhatsApp, Telegram, web)
- Owner/admin sets the Support PIN in Settings.
- Message the ForeverLink bot.
- Give your public URL name (or the email of a member) and the PIN.
- Ask things like “point #12 to https://example.com/menu” or “why doesn’t QR 4 redirect?”.
Never send your panel password or 2FA codes in chat.
---
15. API (Scale and White Label)
REST at {APP_URL}/api/v1. Create a key in Settings. It is shown once.
Header:
Authorization: Bearer fl_live_…
or `X-API-Key: fl_live_…`
The key is bound to **your** organization. There is no `organization_id` you can switch.
### Scopes
| Scope | What it allows |
| --- | --- |
| `account:read` | `GET /me`, `GET /stats` |
| `links:read` | `GET /links`, `GET /links/{number}` |
| `links:write` | create / update / ranges |
| `tickets:write` | `GET/POST /tickets` |
### Endpoints
**`GET /api/v1/me`** — public URL name, plan, limits, billing status, usage.
**`GET /api/v1/links`** — query: `q`, `label`, `status`, `filter=never_clicked\|no_destination`, `page`, `per_page`, `sort=number\|clicks`.
**`GET /api/v1/links/{number}`** — detail, 14-day clicks, revisions.
**`POST /api/v1/links`**
{
"number": 42,
"target_url": "https://example.com",
"label": "shop",
"notes": "",
"status": "active"
}
`number` is optional (next free ID).
**`PATCH /api/v1/links/{number}`** — any subset of `target_url`, `label`, `notes`, `status`.
**`POST /api/v1/links/assign-range`**
{ "from": 1, "to": 50, "label": "april", "target_url": "https://example.com/promo", "status": "active" }
**`POST /api/v1/links/generate-range`**
{ "from": 1, "to": 500 }
**`GET /api/v1/stats`** — totals and top links.
**`GET /api/v1/tickets`** · **`POST /api/v1/tickets`**
{ "subject": "QR 12 is dead", "body": "Scans show not configured", "priority": "normal" }
### Errors
{ "error": { "code": "UNAUTHORIZED", "message": "Invalid or missing API key." } }
| HTTP | Meaning |
| --- | --- |
| 401 | Missing or invalid key |
| 402 | Writes while billing is not active |
| 403 | Wrong plan, suspended org, or missing scope |
| 404 | Unknown link or route |
| 429 | Rate limit (default 60 requests / minute) |
Starter and Growth keys are rejected with `403`.
---
## 16. Why a QR does not redirect
Check in order:
1. The printed URL is `https://foreverlink.app/r/{your-org}/{number}` — URL name and number match the inventory.
2. The ID exists.
3. Status is `active`.
4. Destination is a valid `http(s)` URL.
5. Billing is `trialing` / `active` / `past_due` (not `suspended` or `pending_payment`).
---
## 17. White Label
$999 one-time software license. After payment, fill the configuration form (domain + optional self-host notes). Run it on your server, or add hosted SaaS for +$50/mo. Includes API access, documentation, and product support. Not a paid installation project.
Inventory above 25,000 IDs on Scale is sold as **5,000-ID packs** at $19/month. Add them at checkout or in Billing.
### Custom domain (Scale and White Label)
Print QR / NFC on **your** host (`https://links.yourbrand.com/r/42`) instead of `foreverlink.app`.
1. In **Settings → Custom domain** save a **subdomain** (`links.yourbrand.com`). Do not use the bare domain.
2. In your DNS panel create **one CNAME**:
- **Type:** CNAME
- **Name / host:** `links` (most panels) or `links.yourbrand.com` if they ask for the FQDN
- **Target / points to:** `foreverlink.app`
- **Cloudflare proxy:** Proxied (orange cloud) — this is how HTTPS works on your hostname
- **TTL:** Auto
3. Wait 1–15 minutes. Click **Verify DNS**.
4. Download QRs again. They now encode `https://links.yourbrand.com/r/{number}`.
Do **not** create an A record to an IP. Do **not** CNAME the apex (`yourbrand.com`) unless your DNS has ALIAS/ANAME.
If Verify fails and you use Cloudflare, the CNAME may be hidden (flattening). Add the **TXT** shown under “Verify still fails?” (`_foreverlink.links.yourbrand.com` = the token). Old `https://foreverlink.app/r/{org}/{number}` URLs keep working.
---
Need a human? [Contact](/contact) or open a ticket in the app.