Link Types

DyLy supports four distinct types of links, each designed for specific use cases. Understanding these link types will help you choose the right solution for your needs.

Overview

  • URL Link: Redirects users to a registered URL - perfect for link shortening and tracking
  • JSON Link: Returns registered JSON data - ideal for static endpoints and configuration
  • JWT Link: Returns a cryptographically signed JWT with your JSON payload - secure data delivery
  • Deep Link: Launches mobile apps from web links - seamless app integration

URL links are the most straightforward type - they redirect visitors to a specified destination URL. This is the classic "link shortener" functionality.

How It Works

  1. User clicks the short link (e.g., https://myapp.dyly.dev/promo)
  2. DyLy server receives the request and validates the link
  3. Server responds with an HTTP 302 redirect to the destination URL
  4. User's browser automatically follows the redirect to the final destination

Key Features

  • Simple Redirection: One-to-one mapping from short URL to destination
  • Tracking: DyLy can track clicks, user agents, and referrers (if enabled)
  • Any Destination: Redirect to any valid URL on the internet
  • Preserves Context: Query parameters and fragments can be preserved or modified

Use Cases

Marketing & Analytics:

  • Shorten long campaign URLs for social media posts
  • Track click-through rates across different channels
  • Create memorable links for offline marketing (billboards, print ads)
  • A/B testing different landing pages

User Experience:

  • Simplify complex URLs with many parameters
  • Create human-readable links for documentation
  • Replace auto-generated URLs with branded short links
  • Reduce character count for SMS or Twitter

Operations:

  • Redirect old URLs to new locations after site restructuring
  • Create temporary redirects for events or promotions
  • Centralize link management across multiple platforms

Example API Request

POST /url/api/v1/links
{
  "type": "url",
  "projectId": "your-project-id",
  "destinationUrl": "https://example.com/products/awesome-product?utm_source=social&utm_campaign=spring2024",
  "path": "spring-sale",
  "expiresIn": 2592000
}

Response:

{
  "shortUrl": "https://myapp.dyly.dev/spring-sale",
  "destinationUrl": "https://example.com/products/awesome-product?utm_source=social&utm_campaign=spring2024",
  "expiresAt": "2024-05-01T00:00:00Z",
  ...
}

Best Practices

Use Descriptive Paths: For user-facing links, choose memorable paths
Set Appropriate Expiration: Marketing links often need longer expiration than temporary shares
Monitor Analytics: Track link performance to measure campaign effectiveness
Test Destinations: Ensure the destination URL is correct before distributing the short link

Tip: URL links can be created from both the portal UI and the API, making them the most accessible link type.

JSON links return structured JSON data instead of redirecting. They act as static API endpoints, perfect for configuration files, metadata, or any structured data.

How It Works

  1. User or application requests the link (e.g., https://myapp.dyly.dev/api/config)
  2. DyLy server receives the request and validates the link
  3. Server responds with HTTP 200 OK and the registered JSON as the response body
  4. Content-Type: application/json header is automatically set

Key Features

  • Static Endpoints: Create API-like endpoints without backend infrastructure
  • No Database Required: Store configuration or metadata directly in DyLy
  • Versioning: Create different paths for different versions (e.g., /v1/config, /v2/config)
  • Standard JSON: Any valid JSON structure is supported

Use Cases

Well-Known Endpoints:

  • .well-known/apple-app-site-association for Apple Universal Links
  • .well-known/assetlinks.json for Android App Links
  • .well-known/openid-configuration for OAuth/OIDC discovery
  • .well-known/security.txt for security contact information

Configuration & Metadata:

  • App configuration that can be updated without app releases
  • Feature flags and remote configuration
  • Public metadata about your service or API
  • Static API responses for testing or demos

Data Sharing:

  • Public datasets or reference data
  • Shared team configurations
  • Standard response templates
  • API mock endpoints for development

Example API Request

POST /url/api/v1/links
{
  "type": "json",
  "projectId": "your-project-id",
  "path": ".well-known/apple-app-site-association",
  "jsonContent": {
    "applinks": {
      "apps": [],
      "details": [
        {
          "appIDs": ["TEAM123.com.example.app"],
          "paths": ["*"]
        }
      ]
    }
  }
}

When accessed, the link returns:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appIDs": ["TEAM123.com.example.app"],
        "paths": ["*"]
      }
    ]
  }
}

Limitations

  • Maximum JSON size: Check current limits in the API documentation
  • No dynamic content - JSON is static once created
  • To update content, you must update the link via API or create a new one

Best Practices

Validate JSON: Ensure your JSON is valid before creating the link
Use Specific Paths: Follow conventions for well-known endpoints
Version Your Endpoints: Use paths like /v1/config for future compatibility
Document Schema: Provide documentation for the JSON structure you're serving

Developer Tip: JSON links are perfect for microservices architecture where you need simple, stateless data endpoints without spinning up additional infrastructure.

JWT links return cryptographically signed JSON data as a JWT (JSON Web Token). This ensures data integrity and authenticity, making them ideal for secure data exchange.

How It Works

JWT links can work in three different flows, depending on your security and application requirements:

Flow 1: Direct JWT Response

  1. User or application requests the link
  2. DyLy returns the JWT directly as the response body
  3. Consumer validates the JWT signature using the public JWKS

Best for: Server-to-server communication, request_uri parameters

Flow 2: Redirect - Implicit (Fragment-Based)

  1. User clicks the link in a browser
  2. DyLy redirects to destinationUrl#jwt=<token>
  3. Client-side JavaScript extracts the JWT from the URL fragment
  4. Application validates and uses the JWT

Best for: Single Page Applications (SPAs), client-side apps

Flow 3: Redirect - Code (Authorization Code)

  1. User clicks the link
  2. DyLy redirects to destinationUrl?code=<authorization-code>&state=<state>
  3. Backend exchanges the code for the JWT using Client ID/Secret or PKCE
  4. Application validates and uses the JWT

Best for: Web apps with backends, mobile apps, any OAuth 2.0-style flow

JWT Structure & Claims

DyLy automatically includes standard claims in every JWT:

Default Claims (automatically added, cannot be overwritten):

  • iss (Issuer): Set to your link's domain (e.g., myapp.dyly.dev)
  • iat (Issued At): UTC timestamp when the JWT was generated
  • exp (Expiration): UTC timestamp when the JWT expires
  • nbf (Not Before): UTC timestamp before which the JWT is invalid
  • jti (JWT ID): Unique identifier for this specific JWT

Custom Claims: You can add any additional claims in the jwtClaims field:

{
  "jwtClaims": {
    "sub": "user-123",
    "email": "user@example.com",
    "role": "admin",
    "nonce": "random-nonce-value"
  }
}

Signature & Verification

Signing:

  • DyLy signs all JWTs using industry-standard algorithms (RS256)
  • Signing keys are securely managed by DyLy - you don't need to manage keys
  • Each project has its own signing keys for isolation

Verification:

  • Public keys are available at https://<your-domain>/jwks.json
  • Use standard JWT libraries to verify signatures (e.g., jsonwebtoken in Node.js, PyJWT in Python)
  • Always verify the signature before trusting JWT contents

Use Cases

Passwordless Authentication:

  • Magic links for login (see Magic Link tutorial)
  • Email verification links
  • Password reset flows

Secure Data Transfer:

  • Delivering signed configuration or metadata
  • Transferring user claims between systems
  • Signed invitations or access tokens

OAuth 2.0 & OpenID Connect:

  • request_uri parameter in RFC9101
  • Custom authentication flows
  • Federation between services

State Validation (CSRF Protection)

When using redirect flows (Implicit or Code), you should use the state validation API to prevent CSRF attacks.

How It Works:

  1. When a user clicks the JWT link, DyLy sets a session cookie and generates a state parameter
  2. The state is included in the redirect URL
  3. Your application calls the state validation API with the state value
  4. DyLy verifies the state matches the session cookie
  5. If valid, you can proceed with confidence that the request is legitimate

State Validation API:

GET https://<your-domain>/state-validation?state=<state>&clientId=<clientId>&alias=<alias>
Cookie: <session-cookie-automatically-included>

Response:

{
  "cookieValidation": "VALID",
  "clickedAt": "2024-03-15T10:30:00Z",
  "userAgent": "Mozilla/5.0...",
  "ipAddress": "192.168.1.1"
}

Important: State validation must be called from the browser (where the cookie exists), not from your backend server. For mobile apps, ensure cookies are preserved across the authentication flow.

Alternative Validation: If cookie-based validation isn't feasible, the response metadata (IP address, user agent, timestamp) can be used for heuristic validation, though this provides weaker security guarantees.

Example API Request (Code Flow with PKCE)

POST /url/api/v1/links
{
  "type": "jwt",
  "projectId": "your-project-id",
  "flow": "code",
  "clientType": "public",
  "destinationUrl": "https://yourapp.com/auth/callback",
  "jwtClaims": {
    "sub": "user-12345",
    "email": "user@example.com",
    "role": "member"
  },
  "jwtExpiresIn": 300,
  "expiresIn": 3600,
  "oneTime": true,
  "keyProtected": true
}

Response:

{
  "shortUrl": "https://myapp.dyly.dev/abc123?key=secret456",
  "flow": "code",
  "clientType": "public",
  "codeVerifier": "save-this-securely",
  ...
}

Later, exchange the code for JWT:

POST https://dyly-api.lilacwells.com/url/api/v1/links/{alias}/jwt
Content-Type: application/x-www-form-urlencoded

code=<code-from-redirect>&client_id=<clientId>&clientType=public&codeVerifier=<saved-verifier>

Security Considerations

⚠️ Implicit Flow Risk: The implicit flow (fragment-based) exposes the JWT in the URL fragment. While fragments aren't sent to servers, they may appear in browser history or logs. Use with caution and only for appropriate use cases.

⚠️ Code Flow Recommended: For sensitive data, use the code flow with client authentication (confidential) or PKCE (public clients).

⚠️ Short JWT Expiration: Set jwtExpiresIn to the minimum time needed (e.g., 5 minutes) to reduce the window of exposure if a JWT is compromised.

⚠️ Always Verify Signatures: Never trust JWT contents without verifying the signature against the JWKS.

Use State Validation: Always implement state validation in redirect flows to prevent CSRF attacks.

Combine Security Features: Use oneTime: true and keyProtected: true for maximum security in sensitive flows.

Best Practices

Choose the Right Flow: Direct for server-to-server, Code for web/mobile apps, Implicit only when necessary
Minimize JWT Lifetime: Set jwtExpiresIn as short as practical
Validate Everything: Always verify JWT signatures and check all claims (exp, nbf, iss, etc.)
Use PKCE for Public Clients: Mobile apps and SPAs should use PKCE instead of client secrets
Implement State Validation: Protect against CSRF with proper state validation
Monitor Usage: Track JWT link usage for security auditing

Deep links seamlessly bridge web and mobile experiences by launching your mobile app directly from a web URL, optionally navigating to specific in-app screens.

How It Works

When App is Installed:

  1. User clicks the deep link (e.g., https://myapp.dyly.dev/product/123)
  2. Operating system intercepts the request (via Universal Links on iOS or App Links on Android)
  3. OS launches your app instead of opening the browser
  4. App receives the URL and routing information
  5. App navigates to the appropriate screen (e.g., product detail page)

When App is NOT Installed:

  1. User clicks the deep link
  2. Browser opens and requests the URL from DyLy
  3. DyLy sets a deferred deep link cookie
  4. DyLy redirects to destinationUrl (typically your app store page)
  5. User downloads and installs the app
  6. On first launch, app calls the deferred parameters endpoint
  7. DyLy returns the original deep link parameters
  8. App navigates to the intended screen

Required Setup

To use deep links, you must first configure well-known endpoints:

For iOS (Universal Links): Create a JSON link at .well-known/apple-app-site-association:

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appIDs": ["TEAM123.com.example.app"],
        "paths": [
          "NOT /_/*",
          "NOT /deferred-params",
          "/*"
        ]
      }
    ]
  }
}

For Android (App Links): Create a JSON link at .well-known/assetlinks.json:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.app",
    "sha256_cert_fingerprints": ["14:6D:E9:83:..."]
  }
}]

Important: Add "NOT /deferred-params" to your paths to prevent the app from launching when calling the deferred parameters API.

Deferred Deep Linking

Deferred deep linking allows you to preserve link context even when the app isn't installed at click time.

How It Works:

  1. DyLy sets a cookie when the link is clicked
  2. After app installation, app calls /deferred-params?clientId=<clientId>
  3. DyLy matches the request to the original click using:
    • Cookie (highest confidence)
    • IP address + User Agent (fallback)
  4. Returns the deep link token with a matching confidence score

API Request:

GET https://<your-domain>/deferred-params?clientId=<clientId>
Cookie: <automatically-included-if-browser>

Response:

{
  "token": "eyJhbGci...",
  "matchingScore": 0.95
}

Matching Score Interpretation:

  • 1.0: Cookie match - highest confidence, safe to use
  • 0.8-0.99: Strong IP/UA match - likely correct, use with caution
  • 0.6-0.79: Weak IP/UA match - low confidence, consider not using
  • less than 0.6: No match found - DyLy returns 404

Token Validation

The token returned in deep links and deferred parameters contains:

  • Your custom jwtClaims (set when creating the link)
  • Link metadata (domain, path)
  • Standard JWT claims (iss, exp, etc.)

Your app must verify:

  1. ✅ JWT signature (using JWKS from https://<your-domain>/.well-known/jwks.json)
  2. iss claim matches your domain
  3. exp hasn't passed (token not expired)
  4. ✅ Custom claims match expected values

Use Cases

User Invitations:

  • Friend referral links that open to a specific group or feature
  • Team invitation links with pre-filled information
  • Content sharing that opens directly to shared content

Marketing Campaigns:

  • App install campaigns with deep links to promoted products
  • QR codes on physical products that open product details
  • Email campaigns that deep link to specific app screens

Customer Support:

  • Help articles that deep link to relevant settings
  • Troubleshooting links that open diagnostic screens
  • Account recovery flows

E-Commerce:

  • Product links from web to app
  • Cart recovery links
  • Order tracking that opens in app

Example API Request

POST /url/api/v1/links
{
  "type": "deep",
  "projectId": "your-project-id",
  "path": "products/awesome-widget",
  "destinationUrl": "https://apps.apple.com/app/yourapp/id123456",
  "jwtClaims": {
    "productId": "awesome-widget",
    "campaignId": "spring-2024",
    "referrerId": "user-789"
  },
  "jwtExpiresIn": 300,
  "expiresIn": 2592000,
  "keyProtected": false,
  "oneTime": false
}

Response:

{
  "shortUrl": "https://myapp.dyly.dev/products/awesome-widget",
  "type": "deep",
  "jwtClaims": {
    "productId": "awesome-widget",
    "campaignId": "spring-2024",
    "referrerId": "user-789"
  },
  ...
}

DyLy provides a modern alternative to Firebase Dynamic Links (which is being sunset):

FeatureFirebase Dynamic LinksDyLy Deep Links
SDK RequiredYesNo - API only
Deferred Deep LinkingYesYes
JWT Signed TokensNoYes
Custom DomainsYesYes (Paid Plan)
Link ExpirationNoYes
One-Time LinksNoYes (Paid Plan)
Protected LinksNoYes (Paid Plan)
Server-Side OnlyNoYes
StatusDeprecatedActive & Supported

Security Considerations

Always Validate Tokens: Never trust deep link parameters without verifying JWT signatures
Check Matching Score: For deferred deep links, only use high-confidence matches (≥0.9)
Implement Timeouts: Reject deferred parameters that are too old
Validate Claims: Ensure custom claims contain expected values and types
User Confirmation: For sensitive actions, ask for user confirmation even with valid deep links

⚠️ Phishing Risk: Educate users about legitimate deep link domains to prevent phishing
⚠️ Preview/Prefetch: Be aware that link previews may consume one-time links unintentionally

Best Practices

Test Both Paths: Test with app installed and app not installed scenarios
Fallback Gracefully: Always provide a good destination URL (app store or mobile web)
Include Context: Use jwtClaims to pass necessary routing and personalization data
Monitor Metrics: Track deep link performance, install attribution, and conversion rates
Handle Errors: Implement error handling for expired links, invalid tokens, or network issues

Use CaseRecommended Link TypeWhy?
URL ShorteningURL LinkSimple redirect, easiest to set up
App ConfigurationJSON LinkStatic data without backend infrastructure
Universal/App Links SetupJSON LinkRequired for well-known endpoints
Passwordless LoginJWT LinkCryptographic security with signatures
Invitation SystemDeep Link or JWT LinkDeep Link for mobile, JWT for web
Password ResetJWT LinkSecure, verifiable, one-time use
Marketing CampaignURL LinkSimple tracking and analytics
Mobile App LaunchDeep LinkSeamless app integration
OAuth request_uriJWT Link (Direct)Standard-compliant signed requests

Next Steps

Now that you understand the different link types:

  1. Review Core Features: Learn about expiration, protection, and other features that apply to all link types
  2. Follow Tutorials: See real-world implementations in Use Cases
  3. API Reference: Dive deep into the complete API documentation

Start Simple: Begin with URL links to get familiar with DyLy, then explore more advanced link types as your needs evolve.