API Documentation
Complete reference for the PVTLNK REST API
Related Document: Encryption Architecture Guide
Learn about our security architecture
PVTLNK API Documentation
Overview
PVTLNK provides a RESTful API for Enterprise subscribers to programmatically manage links, access analytics, and integrate with external systems.
Base URL: https://pvt.link/api
Authentication: API Token (Enterprise only)
Authentication
All API v1 endpoints require authentication via API token. Include the token in the Authorization header:
Authorization: Bearer YOUR_API_TOKEN
Generate API Token
Generate a new API token from the API Settings page or programmatically:
http
POST /api/v1/tokens/generate
Authorization: Bearer EXISTING_TOKEN
Response:
json
{
"token": "abc123...",
"expires_at": "2027-01-20T00:00:00Z"
}
Revoke API Token
http
DELETE /api/v1/tokens/revoke
Authorization: Bearer YOUR_API_TOKEN
Links API
List All Links
http
GET /api/v1/links
Authorization: Bearer YOUR_API_TOKEN
Query Parameters:
- page (integer) - Page number for pagination
- per_page (integer) - Results per page (default: 25, max: 100)
Response:
json
{
"links": [
{
"id": 123,
"short_code": "abc123",
"short_url": "https://pvt.link/abc123",
"destination_url": "https://example.com",
"title": "My Link",
"click_count": 150,
"created_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"current_page": 1,
"total_pages": 5,
"total_count": 123
}
}
Get Single Link
http
GET /api/v1/links/:id
Authorization: Bearer YOUR_API_TOKEN
Create Link
```http POST /api/v1/links Authorization: Bearer YOUR_API_TOKEN Content-Type: application/json
{ “link”: { “destination_url”: “https://example.com”, “title”: “My Campaign Link”, “short_code”: “custom-code”, “password”: “optional-password”, “starts_at”: “2026-01-20T00:00:00Z”, “expires_at”: “2026-02-20T00:00:00Z”, “utm_params”: { “utm_source”: “newsletter”, “utm_medium”: “email”, “utm_campaign”: “jan-2026” } } } ```
Response:
json
{
"link": {
"id": 456,
"short_code": "custom-code",
"short_url": "https://pvt.link/custom-code",
"destination_url": "https://example.com",
"title": "My Campaign Link",
"click_count": 0,
"created_at": "2026-01-20T12:00:00Z"
}
}
Update Link
```http PATCH /api/v1/links/:id Authorization: Bearer YOUR_API_TOKEN Content-Type: application/json
{ “link”: { “destination_url”: “https://new-destination.com”, “title”: “Updated Title” } } ```
Delete Link
http
DELETE /api/v1/links/:id
Authorization: Bearer YOUR_API_TOKEN
Bulk Import Links
```http POST /api/v1/links/bulk_import Authorization: Bearer YOUR_API_TOKEN Content-Type: application/json
{ “links”: [ { “destination_url”: “https://example1.com”, “title”: “Link 1” }, { “destination_url”: “https://example2.com”, “title”: “Link 2” } ] } ```
Analytics API
Get Analytics Overview
http
GET /api/v1/analytics/overview
Authorization: Bearer YOUR_API_TOKEN
Query Parameters:
- days (integer) - Number of days to include (default: 30)
Response:
json
{
"total_clicks": 15234,
"total_links": 89,
"unique_visitors": 12456,
"clicks_by_day": {
"2026-01-15": 523,
"2026-01-16": 612,
"2026-01-17": 489
},
"top_links": [
{
"id": 123,
"short_code": "abc123",
"title": "Popular Link",
"click_count": 2345
}
]
}
Get Advanced Analytics
http
GET /api/v1/analytics/advanced
Authorization: Bearer YOUR_API_TOKEN
Query Parameters:
- link_id (integer) - Filter by specific link
- days (integer) - Number of days to include
Response:
json
{
"devices": {
"desktop": 6234,
"mobile": 8123,
"tablet": 877
},
"browsers": {
"Chrome": 8234,
"Safari": 4123,
"Firefox": 2877
},
"countries": {
"US": 5234,
"UK": 3123,
"DE": 2877
},
"referrers": {
"google.com": 3234,
"twitter.com": 2123,
"direct": 9877
}
}
Conversion Tracking API
Track Conversion (Postback)
Public endpoint for tracking conversions. No authentication required - uses postback token.
```http POST /api/conversions/track/:token Content-Type: application/json
{ “value”: 99.99, “currency”: “USD”, “order_id”: “ORDER-12345”, “click_id”: 789 } ```
URL Parameters:
- token - Postback token from conversion goal
Body Parameters (all optional):
- value (decimal) - Conversion value (overrides goal default)
- currency (string) - 3-letter currency code
- order_id (string) - External order/transaction ID
- click_id (integer) - ClickAnalytic ID for explicit attribution
- ip (string) - Client IP for automatic attribution
- ua (string) - User agent for automatic attribution
Response:
json
{
"success": true,
"conversion_id": 456,
"attributed": true,
"value": 99.99,
"time_to_convert": "2.5 hours"
}
Error Responses:
404- Invalid postback token410- Conversion goal is inactive403- Feature not available for subscription409- Duplicate conversion (already tracked)
Outbound Webhooks
Enterprise users can configure webhooks to receive real-time notifications for events.
Configuration
Set up webhooks in API Settings: - Webhook URL: Your HTTPS endpoint - Webhook Secret: For HMAC-SHA256 signature verification
Event Types
link.clicked- Triggered when a short link is clickedconversion.tracked- Triggered when a conversion is recordedsubscription.updated- Triggered on subscription changes
Webhook Payload
json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"event": "link.clicked",
"created_at": "2026-01-20T12:30:45Z",
"data": {
"link": {
"id": 123,
"short_code": "abc123",
"original_url": "https://example.com"
},
"click": {
"id": 789,
"timestamp": "2026-01-20T12:30:45Z",
"country": "US",
"device_type": "mobile",
"browser": "Chrome",
"os": "iOS"
}
}
}
Signature Verification
Webhooks are signed with HMAC-SHA256. Verify using the X-PVTLNK-Signature header:
```ruby expected_signature = OpenSSL::HMAC.hexdigest(“SHA256”, webhook_secret, request.raw_post) provided_signature = request.headers[“X-PVTLNK-Signature”].sub(“sha256=”, “”)
if Rack::Utils.secure_compare(expected_signature, provided_signature) # Signature is valid end ```
Retry Policy
Failed webhook deliveries are retried up to 3 times with exponential backoff: - First retry: 1 second - Second retry: 5 seconds - Third retry: 30 seconds
Rate Limits
- API v1 endpoints: 100 requests per minute
- Conversion postback: 1000 requests per minute
Rate limit headers are included in all responses:
- X-RateLimit-Limit: Maximum requests per window
- X-RateLimit-Remaining: Requests remaining
- X-RateLimit-Reset: Unix timestamp when limit resets
Error Responses
All errors follow a consistent format:
json
{
"error": "Error message",
"code": "error_code",
"details": {}
}
HTTP Status Codes
200- Success201- Created400- Bad Request401- Unauthorized403- Forbidden404- Not Found409- Conflict422- Unprocessable Entity429- Too Many Requests500- Internal Server Error
SDK & Libraries
Coming soon: - JavaScript/TypeScript SDK - Python SDK - Ruby gem - PHP package
Support
For API support, contact us through your Enterprise dashboard or at api@pvt.link.