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-token

For 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
POST/links

Create 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" }
GET/links

List your links (requires auth)

Query Parameters

  • search - Search by URL or code
  • folder_id - Filter by folder
  • tag_id - Filter by tag
  • limit - Number of results (default: 50)
  • offset - Pagination offset

Other Endpoints

GET/links/{id}Get link details
PUT/links/{id}Update a link
DELETE/links/{id}Delete a link
GET/links/{id}/statsGet link analytics
GET/links/{id}/qrGenerate QR code — optional ?color=, logo=true, format=svg
GET/links/{id}/rulesList / replace (PUT) smart-routing rules
PUT/auth/bioUpdate your link-in-bio settings
GET/api/bio/{username}Public bio profile (when enabled)
GET/auth/api-keysList / create (POST) keys; DELETE /auth/api-keys/{id} to revoke
GET/links/exportExport links as CSV

Full 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 -d

Environment Variables

VariableDescriptionDefault
DATABASE_URLPostgreSQL connection stringRequired
JWT_SECRETSecret for JWT tokensRequired
BASE_URLAPI base URLhttp://localhost:3000
FRONTEND_URLFrontend URLhttp://localhost:5173
REDIS_URLRedis connection (optional)-
SMTP_HOSTSMTP server hostname-
MIN_ALIAS_LENGTHMinimum custom alias length5
ENABLE_URL_SANITIZATIONBlock malicious URLstrue
ENABLE_QR_BRANDINGBrand colour / logo / SVG on QR codestrue
ENABLE_BURN_AFTER_READINGOne-time / self-destruct linkstrue
ENABLE_SAFE_LINK_INTERSTITIALDestination preview + reputation before redirecttrue
ENABLE_CONDITIONAL_ROUTINGRoute by device / OS / country / language + A/Btrue
ENABLE_LINK_IN_BIOOpt-in public link-in-bio profile pagestrue
ENABLE_API_KEYSPersonal API keys for the MCP server / API clientstrue

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