Documentation
Learn how to use opn.onl to shorten links, track analytics, and integrate with your applications.
Getting Started
opn.onl provides a simple REST API for creating and managing short links. You can use it directly via HTTP requests or integrate it into your applications.
# Create a short link (no authentication required)
curl -X POST https://l.opn.onl/links \
-H "Content-Type: application/json" \
-d '{"original_url": "https://example.com/very-long-url"}'API Reference
Authentication
Most endpoints require authentication via Bearer token. Get your token by logging in:
POST https://l.opn.onl/auth/login
{"email": "[email protected]", "password": "yourpassword"}Include the token in subsequent requests:
Authorization: Bearer your-jwt-tokenFor scripts and the MCP server, create a long-lived API key in Settings → API Keys and send it the same way (it never expires until you revoke it):
Authorization: Bearer opn_xxxxxxxxxxxx/linksCreate a new short link
Request Body
{
"original_url": "https://example.com/page", // Required
"custom_alias": "my-link", // Optional (5-50 chars)
"title": "My Link Title", // Optional, private
"password": "secret123", // Optional
"expires_at": "2025-12-31T23:59:59Z", // Optional
"notes": "Internal notes" // Optional
}Response
{
"id": 123,
"code": "abc123",
"short_url": "https://l.opn.onl/abc123",
"original_url": "https://example.com/page",
"click_count": 0,
"created_at": "2025-01-01T00:00:00Z"
}/linksList your links (requires auth)
Query Parameters
search- Search by URL or codefolder_id- Filter by foldertag_id- Filter by taglimit- Number of results (default: 50)offset- Pagination offset
Other Endpoints
/links/{id}Get link details/links/{id}Update a link/links/{id}Delete a link/links/{id}/statsGet link analytics/links/{id}/qrGenerate QR code — optional ?color=, logo=true, format=svg/links/{id}/rulesList / replace (PUT) smart-routing rules/auth/bioUpdate your link-in-bio settings/api/bio/{username}Public bio profile (when enabled)/auth/api-keysList / create (POST) keys; DELETE /auth/api-keys/{id} to revoke/links/exportExport links as CSVFull interactive API documentation is available at https://l.opn.onl/swagger-ui/
Self-Hosting Guide
opn.onl is fully open-source and can be self-hosted on your own infrastructure. The stack consists of a Rust backend and React frontend.
Requirements
- Docker and Docker Compose
- PostgreSQL database
- Redis (optional, for caching)
- SMTP server (for email verification)
Quick Start with Docker
# Clone the repository
git clone https://github.com/ysalitrynskyi/opn.onl.git
cd opn.onl
# Copy environment file
cp .env.example .env
# Edit .env with your settings
nano .env
# Start with Docker Compose
docker-compose up -dEnvironment Variables
| Variable | Description | Default |
|---|---|---|
DATABASE_URL | PostgreSQL connection string | Required |
JWT_SECRET | Secret for JWT tokens | Required |
BASE_URL | API base URL | http://localhost:3000 |
FRONTEND_URL | Frontend URL | http://localhost:5173 |
REDIS_URL | Redis connection (optional) | - |
SMTP_HOST | SMTP server hostname | - |
MIN_ALIAS_LENGTH | Minimum custom alias length | 5 |
ENABLE_URL_SANITIZATION | Block malicious URLs | true |
ENABLE_QR_BRANDING | Brand colour / logo / SVG on QR codes | true |
ENABLE_BURN_AFTER_READING | One-time / self-destruct links | true |
ENABLE_SAFE_LINK_INTERSTITIAL | Destination preview + reputation before redirect | true |
ENABLE_CONDITIONAL_ROUTING | Route by device / OS / country / language + A/B | true |
ENABLE_LINK_IN_BIO | Opt-in public link-in-bio profile pages | true |
ENABLE_API_KEYS | Personal API keys for the MCP server / API clients | true |
For complete setup instructions, see the GitHub repository.
Features
Custom Aliases
Create memorable short links
Analytics
Track clicks, locations, devices
Password Protection
Secure sensitive links
Expiration Dates
Auto-expire links
Folders
Organize your links
Tags
Label and filter links
Teams
Collaborate with others
GeoIP Analytics
See where clicks come from
Get Help
Need Custom Development?
Whether you need help setting up your own instance, custom integrations, or additional features - I'm here to help!
Built with ❤️ by Yevhen Salitrynskyi
