API Documentation

Public Document 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


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

http GET /api/v1/links/:id Authorization: Bearer YOUR_API_TOKEN

```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" } }

```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” } } ```

http DELETE /api/v1/links/:id Authorization: Bearer YOUR_API_TOKEN

```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 token
  • 410 - Conversion goal is inactive
  • 403 - Feature not available for subscription
  • 409 - 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 clicked
  • conversion.tracked - Triggered when a conversion is recorded
  • subscription.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 - Success
  • 201 - Created
  • 400 - Bad Request
  • 401 - Unauthorized
  • 403 - Forbidden
  • 404 - Not Found
  • 409 - Conflict
  • 422 - Unprocessable Entity
  • 429 - Too Many Requests
  • 500 - 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.