Most links are immortal by default and dead in practice: the campaign ends, the offer expires, the preview must not outlive the launch — yet the URL keeps redirecting forever. Link expiration is the discipline of giving URLs a lifecycle. This guide covers the two expiry models, the status-code semantics, and the operational patterns that make expiring links painless.
Two models: time and clicks
Time-based expiry — the link dies at a moment in time. Right for anything with a deadline: campaign landing pages, contract periods, event registration, beta windows, time-limited offers.
Click-based expiry — the link dies after N total clicks. Right for anything with scarcity: limited-capacity registration, invite codes, giveaway entries, temporary downloads.
| Model | Best for | Default in practice |
|---|---|---|
| Time (ISO datetime) | Campaigns, contracts, events | Most links should have one |
| Clicks (integer) | Scarcity mechanics | Occasional, precise use |
| Neither | Evergreen content, menus, docs | When the URL is the asset |
The platform supports both on the same link — a link can expire after 30 days and after 500 clicks, whichever comes first.
Status-code semantics: 410 Gone
An expired link must say something precise. The right response is 410 Gone — the HTTP status for "the resource intentionally no longer exists" — with a short human-readable page explaining the link has expired. Compare the alternatives:
| Status | Meaning | Right for |
|---|---|---|
| 404 | Resource not found | Unknown codes, typos |
| 410 | Resource intentionally gone | Expired links |
| 302 | Redirect | Live links only |
410 matters for three reasons: recipients understand "expired" instead of "broken"; search engines stop trying to crawl it; and your analytics can distinguish dead links from typos.
The renewal pattern
Expiry shouldn't mean death — it should mean paused until renewed. The link record remains in the dashboard with its historical data; updating the expiry (or clearing it) reactivates the identical short URL:
# Link expires 2026-09-01
curl -X PATCH https://yas.sh/api/v1/links/<id> \
-H "Authorization: Bearer yas_live_..." -H "Content-Type: application/json" \
-d '{"expiresAt":"2026-10-01T00:00:00Z"}'
# Renew indefinitely
curl -X PATCH https://yas.sh/api/v1/links/<id> \
-H "Authorization: Bearer yas_live_..." -H "Content-Type: application/json" \
-d '{"expiresAt":""}'
Because the short code never changes, renewal is invisible to everyone who already has the link — printed QR codes keep working, emails stay valid. That's the practical payoff of dynamic links.
Operational patterns that work
Deadline margin. Set campaign links to expire 7–14 days after the official end date. Late clicks still convert (people bookmark, revisit, forward), and the margin absorbs them without extending the campaign's life forever.
Contract hygiene. For client-facing links, tie expiry to the contract end date plus notice period. When the contract renews, renew the links — the renewal pattern makes this a 30-second dashboard task.
Scarcity precision. For click-limited links, set the limit slightly below capacity (e.g. 48 of 50) so over-subscription never turns into a public error — the platform stops redirecting at the limit, which is also the moment you learn the true demand.
Audit via analytics. Expired links keep their click history. Quarterly, review links that expired with high click velocity — high demand is the signal that a link should be renewed, not retired.
The dashboard workflow
The dashboard lists every link with its expiry state; expired links are flagged and can be renewed or deleted in one click. Combined with the CSV export, a full link-lifecycle review is an export-and-filter exercise:
# Export all links with expiry state
curl -H "Authorization: Bearer yas_live_..." \
"https://yas.sh/api/v1/links/export.csv" -o links.csv
Conclusion
Link expiration is lifecycle management for URLs: time limits for deadlines, click limits for scarcity, 410 semantics for clarity, and renewal without code change for agility. It's the difference between a link that lingers forever and a link that knows when its job is done. Set your first expiry on the dashboard — the API docs show the full field contract.
