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
- Your backend generates a signed URL with user info
- Your app opens this URL
- User is automatically authenticated on the portal
- 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)
Generating a Signed Link
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