Create & Manage Links
Full REST reference for creating smart links, reading configuration, updating destinations and access rules, and deleting links when campaigns end.
Custom slugs
Choose memorable paths like /summer26 or let ExaLink generate a random slug.
UTM objects
Pass source, medium, campaign, term, and content once — applied on every redirect.
Password & caps
Gate links with a password, expire them, or stop traffic after maxClicks.
Branded domains
Serve short URLs from verified domains such as go.yourbrand.com.
Authentication
Authorization: Basic <token>. Auth guide →POST
/v1/exalink/links
GET
/v1/exalink/links/:id
PATCH
/v1/exalink/links/:id
DELETE
/v1/exalink/links/:id
Creates a new smart link. On success the response includes a stable id and the public shortUrl. Rate limit: 100 requests/second per API key.
Request body
{"destination": "https://shop.example.com/summer-sale","slug": "summer26","domain": "go.example.com","title": "Summer Sale 2026","utm": {"source": "sms","medium": "campaign","campaign": "summer_sale_2026","term": "discount","content": "hero_cta"},"expiresAt": "2026-09-30T23:59:59.000Z","password": "vip-access","maxClicks": 10000}
Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
| destination | string | required | Target URL after redirect. Query strings on the destination are preserved; UTM params from the utm object are merged (utm wins on key collision). |
| slug | string | optional | Custom short path. If omitted, a unique random slug is generated. Case-sensitive uniqueness is enforced per domain. |
| domain | string | optional | Hostname for the short URL (default "sndx.in"). Must be verified in Dashboard → ExaLink → Domains. |
| title | string | optional | Optional display name for dashboards, exports, and webhook payloads. Max 120 characters. |
| utm | object | optional | Optional UTM bag: source, medium, campaign, term, content. Stored on the link and applied on every redirect. |
| utm.source | string | optional | Maps to utm_source on the final URL. |
| utm.medium | string | optional | Maps to utm_medium on the final URL. |
| utm.campaign | string | optional | Maps to utm_campaign on the final URL. |
| utm.term | string | optional | Maps to utm_term (optional). |
| utm.content | string | optional | Maps to utm_content (optional). |
| expiresAt | string (ISO 8601) | optional | When set, the link transitions to expired after this timestamp. Pass null later via PATCH to clear. |
| password | string | optional | If set, users see a password form before redirect. Never returned in plaintext on subsequent GET responses. |
| maxClicks | integer | optional | Hard cap on total recorded clicks. When reached, status becomes capped and redirects stop. |
Responses
{"success": true,"code": "LINK_CREATED","message": "Smart link created successfully.","requestId": "REQ-1782201000456","timestamp": "2026-07-12T10:30:00.456Z","data": {"id": "link_01HZXK9P2M7QVR8N4W3T6Y5B0A","shortUrl": "https://go.example.com/summer26","slug": "summer26","domain": "go.example.com","destination": "https://shop.example.com/summer-sale?utm_source=sms&utm_medium=campaign&utm_campaign=summer_sale_2026&utm_term=discount&utm_content=hero_cta","title": "Summer Sale 2026","status": "active","utm": {"source": "sms","medium": "campaign","campaign": "summer_sale_2026","term": "discount","content": "hero_cta"},"passwordProtected": true,"maxClicks": 10000,"expiresAt": "2026-09-30T23:59:59.000Z","clicks": 0,"uniqueClicks": 0,"createdAt": "2026-07-12T10:30:00.456Z","updatedAt": "2026-07-12T10:30:00.456Z"}}
Code examples
curl -X POST 'https://api.sendexa.co/v1/exalink/links' \-H 'Content-Type: application/json' \-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \-d '{"destination": "https://shop.example.com/summer-sale","slug": "summer26","title": "Summer Sale 2026","utm": {"source": "sms","medium": "campaign","campaign": "summer_sale_2026"},"maxClicks": 10000}'
Returns the full configuration and lifetime counters for a single link. The plaintext password is never returned — only passwordProtected: true|false.
| Field | Type | Required | Description |
|---|---|---|---|
| id | path string | required | Link identifier returned on create (e.g. link_01HZX…). |
curl -X GET 'https://api.sendexa.co/v1/exalink/links/link_01HZXK9P2M7QVR8N4W3T6Y5B0A' \-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \-H 'Accept: application/json'
Partial update. Only fields you send are changed. Use this to rotate destinations mid-campaign, clear a password, pause a link, or extend expiry. Slug and domain cannot be changed after create (delete and recreate if you need a new path).
| Field | Type | Required | Description |
|---|---|---|---|
| id | path string | required | Link identifier. |
| destination | string | optional | New target URL. |
| title | string | optional | New display title. |
| utm | object | optional | Replace the entire UTM object. Omitted keys inside utm are cleared if you send a new object. |
| expiresAt | string | null | optional | New expiry, or null to remove expiry. |
| password | string | null | optional | Set a new password, or null to disable password protection. |
| maxClicks | integer | null | optional | New cap, or null for unlimited. |
| status | "active" | "paused" | optional | Pause or resume the link without deleting historical analytics. |
{"destination": "https://shop.example.com/summer-sale-v2","title": "Summer Sale 2026 (extended)","expiresAt": "2026-10-15T23:59:59.000Z","password": null,"status": "active"}
Analytics continuity
destination or UTM does not reset click counters. Historical timeseries remain under the same id.Permanently deletes the link. The short URL stops resolving immediately (HTTP 404 for visitors). Analytics snapshots may still be available for a retention window via the dashboard; the REST analytics endpoint returns LINK_NOT_FOUND after delete.
| Field | Type | Required | Description |
|---|---|---|---|
| id | path string | required | Link identifier to delete. |
curl -X DELETE 'https://api.sendexa.co/v1/exalink/links/link_01HZXK9P2M7QVR8N4W3T6Y5B0A' \-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN'
Irreversible
status: "paused" via PATCH if you might reuse the same short path later. DELETE frees the slug for new links, but previous QR codes or printed URLs will break.| Code | When |
|---|---|
| 201 | POST create succeeded |
| 200 | GET / PATCH / DELETE succeeded |
| 400 | Validation failed (body or query) |
| 401 | Missing or invalid Basic Auth token |
| 403 | Domain not verified or feature not enabled |
| 404 | Unknown link id |
| 409 | Slug already taken on domain |
| 429 | Rate limit exceeded |
| 500 | Unexpected server error — retry with backoff |