Linkzly

Public REST API Reference

The Linkzly REST API lets you create, manage, and analyze all of your Linkzly resources programmatically. This reference covers authentication, rate limiting, p

11 min read

Public REST API Reference

The Linkzly REST API lets you create, manage, and analyze all of your Linkzly resources programmatically. This reference covers authentication, rate limiting, pagination, and the available public endpoints. You can also explore the full interactive API documentation from within the Linkzly console at API Keys → API Docs (/dashboard/api-keys/docs).


16.1 Authentication

The Linkzly API supports two authentication methods. Both are accepted on all public API endpoints.

Method 1 — Bearer Token (Recommended)

Authorization: Bearer lzly_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Method 2 — X-API-Key Header

X-API-Key: lzly_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Use the API key you created under API Keys in the console. The key must have the appropriate permission scope for each endpoint you call.

API Key format: lzly_[live|test]_[32-character-id]

Response Meaning
401 Unauthorized The API key is missing, malformed, expired, or revoked
403 Forbidden The API key is valid, but it does not have the required permission for this endpoint

16.2 Base URL

The Linkzly public API uses the prefix /api/use:

https://your-linkzly-instance.com/api/use

All endpoints are served over HTTPS. HTTP requests are automatically upgraded to HTTPS. The API version is v1.

Interactive Docs: The OpenAPI 3.0 specification is available at /api/docs/openapi.json. A Swagger UI is available at /api/docs. A Postman collection can be downloaded at {API_BASE_URL}/docs/postman/collection.json.


16.3 Permissions

API keys are granted granular permissions at the time of creation. Each permission follows the format resource:action.

The 11 supported permissions are:

Permission Description
links:read Read and list short links
links:write Create and update short links
links:delete Delete short links
analytics:read Read analytics data
qr:read Read and list QR codes
qr:write Create and update QR codes
qr:delete Delete QR codes
domains:read Read and list custom domains
domains:write Add and update custom domains
domains:delete Delete custom domains
webhooks:read Read and list webhooks
webhooks:write Create, update, and delete webhooks

16.4 Rate Limiting

Every response includes rate limit headers so you can track your usage in real time.

Header Description
X-RateLimit-Limit Total number of requests allowed in the current time window
X-RateLimit-Remaining Requests remaining before hitting the limit
X-RateLimit-Reset Unix timestamp (seconds) when the rate limit window resets

When you exceed the rate limit, the API returns 429 Too Many Requests along with a Retry-After header indicating how many seconds to wait before retrying.

Rate limits are tiered by scope: per IP address, per authenticated user, per organization, and per API key. API keys have a configurable rate limit (default: 1,000 requests/hour). The limit window can be set to per minute, per hour, or per day. Your per-key rate limit is configured in the API Keys console.


16.5 Idempotency

To prevent duplicate operations when retrying requests, include an idempotency key:

X-Idempotency-Key: <uuid>

Supply a unique UUID (v4 recommended) for each distinct operation. If a request with the same idempotency key is submitted more than once, the API returns the same response as the original request without performing the operation a second time.


16.6 Pagination

All list endpoints support pagination. Pass query parameters to control page size and position.

Parameter Description
page Page number (integer, starts at 1)
limit / perPage Number of results per page. Accepted values: 10, 20, 50, 100

Response Shape

Every paginated response wraps results in the following envelope:

{
  "data": [ ... ],
  "total": 243,
  "page": 1,
  "perPage": 20,
  "hasMore": true
}
Field Description
data Array of resource objects for the current page
total Total count of matching records across all pages
page The current page number
perPage Number of records per page
hasMore true if there are more pages after the current one

16.7 Public API Endpoints

The public API (/api/use) exposes four verified endpoints for third-party integrations:

Method Endpoint Description Required Permission
GET /api/use API discovery — returns API version and available endpoints None
POST /api/use/links Create a short link links:write
GET /api/use/links List all short links links:read
GET /api/use/analytics/links/:id Get analytics for a specific link analytics:read

Note: Additional endpoints for QR codes, custom domains, webhooks, and other resources are documented in the interactive console at /dashboard/api-keys/docs and in the OpenAPI spec at /api/docs/openapi.json.


GET /api/use — API Discovery

Returns the current API version, available endpoints, and API health status.

Authentication: Not required.

Returns: API metadata object including version, available routes, and status.


POST /api/use/links — Create a Short Link

Required Permission: links:write

Body Fields

Field Type Required Description
destinationUrl string Yes The full URL to redirect to. Must begin with http:// or https://. Maximum 2,048 characters.
title string No Internal label for the link. Maximum 255 characters.
customSlug string No Custom short code (e.g., summer-sale). Alphanumeric, hyphens, and underscores. Auto-generated if omitted.
expiresAt string No ISO 8601 datetime after which the link stops redirecting. Must be a future date.
tags string[] No Array of tag strings for filtering and categorization.
metadata object No Arbitrary key-value metadata to attach to the link.

Returns: The full link object including id, shortUrl, shortCode, destinationUrl, status, clicks, createdAt, and updatedAt.

Example Request

curl -X POST https://your-linkzly-instance.com/api/use/links \
  -H "Authorization: Bearer lzly_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "destinationUrl": "https://example.com/landing-page",
    "title": "Summer Campaign",
    "customSlug": "summer-sale",
    "tags": ["marketing", "summer"]
  }'

Example Response

{
  "id": "lnk_abc123",
  "shortUrl": "https://linkz.ly/summer-sale",
  "shortCode": "summer-sale",
  "destinationUrl": "https://example.com/landing-page",
  "title": "Summer Campaign",
  "status": "active",
  "clicks": 0,
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-15T10:30:00Z"
}

GET /api/use/links — List Short Links

Required Permission: links:read

Query Parameters

Parameter Type Description
page integer Page number (starts at 1)
limit integer Results per page (10, 20, 50, 100)
search string Full-text search across title, short code, and destination URL
status string Filter by status: active, inactive, or expired
tag string Filter by tag name
sortBy string Sort field: createdAt or clicks
sortOrder string Sort direction: asc or desc

Returns: A paginated array of link objects.


GET /api/use/analytics/links/:id — Link Analytics

Required Permission: analytics:read

Path Parameters

Parameter Description
id The ID of the short link to retrieve analytics for

Query Parameters

Parameter Type Description
startDate string Start of the date range (ISO 8601)
endDate string End of the date range (ISO 8601)
interval string Time bucket size: hour, day, or week

Response Fields

The analytics response includes summary metrics and breakdowns:

Field Description
totalClicks Total click events in the selected period
uniqueVisitors Count of distinct visitors
botDetection Bot traffic count and percentage
responseTime Average response time in milliseconds
bounceRate Percentage of single-interaction visits
geography[] Click breakdown by country and region
devices[] Breakdown by device type (Mobile, Desktop, Tablet)
browsers[] Browser breakdown with click counts and percentages
referrers[] Top referring domains with click counts
timeSeries[] Time-series click data at the requested interval
utmSources[] UTM source values with click counts
utmMediums[] UTM medium values with click counts
utmCampaigns[] UTM campaign values with click counts

16.8 Additional Endpoints (Console API)

The Linkzly console uses a broader internal API with additional resource endpoints. These are documented in the interactive API reference at /dashboard/api-keys/docs and in the OpenAPI 3.0 spec at /api/docs/openapi.json.

The full console API covers the following resources with their associated permissions:

Resource Available Permissions
Short Links links:read, links:write, links:delete
QR Codes qr:read, qr:write, qr:delete
Custom Domains domains:read, domains:write, domains:delete
Analytics analytics:read
Webhooks webhooks:read, webhooks:write

For endpoint details, request parameters, response shapes, and code examples in JavaScript, Python, Go, PHP, cURL, and Ruby, open the in-console documentation via API Keys → API Docs in the Linkzly dashboard.


16.9 Webhooks

Webhooks allow Linkzly to push real-time event notifications to your server. Configure and manage webhooks from the Webhooks page in the console (/dashboard/webhooks), or use the Webhooks API endpoints documented in the console API reference.

Webhooks are managed through your API key with the webhooks:read and webhooks:write permissions.

Webhook Payload Signing

Every webhook delivery is signed with HMAC-SHA256 to allow your server to verify the payload authenticity.

Header Value
X-Webhook-Signature sha256=<signature>

The signature is computed over the string {webhook_id}.{timestamp}.{body}. Verify it on your server by recomputing the HMAC-SHA256 with your webhook secret and comparing the result to the header value.


16.10 Error Responses

HTTP Status Codes

Code Meaning
200 OK — Request was successful
201 Created — A new resource was created
204 No Content — Delete was successful; no response body
400 Bad Request — Validation error; check the details array in the response
401 Unauthorized — API key is missing, invalid, expired, or revoked
403 Forbidden — API key is valid but does not have the required permission
404 Not Found — The resource does not exist, or it belongs to a different organization
409 Conflict — A resource with the same identifier already exists (e.g., duplicate short code or domain)
422 Unprocessable Entity — The request body is well-formed but semantically invalid
429 Too Many Requests — Rate limit exceeded; check the Retry-After header
500 Internal Server Error — Contact support and include the request path and timestamp from the response

Error Response Body Format

All error responses use the same JSON structure:

{
  "error": "ErrorType",
  "message": "Human-readable message",
  "statusCode": 400,
  "timestamp": "2024-01-15T10:30:00Z",
  "path": "/api/use/links",
  "details": []
}
Field Description
error Machine-readable error type (e.g., ValidationError, NotFound, RateLimitExceeded)
message A short, human-readable summary of what went wrong
statusCode The HTTP status code for this error
timestamp ISO 8601 timestamp of when the error occurred
path The request path that produced the error
details Array of additional error detail objects (present for validation errors)

16.11 SDK Libraries

Official SDKs are available via standard package managers:

Language Install Command
JavaScript / Node.js npm install @linkzly/sdk
Python pip install linkzly
Go go get github.com/linkzly/linkzly-go
PHP composer require linkzly/linkzly-php
Ruby gem install linkzly

Code examples for all languages are available in the in-console documentation (API Keys → API Docs) and in the GitHub examples repository at https://github.com/linkzly/examples.


16.12 API Key Tester

Use the interactive Test API Key tool at /dashboard/api-keys/test to:

  • Validate your API key format and active status
  • View the rate limits and permissions assigned to a key
  • See which endpoints the key is authorized to access
  • Test key authentication in real time before writing integration code

Was this helpful?

Help us improve our documentation