Skip to main content

Signed Links

Signed Links let your users vote and submit requests without creating a FeatKit account. You pass their identity from your app, we verify the signature.

How it works

  1. Your backend generates a signed URL with user info
  2. Your app opens this URL
  3. User is automatically authenticated on the portal
  4. Votes and submissions are tied to their identity

What you need

  • Project ID — from Project Settings
  • Secret Key — from Project Settings → Signed Links
  • User info: ID (required), email (optional), name (optional)
Your backend creates a signed token with user data.

Signature structure

Payload: { user_id, email, name, timestamp, expires }
Signature: HMAC-SHA256(payload, secret_key)
Final URL: https://featkit.com/p/[slug]?token=[base64payload].[signature]

Code examples

import hmac
import hashlib
import base64
import json
import time

def generate_signed_link(slug, secret_key, user_id, email=None, name=None):
    payload = {
        "user_id": user_id,
        "email": email,
        "name": name,
        "timestamp": int(time.time()),
        "expires": int(time.time()) + 86400  # 24 hours
    }
    payload_json = json.dumps(payload, separators=(',', ':'))
    payload_b64 = base64.urlsafe_b64encode(payload_json.encode()).decode()
    signature = hmac.new(secret_key.encode(), payload_b64.encode(), hashlib.sha256).hexdigest()
    return f"https://featkit.com/p/{slug}?token={payload_b64}.{signature}"

Token expiration

Tokens should expire. Recommended: 24 hours. Set the expires field to timestamp + 86400.
Shorter expiration times (1-4 hours) are more secure but require more frequent token generation.

Opening in your iOS app

Request the signed URL from your backend, then open it:
import SafariServices

func openAuthenticatedPortal(signedURL: String) {
    guard let url = URL(string: signedURL) else { return }
    let safari = SFSafariViewController(url: url)
    present(safari, animated: true)
}

Testing

Generate a test link in your dashboard: Project Settings → Signed Links → Test Link Generator This lets you verify your integration without deploying backend changes.

Security notes

Never expose your Secret Key in client code. Generate tokens on your backend only.
  • Store your Secret Key securely (environment variables, secrets manager)
  • Generate tokens server-side only
  • Use HTTPS for all requests
  • Set reasonable expiration times