API Reference
All endpoints are available at https://linksnap.forjio.com/api/v1. Authenticate with a Bearer token (JWT) or API key via the Authorization header.
Authentication
/auth/signupRegister a new account.
Request body
{
"email": "user@example.com",
"password": "securePassword123",
"name": "Jane Doe"
}Response
{
"data": {
"accessToken": "eyJhbG...",
"refreshToken": "eyJhbG...",
"user": { "id": "usr_...", "email": "user@example.com", "name": "Jane Doe" }
}
}/auth/loginAuthenticate with email and password.
Request body
{
"email": "user@example.com",
"password": "securePassword123"
}Response
{
"data": {
"accessToken": "eyJhbG...",
"refreshToken": "eyJhbG...",
"user": { "id": "usr_...", "email": "user@example.com" }
}
}/auth/meAuth requiredGet current user profile and usage stats.
Response
{
"data": {
"id": "usr_...",
"email": "user@example.com",
"name": "Jane Doe",
"plan": "PRO",
"linksUsed": 42,
"linksLimit": 5000
}
}Links
/linksAuth requiredCreate a new short link.
Request body
{
"url": "https://example.com/my-long-page",
"slug": "my-link", // optional
"expiresAt": "2026-12-31", // optional
"maxClicks": 1000, // optional
"tags": ["marketing"] // optional
}Response
{
"data": {
"id": "lnk_...",
"url": "https://example.com/my-long-page",
"slug": "my-link",
"shortUrl": "https://lsnp.io/my-link",
"createdAt": "2026-03-23T10:00:00Z"
}
}/linksAuth requiredList links (paginated). Supports ?q=search&tag=marketing&sort=clicks&order=desc&cursor=...&limit=20.
Response
{
"data": [
{ "id": "lnk_...", "url": "...", "slug": "my-link", "clicks": 142 }
],
"meta": { "cursor": "next_cursor_value", "hasMore": true }
}/links/:idAuth requiredGet a single link by ID or slug.
Response
{
"data": {
"id": "lnk_...",
"url": "https://example.com",
"slug": "my-link",
"clicks": 142,
"tags": ["marketing"],
"expiresAt": null,
"maxClicks": null,
"status": "active",
"createdAt": "2026-03-23T10:00:00Z"
}
}/links/:idAuth requiredUpdate a link's URL, slug, expiry, max clicks, tags, or status.
Request body
{
"url": "https://example.com/updated",
"slug": "new-slug",
"tags": ["updated"],
"status": "archived"
}Response
{
"data": {
"id": "lnk_...",
"url": "https://example.com/updated",
"slug": "new-slug",
"status": "archived"
}
}/links/:idAuth requiredPermanently delete a link.
Response
{
"data": { "success": true }
}Analytics
/links/:id/statsAuth requiredGet click analytics for a link. Supports ?from=2026-01-01&to=2026-03-31 date range filtering.
Response
{
"data": {
"totalClicks": 142,
"uniqueClicks": 98,
"countries": { "US": 45, "ID": 32, "GB": 21 },
"devices": { "mobile": 78, "desktop": 52, "tablet": 12 },
"browsers": { "Chrome": 65, "Safari": 42, "Firefox": 20 },
"referrers": { "twitter.com": 30, "direct": 62 },
"timeSeries": [
{ "date": "2026-03-22", "clicks": 12 },
{ "date": "2026-03-23", "clicks": 8 }
]
}
}QR Codes
/qr-codesAuth requiredCreate a new QR code with optional style customization.
Request body
{
"url": "https://example.com",
"title": "My QR Code", // optional
"linkId": "lnk_...", // optional — link to an existing short link
"styleConfig": { // optional
"pattern": "square", // square | dots | rounded | classy
"corners": "square", // square | rounded | dots
"foregroundColor": "#000000",
"backgroundColor": "#ffffff",
"frame": "none" // none | border | rounded-border | badge
}
}Response
{
"data": {
"id": "qr_...",
"url": "https://example.com",
"slug": "qr-a1b2c3d4",
"scanUrl": "https://lsnp.io/q/qr-a1b2c3d4",
"hasWatermark": true,
"totalScans": 0,
"createdAt": "2026-04-02T10:00:00Z"
}
}/qr-codesAuth requiredList QR codes (paginated). Supports ?q=search&cursor=...&limit=20.
Response
{
"data": [
{ "id": "qr_...", "url": "...", "slug": "qr-a1b2c3d4", "totalScans": 42 }
],
"meta": { "cursor": "next_cursor_value", "hasMore": true }
}/qr-codes/:idAuth requiredGet a single QR code by ID.
Response
{
"data": {
"id": "qr_...",
"url": "https://example.com",
"slug": "qr-a1b2c3d4",
"scanUrl": "https://lsnp.io/q/qr-a1b2c3d4",
"styleConfig": { ... },
"totalScans": 42,
"hasWatermark": false
}
}/qr-codes/:id/download?format=pngAuth requiredDownload QR code image. Supported formats: png, svg (svg requires Pro or Business plan).
Response
Binary image data (Content-Type: image/png or image/svg+xml)
/qr-codes/:id/statsAuth requiredGet scan analytics for a QR code. Supports ?from=2026-01-01&to=2026-03-31 date range.
Response
{
"data": {
"totalScans": 142,
"scansByDay": [{ "date": "2026-04-01", "count": 12 }],
"scansByCountry": [{ "country": "US", "count": 45 }],
"scansByDevice": [{ "device": "mobile", "count": 78 }],
"scansByBrowser": [{ "browser": "Chrome", "count": 65 }]
}
}/qr-codes/:idAuth requiredPermanently delete a QR code and all scan data.
Response
{
"data": { "success": true }
}Billing
/billing/plansList available plans and pricing. No authentication required.
Response
{
"data": [
{ "key": "FREE", "name": "Free", "price": 0, "linksLimit": 25 },
{ "key": "PRO", "name": "Pro", "price": 49000, "linksLimit": 5000 },
{ "key": "BUSINESS", "name": "Business", "price": 149000, "linksLimit": 50000 }
]
}/billing/checkoutAuth requiredCreate a payment checkout session for upgrading to a paid plan.
Request body
{
"plan": "PRO"
}Response
{
"data": {
"snapToken": "...",
"redirectUrl": "https://app.midtrans.com/snap/..."
}
}