Advanced Link Controls
Use this guide to configure scheduling, expiry, click caps, password protection, routing rules, and social previews on your short links.
When to use
- You want a link to go live at a specific date and time.
- You need a link to automatically expire after a deadline or click threshold.
- You want to password-protect a link before sharing it publicly.
- You need to route different audiences to different destinations from a single link.
Scheduling
Schedule a link to become active and/or deactivate at specific times.
| Field | Type | Effect |
|---|---|---|
scheduledStartAt | ISO 8601 timestamp | Link returns 404 before this time |
scheduledEndAt | ISO 8601 timestamp | Link returns 410 (Gone) after this time |
Both fields are optional. If neither is set, the link is active immediately and indefinitely (subject to the enabled flag).
Behavior at access time:
- Before
scheduledStartAt: visitor sees a 404 (link appears to not exist). - After
scheduledEndAt: visitor sees a 410 (link has ended). - Between the two: normal redirect behavior.
Expiry
Set an absolute expiration time after which the link stops working.
| Field | Type | Effect |
|---|---|---|
expiresAt | ISO 8601 timestamp | Link returns 410 (Gone) after this time |
After expiry:
- The link record is not deleted — it remains queryable via the API for history and analytics.
- The redirect returns HTTP 410 (Gone).
- Analytics collected before expiry are preserved.
Click caps
Limit the total number of clicks a link can receive.
| Field | Type | Effect |
|---|---|---|
maxClicks | Positive integer | Link becomes unavailable after reaching this count |
Set maxClicks to null or omit it to disable the cap. The minimum value is 1.
Password protection
Protect a link with a password. Visitors must enter the correct password before being redirected.
| Field | Type | Effect |
|---|---|---|
password | String (max 128 chars) | Visitor sees a password bridge page instead of immediate redirect |
When a password is set:
- Visitor navigates to the short link.
- Instead of a redirect, a password entry form is displayed.
- Visitor enters the password.
- If correct, the visitor is redirected to the destination.
- If incorrect, the form re-displays with an error message.
Set password to null or empty string to remove password protection.
Note: The API never returns the plaintext password — it returns a boolean indicating whether a password is set.
Routing rules
Route different visitors to different destinations from a single short link using conditional routing rules.
Each rule has:
| Property | Type | Description |
|---|---|---|
id | String | Unique rule identifier |
priority | 0–9999 | Lower number = higher priority |
weight | Number (optional) | Percentage for A/B testing |
destinationUrl | URL | Target destination for this rule |
conditions | Object (optional) | When this rule should apply |
Condition types
| Condition | Type | Example |
|---|---|---|
countryIn | String[] | ["US", "GB", "CA"] |
deviceIn | String[] | ["MOBILE", "TABLET"] |
sourceIn | String[] | ["email", "social"] |
campaignIn | String[] | ["spring-launch"] |
segmentIn | String[] | ["vip", "returning"] |
Rules are evaluated in priority order. The first matching rule wins. If no rule matches, the link's default destinationUrl is used.
Tracking policy
Control how click tracking and context tokens work for a link.
| Field | Type | Description |
|---|---|---|
mode | DIRECT or BRIDGE | Whether to use a tracking bridge page |
appendContextParam | Boolean | Append ?ctx= to destination URL |
templateRefs | String[] | References to tracking templates (UTM configs) |
contextVars | Object | Custom key-value pairs appended to tracking |
queryVarAllowlist | Array | Query parameters allowed to pass through to destination |
Social preview
Customize the Open Graph metadata shown when the link is shared on social platforms.
| Field | Type | Description |
|---|---|---|
ogTitle | String | Custom title for social cards |
ogDescription | String | Custom description for social cards |
ogImage | URL | Custom image for social cards |
Additional SEO controls:
| Field | Type | Description |
|---|---|---|
nofollow | Boolean | Add rel=nofollow to the redirect |
sponsored | Boolean | Mark link as sponsored content |
affiliateDisclosure | String | Affiliate disclosure text |
Link status
Links use a simple enabled/disabled model combined with scheduling and expiry:
| Condition | Effective status | HTTP response |
|---|---|---|
enabled is false | Disabled | 404 Not Found |
Before scheduledStartAt | Not yet active | 404 Not Found |
After scheduledEndAt | Ended | 410 Gone |
After expiresAt | Expired | 410 Gone |
| All conditions pass | Active | 302/307 Redirect |
Version history
The platform keeps up to 3 versions of each link snapshot. Each version records:
- Version number (auto-incremented)
- Snapshot timestamp
- Actor who made the change
- Complete link state at that version
Use the version history to audit who changed a link and when.
Tags and categories
Organize links with custom metadata:
| Field | Type | Description |
|---|---|---|
tags | String[] | Freeform tags for filtering and search |
categories | String[] | Predefined categories for grouping |
Tags and categories also feed into the platform's link embedding system for personalization.
UI path
- Open
https://app.{PUBLIC_DOMAIN}. - Navigate to your handle and open Links.
- Select a link or create a new one.
- Expand the Advanced Settings section.
- Configure scheduling, expiry, password, routing rules, or social preview.
- Save changes.
Required auth
- CREATOR-level
JWTor above to manage link settings. PATwithlinks.writescope for automation.
API fallback
Create or update a link
PUT /v2/handles/{handle}/links/{slug}
{
"destinationUrl": "https://example.com",
"title": "My Campaign Link",
"enabled": true,
"scheduledStartAt": "2026-03-01T00:00:00Z",
"scheduledEndAt": "2026-03-31T23:59:59Z",
"expiresAt": null,
"maxClicks": 1000,
"password": null,
"redirectType": "302",
"routingRules": [
{
"id": "rule-mobile",
"priority": 100,
"destinationUrl": "https://m.example.com",
"conditions": { "deviceIn": ["MOBILE"] }
}
],
"trackingPolicy": {
"mode": "DIRECT",
"appendContextParam": true
},
"socialPreview": {
"ogTitle": "Spring Campaign",
"ogDescription": "Check out our spring deals",
"ogImage": "https://cdn.example.com/spring.jpg"
},
"tags": ["spring", "promo"],
"categories": ["marketing"],
"nofollow": false,
"sponsored": false
}
Preview routing decision
POST /v2/handles/{handle}/links/{slug}/route-preview
{
"country": "US",
"device": "mobile",
"source": "email"
}
Returns which destination URL would be selected for the given conditions.
Common errors
| Code | Error | Cause |
|---|---|---|
| 400 | invalid_slug | Slug does not match ^[A-Za-z0-9_-]{4,24}$ |
| 400 | invalid_destination_url | URL is not a valid HTTP(S) URL or is on the blocked domain list |
| 400 | invalid_routing_rules | Rule priority out of range or missing required fields |
| 404 | not_found | Link does not exist |
Related: