> ## Documentation Index
> Fetch the complete documentation index at: https://speakeasy-20cf8bdf.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction

> Learn how to use Dub's links to track and analyze your marketing campaigns.

Links are the bread and butter of [Dub](https://dub.co).

Everything on Dub starts with a link. Whether you're creating:

* a handful of links for your marketing campaign
* hundreds of links for your affiliate program
* thousands of links, [programmatically](/api-reference/endpoint/bulk-create-links), for your SMS campaign

In this guide, we'll cover the link model, how to create links, and more.

## The link model

The link model consists of the following properties:

| Property    | Description                                               | Example                         |
| ----------- | :-------------------------------------------------------- | :------------------------------ |
| `id`        | The unique identifier of the link (prefixed with `link_`) | `link_eBKA4MT44XnI17hYLchkjUOd` |
| `url`       | The destination URL of the link                           | `https://dub.co/home`           |
| `shortLink` | The shortened version of the link (including https)       | `https://dub.link/claim`        |
| `domain`    | The domain of the link                                    | `dub.link`                      |
| `key`       | The short link slug                                       | `claim`                         |

For more advanced features like [custom link previews](https://dub.co/help/article/custom-link-previews), [conversion tracking](/conversions/quickstart), and more, see the full list of properties below;

<Accordion title="Full list of link properties">
  <ResponseField name="id" type="string" required>
    The unique ID of the short link. Prefixed with `link_`.
  </ResponseField>

  <ResponseField name="domain" type="string" required>
    The domain of the short link. If not provided, the primary domain for the
    workspace will be used (or dub.sh if the workspace has no domains).
  </ResponseField>

  <ResponseField name="key" type="string" required>
    The short link slug. If not provided, a random 7-character slug will be
    generated.
  </ResponseField>

  <ResponseField name="url" type="string" required>
    The destination URL of the short link.
  </ResponseField>

  <ResponseField name="shortLink" type="string" required>
    The full URL of the short link, including the https protocol (e.g.
    `https://d.to/try`).
  </ResponseField>

  <ResponseField name="trackConversion" type="boolean" default="false">
    Whether to track conversions for the short link.
  </ResponseField>

  <ResponseField name="externalId" type="string | null">
    The ID of the link in your database. If set, it can be used to identify the
    link in future API requests (must be prefixed with `ext_` when passed as a
    query parameter). This key is unique across your workspace.
  </ResponseField>

  <ResponseField name="tenantId" type="string | null">
    The ID of the tenant that created the link inside your system. If set, it can
    be used to fetch all links for a tenant.
  </ResponseField>

  <ResponseField name="archived" type="boolean" required default="false">
    Whether the short link is archived.
  </ResponseField>

  <ResponseField name="expiresAt" type="string | null">
    The date and time when the short link will expire in ISO-8601 format.
  </ResponseField>

  <ResponseField name="expiredUrl" type="string | null">
    The URL to redirect to when the short link has expired.
  </ResponseField>

  <ResponseField name="password" type="string | null">
    The password required to access the destination URL of the short link.
  </ResponseField>

  <ResponseField name="proxy" type="boolean" required default="false">
    Whether the short link uses Custom Social Media Cards feature.
  </ResponseField>

  <ResponseField name="title" type="string | null">
    The title of the short link generated via api.dub.co/metatags. Will be used
    for Custom Social Media Cards if proxy is true.
  </ResponseField>

  <ResponseField name="description" type="string | null">
    The description of the short link generated via api.dub.co/metatags. Will be
    used for Custom Social Media Cards if proxy is true.
  </ResponseField>

  <ResponseField name="image" type="string | null">
    The image of the short link generated via api.dub.co/metatags. Will be used
    for Custom Social Media Cards if proxy is true.
  </ResponseField>

  <ResponseField name="video" type="string | null">
    The custom link preview video (og:video). Will be used for Custom Social Media
    Cards if `proxy` is true. Learn more: [https://d.to/og](https://d.to/og)
  </ResponseField>

  <ResponseField name="rewrite" type="boolean" required default="false">
    Whether the short link uses link cloaking.
  </ResponseField>

  <ResponseField name="doIndex" type="boolean" required default="false">
    Whether to allow search engines to index the short link.
  </ResponseField>

  <ResponseField name="ios" type="string | null">
    The iOS destination URL for the short link for iOS device targeting.
  </ResponseField>

  <ResponseField name="android" type="string | null">
    The Android destination URL for the short link for Android device targeting.
  </ResponseField>

  <ResponseField name="publicStats" type="boolean" required default="false">
    Whether the short link's stats are publicly accessible.
  </ResponseField>

  <ResponseField name="tags" type="object[] | null">
    The tags assigned to the short link.

    <Expandable title="properties">
      <ResponseField name="tags.id" type="string">
        The unique ID of the tag.
      </ResponseField>

      <ResponseField name="tags.name" type="string">
        The name of the tag.
      </ResponseField>

      <ResponseField name="tags.color" type="string">
        The color of the tag.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="webhookIds" type="string[]">
    The IDs of the webhooks that the short link is associated with.
  </ResponseField>

  <ResponseField name="comments" type="string | null">
    The comments for the short link.
  </ResponseField>

  <ResponseField name="qrCode" type="string">
    The full URL of the QR code for the short link (e.g.
    `https://api.dub.co/qr?url=https://d.to/try`).
  </ResponseField>

  <ResponseField name="utm_source" type="string | null">
    The UTM source of the short link.
  </ResponseField>

  <ResponseField name="utm_medium" type="string | null">
    The UTM medium of the short link.
  </ResponseField>

  <ResponseField name="utm_campaign" type="string | null">
    The UTM campaign of the short link.
  </ResponseField>

  <ResponseField name="utm_term" type="string | null">
    The UTM term of the short link.
  </ResponseField>

  <ResponseField name="utm_content" type="string | null">
    The UTM content of the short link.
  </ResponseField>

  <ResponseField name="userId" type="string">
    The user ID of the creator of the short link.
  </ResponseField>

  <ResponseField name="workspaceId" type="string">
    The workspace ID of the short link.
  </ResponseField>

  <ResponseField name="clicks" type="number" required default="0">
    The number of clicks on the short link.
  </ResponseField>

  <ResponseField name="leads" type="number" required default="0">
    The number of leads the short link has generated.
  </ResponseField>

  <ResponseField name="sales" type="number" required default="0">
    The number of sales the short link has generated.
  </ResponseField>

  <ResponseField name="saleAmount" type="number" required default="0">
    The total dollar amount of sales the short link has generated (in cents).
  </ResponseField>

  <ResponseField name="lastClicked" type="string | null">
    The date and time when the short link was last clicked.
  </ResponseField>

  <ResponseField name="createdAt" type="string">
    The date and time when the short link was created.
  </ResponseField>

  <ResponseField name="updatedAt" type="string">
    The date and time when the short link was last updated.
  </ResponseField>

  <ResponseField name="programId" type="string | null">
    The ID of the program the short link is associated with.
  </ResponseField>
</Accordion>

You can use the various Dub SDKs to programmatically manage your links.

## Create a link

The `url` field, representing the destination URL, is the sole mandatory parameter required for the creation of a new short link.

<CodeGroup>
  ```javascript Node.js theme={null}
  import { Dub } from "dub";

  export const dub = new Dub({
    token: process.env.DUB_API_KEY,
  });

  const link = await dub.links.create({
    url: "https://google.com",
  });
  ```

  ```go Go theme={null}
  package main

  import(
    "context"
    dubgo "github.com/dubinc/dub-go"
    "github.com/dubinc/dub-go/models/operations"
    "log"
    "os"
  )

  func main() {
    ctx := context.Background()

    s := dubgo.New(
      dubgo.WithSecurity(os.Getenv("DUB_API_KEY")),
    )

    res, err := s.Links.Create(ctx, &operations.CreateLinkRequestBody{
      URL: "https://google.com",
    })

    if err != nil {
      log.Fatal(err)
    }

    if res != nil {
      // handle response
    }
  }
  ```

  ```python Python theme={null}
  import os
  import dub
  from dub.models import operations

  d = dub.Dub(
    token=os.environ['DUB_API_KEY'],
  )

  res = d.links.create(request={
    "url": "https://google.com",
  })
  ```

  ```ruby Ruby theme={null}
  require 'dub'

  s = ::OpenApiSDK::Dub.new
  s.config_security(
    ::OpenApiSDK::Shared::Security.new(
      token: "DUB_API_KEY",
    )
  )

  req = ::OpenApiSDK::Operations::CreateLinkRequestBody.new(
    url: "https://google.com",
  )
  ```

  ```php PHP theme={null}
  declare(strict_types=1);

  require 'vendor/autoload.php';

  use Dub;
  use Dub\Models\Operations;

  $sdk = Dub\Dub::builder()->setSecurity('DUB_API_KEY')->build();

  $request = new Operations\CreateLinkRequestBody(
    url: 'https://google.com',
  );

  $response = $sdk->links->create(
    request: $request
  );
  ```

  ```bash cURL {5} theme={null}
  curl --request POST \
    --url https://api.dub.co/links \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{"url": "https://google.com"}'
  ```
</CodeGroup>

## Update a link

An existing link can be updated by providing the `id` to the `update` method. This method returns the updated link as a response.

You can use either the `linkId` or an `externalId` prefixed with `ext_` which is a unique identifier for the link in your own database to associate it with the link in Dub's system.

<CodeGroup>
  ```javascript Node.js theme={null}
  import { Dub } from "dub";

  export const dub = new Dub({
    token: process.env.DUB_API_KEY,
  });

  const link = await dub.links.update("link_eBKA4MT44XnI17hYLchkjUOd", {
    url: "https://www.google.uk", // new URL
  });
  ```

  ```go Go theme={null}
  package main

  import(
    "context"
    dubgo "github.com/dubinc/dub-go"
    "github.com/dubinc/dub-go/models/operations"
    "log"
    "os"
  )

  func main() {
    ctx := context.Background()

    s := dubgo.New(
      dubgo.WithSecurity(os.Getenv("DUB_API_KEY")),
    )

    res, err := s.Links.Update(ctx, "link_eBKA4MT44XnI17hYLchkjUOd", &operations.UpdateLinkRequestBody{
      URL: "https://www.google.uk", // new URL
    })

    if err != nil {
      log.Fatal(err)
    }

    if res != nil {
      // handle response
    }
  }
  ```

  ```python Python theme={null}
  import os
  import dub
  from dub.models import operations

  d = dub.Dub(
    token=os.environ['DUB_API_KEY'],
  )

  res = dub.links.update(link_id="link_eBKA4MT44XnI17hYLchkjUOd", request_body={
    "url": "https://www.google.uk", // new URL
  })
  ```

  ```ruby Ruby theme={null}
  require 'dub'

  s = ::OpenApiSDK::Dub.new
  s.config_security(
    ::OpenApiSDK::Shared::Security.new(
      token: "DUB_API_KEY",
    )
  )

  res = s.links.update(link_id="link_eBKA4MT44XnI17hYLchkjUOd", request_body={
    "url": "https://www.google.uk", // new URL
  })
  ```

  ```php PHP theme={null}
  declare(strict_types=1);

  require 'vendor/autoload.php';

  use Dub;
  use Dub\Models\Operations;

  $sdk = Dub\Dub::builder()->setSecurity('DUB_API_KEY')->build();

  $requestBody = new Operations\UpdateLinkRequestBody(
    url: 'https://www.google.uk', // new URL
  );

  $response = $sdk->links->update(
    linkId: 'link_eBKA4MT44XnI17hYLchkjUOd',
    requestBody: $requestBody
  );
  ```

  ```bash cURL theme={null}
  curl --request PATCH \
    --url https://api.dub.co/links/link_eBKA4MT44XnI17hYLchkjUOd \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{"url": "https://www.google.uk"}'
  ```
</CodeGroup>

## Upsert a link

Upserting a link is a combination of creating and updating a link. If a link with the same URL already exists, return it (or update it if there are any changes). Otherwise, a new link will be created.

This allows you to use the upsert method without the necessity of checking for the link's existence beforehand.

<CodeGroup>
  ```javascript Node.js theme={null}
  import { Dub } from "dub";

  export const dub = new Dub({
    token: process.env.DUB_API_KEY,
  });

  const link = await dub.links.upsert({
    url: "https://google.com", // will always be the same short link
  });
  ```

  ```go Go theme={null}
  package main

  import(
    "context"
    dubgo "github.com/dubinc/dub-go"
    "github.com/dubinc/dub-go/models/operations"
    "log"
    "os"
  )

  func main() {
    ctx := context.Background()

    s := dubgo.New(
      dubgo.WithSecurity(os.Getenv("DUB_API_KEY")),
    )

    res, err := s.Links.Upsert(ctx, &operations.UpsertLinkRequestBody{
      URL: "https://google.com",
    })

    if err != nil {
      log.Fatal(err)
    }

    if res != nil {
      // handle response
    }
  }
  ```

  ```python Python theme={null}
  import os
  import dub
  from dub.models import operations

  d = dub.Dub(
    token=os.environ['DUB_API_KEY'],
  )

  res = d.links.upsert(request={
    "url": "https://google.com",
  })
  ```

  ```ruby Ruby theme={null}
  require 'dub'

  s = ::OpenApiSDK::Dub.new
  s.config_security(
    ::OpenApiSDK::Shared::Security.new(
      token: "DUB_API_KEY",
    )
  )

  req = ::OpenApiSDK::Operations::UpsertLinkRequestBody.new(
    url: "https://google.com",
  )
  ```

  ```php PHP theme={null}
  declare(strict_types=1);

  require 'vendor/autoload.php';

  use Dub;
  use Dub\Models\Operations;

  $sdk = Dub\Dub::builder()->setSecurity('DUB_API_KEY')->build();

  $request = new Operations\UpsertLinkRequestBody(
    url: 'https://google.com',
  );

  $response = $sdk->links->upsert(
    request: $request
  );
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.dub.co/links/upsert \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{"url": "https://google.com"}'
  ```
</CodeGroup>
