# Update a link

`PUT https://app.clik.so/api/links/{id}`

> **In short:** Changes the fields you send and leaves the rest alone. Send `null` to clear a field, for example `expires_at` to remove the expiry or `geo_targeting` to remove the country rules.

## You need

* **API key permission:** `write`
* **Workspace role:** editor or higher
* **Plan:** some fields need a paid plan — see "Plan-gated fields" below.

## Example

```bash
curl -X PUT "https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c" \
  -H "Authorization: Bearer $CLIKSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "destination_url": "https://example.com/autumn-sale",
    "title": "Autumn sale",
    "expires_at": null
  }'
```

Response 200:

```json
{
  "status": 200,
  "success": true,
  "message": "Link updated",
  "data": {
    "id": "3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
    "workspace_id": "8a1f2c3d-4b5e-4f60-9a7b-1c2d3e4f5a6b",
    "custom_domain_id": null,
    "domain": "clik.is",
    "domain_status": "default",
    "title": "Autumn sale",
    "description": "",
    "short_code": "summer-sale",
    "destination_url": "https://example.com/autumn-sale",
    "status": "active",
    "expires_at": null,
    "expired_redirect_url": null,
    "folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
    "ab_testing": [],
    "geo_targeting": null,
    "device_targeting": null,
    "qr_metadata": null,
    "og_preview": null,
    "meta_pixel_id": null,
    "tiktok_pixel_id": null,
    "ga4_measurement_id": null,
    "gtm_container_id": null,
    "has_password": false,
    "click_count": 128,
    "created_by": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
    "created_at": "2026-10-09T09:30:00.000Z",
    "updated_at": "2026-10-10T08:15:00.000Z",
    "tags": [
      {
        "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
        "name": "launch",
        "color": "#3b82f6"
      }
    ],
    "creator": {
      "id": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
      "display_name": "Asha Rao",
      "email": "asha@example.com",
      "photo_url": ""
    }
  }
}
```

## Parameters

| Name | In   | Type   | Required | Description    |
| ---- | ---- | ------ | -------- | -------------- |
| `id` | path | string | yes      | The link's id. |

## Request body

| Field                     | Type                           | Required | Description                                                                                                                                                                                                                                                                                                     |
| ------------------------- | ------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `destination_url`         | string · uri                   | no       | A new destination.                                                                                                                                                                                                                                                                                              |
| `short_code`              | string                         | no       | A new code, by the same rules as on create (3–30 characters; `/` for a nested code on Starter and up, `402 UPGRADE_REQUIRED` on Free). A blank value, or the current code, keeps the current one. 3–30 characters Pattern `^(?:[a-zA-Z0-9-]+\|-*[a-zA-Z0-9][a-zA-Z0-9-]*(?:/-*[a-zA-Z0-9][a-zA-Z0-9-]*){1,4})$` |
| `domain`                  | string or null                 | no       | Move the link to `clik.is` or another free Clikso domain.                                                                                                                                                                                                                                                       |
| `custom_domain_id`        | string · uuid or null          | no       | Move the link to one of your verified custom domains.                                                                                                                                                                                                                                                           |
| `title`                   | string or null                 | no       | A new name. `null` clears it. Up to 60 characters                                                                                                                                                                                                                                                               |
| `description`             | string or null                 | no       | A new note. `null` clears it. Up to 250 characters                                                                                                                                                                                                                                                              |
| `status`                  | string                         | no       | `archived` or `expired` turns the short URL off; `active` turns it back on. One of: `active`, `archived`, `expired`                                                                                                                                                                                             |
| `folder_id`               | string · uuid or null          | no       | A new folder. `null` takes the link out of its folder.                                                                                                                                                                                                                                                          |
| `tags`                    | array of string · uuid or null | no       | Replaces all tags. `[]` removes them all; `null` or leaving it out keeps them.                                                                                                                                                                                                                                  |
| `password`                | string or null                 | no       | A new password. `null` removes it. Up to 100 characters                                                                                                                                                                                                                                                         |
| `expires_at`              | string · date-time or null     | no       | A new expiry. `null` removes it.                                                                                                                                                                                                                                                                                |
| `expired_redirect_url`    | string · uri or null           | no       | A new after-expiry destination. `null` clears it.                                                                                                                                                                                                                                                               |
| `ab_testing`              | array of ABVariant or null     | no       | New A/B variants. `null` or `[]` removes them.                                                                                                                                                                                                                                                                  |
| `ab_testing[].url`        | string · uri                   | yes      | Where this share of visitors goes.                                                                                                                                                                                                                                                                              |
| `ab_testing[].percentage` | integer                        | yes      | This variant's weight. Weights are relative, so they do not have to add up to 100. 0–100                                                                                                                                                                                                                        |
| `geo_targeting`           | GeoTargeting or any or null    | no       | New country rules. `null` or `{}` removes them.                                                                                                                                                                                                                                                                 |
| `device_targeting`        | DeviceTargeting or any or null | no       | New device rules. `null` or `{}` removes them.                                                                                                                                                                                                                                                                  |
| `og_preview`              | OgPreview or any or null       | no       | New social preview. `null` or `{}` removes it.                                                                                                                                                                                                                                                                  |
| `qr_metadata`             | QrMetadata or any or null      | no       | New QR style. `null` or `{}` resets it.                                                                                                                                                                                                                                                                         |
| `meta_pixel_id`           | string or null                 | no       | New Meta Pixel id. `null` clears it. Pattern `^\d{6,20}$`                                                                                                                                                                                                                                                       |
| `tiktok_pixel_id`         | string or null                 | no       | New TikTok Pixel id. `null` clears it. Pattern `^[A-Za-z0-9]{8,40}$`                                                                                                                                                                                                                                            |
| `ga4_measurement_id`      | string or null                 | no       | New GA4 measurement id. `null` clears it. Pattern `^G-[A-Z0-9]{4,16}$`                                                                                                                                                                                                                                          |
| `gtm_container_id`        | string or null                 | no       | New Tag Manager container id. `null` clears it. Pattern `^GTM-[A-Z0-9]{4,12}$`                                                                                                                                                                                                                                  |

## Plan-gated fields

| Field                | Feature            | Lowest plan |
| -------------------- | ------------------ | ----------- |
| `password`           | passwordProtection | Starter     |
| `og_preview`         | customOgTags       | Starter     |
| `meta_pixel_id`      | trackingPixels     | Starter     |
| `tiktok_pixel_id`    | trackingPixels     | Starter     |
| `ga4_measurement_id` | trackingPixels     | Starter     |
| `gtm_container_id`   | trackingPixels     | Starter     |
| `geo_targeting`      | geoTargeting       | Pro         |
| `device_targeting`   | deviceTargeting    | Pro         |
| `ab_testing`         | abTesting          | Pro         |
| `short_code`         | nestedSlugs        | Starter     |

## Common errors

| Status | Code                  | When                                                                                                                                                              |
| ------ | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401    | `UNAUTHORIZED`        | The API key is missing, malformed or unknown.                                                                                                                     |
| 402    | `UPGRADE_REQUIRED`    | You set a new value on a field your plan does not include, including a new `short_code` with a `/` on Free.                                                       |
| 403    | `FORBIDDEN`           | The key only has Read permission, or its creator is a viewer in this workspace.                                                                                   |
| 404    | `NOT_FOUND`           | No live link with this id, or `custom_domain_id` is not one of this workspace's domains.                                                                          |
| 409    | `CONFLICT`            | The new `short_code` is already taken on that domain, or it is a reserved name on a Clikso domain.                                                                |
| 422    | `VALIDATION_ERROR`    | A field is malformed or too long (`details.field` names it; a bad `short_code` is named in `details.short_code`), or a folder or tag id is not in this workspace. |
| 422    | `DESTINATION_BLOCKED` | A URL in the body points at a link shortener or a blocked site.                                                                                                   |
| 429    | `RATE_LIMITED`        | The key went over its per-minute request limit.                                                                                                                   |

## Good to know

* This is `PUT`, not `PATCH`, but it behaves like a patch: fields you leave out keep their value.
* `null` clears a plain field: `password: null` removes the password, `folder_id: null` takes the link out of its folder, `expires_at: null` removes the expiry.
* `null` also clears the rule objects: `geo_targeting`, `device_targeting`, `ab_testing`, `og_preview` and `qr_metadata` (since 1.61.1; before that `null` was ignored for them). `{}` (or `[]` for `ab_testing`) still works too. Leaving a field out keeps it.
* `tags` replaces the whole tag list. `tags: []` removes every tag, and `tags: null` (or leaving it out) keeps the tags as they are.
* You can change `short_code` and `destination_url` after creation. The old short URL stops working at once when the code changes. `short_code` follows the same rules as on create: 3 to 30 characters, and `/` for a nested code on Starter and up.
* Setting `status` to `archived` or `expired` stops the short URL from working. Setting it back to `active` turns it on again.
* Keep `title` to 60 characters and `description` to 250, `expires_at` a valid date and `expired_redirect_url` at most 2048 characters, or you get `422` with `details.field` naming the field.
* If your plan was downgraded, a link keeps the paid settings it already has, and you can still edit its other fields. That includes a nested `short_code`: the link keeps working and you can send its current code back unchanged, but you can't change it to a different code with `/`.

---

Source: https://clik.so/docs/api/links/update-link
