> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codeqr.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Express

> Learn how to integrate CodeQR with Express.

## 1. Prerequisites

To follow this guide, you will need to:

* [Create a CodeQR account](https://d.to/try)
* [Create an API key](https://app.codeqr.io/settings/tokens)

## 2. Install and initialize the CodeQR TypeScript SDK

<Steps titleSize="h3">
  <Step title="Install">
    Install the [CodeQR TypeScript SDK](/sdks/typescript) using your preferred package manager:

    <Tabs>
      <Tab title="npm">
        ```bash theme={null}
        npm install @codeqr/ts
        ```
      </Tab>

      <Tab title="yarn">
        ```bash theme={null}
        yarn add @codeqr/ts zod # zod is a peer dependency
        ```
      </Tab>

      <Tab title="pnpm">
        ```bash theme={null}
        pnpm add @codeqr/ts 
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Initialize">
    Then, initialize the CodeQR TypeScript SDK with your API key.

    ```typescript lib/codeqr.ts theme={null}
    import CodeQR from "@codeqr/ts";

    export const codeqr = new CodeQR({
      apiKey: process.env.CODEQR_API_KEY, // optional, defaults to CODEQR_API_KEY env variable
    });
    ```

    You can now use the `codeqr` object to interact with the CodeQR API.

    ```typescript theme={null}
    import { codeqr } from "./lib/codeqr";
    ```
  </Step>
</Steps>

## 3. Create link

Let's create a short link using the [CodeQR TypeScript SDK](/sdks/typescript).

```typescript index.ts theme={null}
app.post("/create-link", async (req: Request, res: Response) => {
  try {
    const result = await codeqr.links.create({
      url: "https://www.google.com",
    });

    res.status(200).json(result);
  } catch (error: any) {
    res.status(400).json(error);
  }
});
```

<Accordion title="Full list of available attributes for the Link model">
  <ParamField body="url" type="string" required>
    The destination URL of the short link.
  </ParamField>

  <ParamField body="domain" type="string">
    The domain of the short link. If not provided, the primary domain for the
    project will be used (or `codeqr.link` if the project has no domains).
  </ParamField>

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

  <ParamField body="externalId" type="string | null">
    This is the ID of the link in your database. If set, it can be used to
    identify the link in the future.
  </ParamField>

  <ParamField body="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.
  </ParamField>

  <ParamField body="prefix" type="string">
    The prefix of the short link slug for randomly-generated keys (e.g. if prefix
    is `/c/`, generated keys will be in the `/c/:key` format). Will be ignored if
    key is provided.
  </ParamField>

  <ParamField body="trackConversion" type="boolean" default={false}>
    Whether to track conversions for the short link.
  </ParamField>

  <ParamField body="identifier" type="string | null">
    The identifier of the short link that is unique across your project. If set,
    it can be used to identify your short link for client-side click tracking.
  </ParamField>

  <ParamField body="archived" type="boolean" default={false}>
    Whether the short link is archived.
  </ParamField>

  <ParamField body="publicStats" type="boolean" default={false}>
    Whether the short link's stats are publicly accessible.
  </ParamField>

  <ParamField body="tagIds" type="string">
    The unique IDs of the tags assigned to the short link.
  </ParamField>

  <ParamField body="tagNames" type="string | string[]">
    The unique name of the tags assigned to the short link (case insensitive).
  </ParamField>

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

  <ParamField body="expiresAt" type="string | null">
    The date and time when the short link will expire at.
  </ParamField>

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

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

  <ParamField body="proxy" type="boolean" default={false}>
    Whether the short link uses Custom Social Media Cards feature.
  </ParamField>

  <ParamField body="title" type="string | null">
    The title of the short link generated via `api.codeqr.io/metatags`. Will be
    used for Custom Social Media Cards if proxy is true.
  </ParamField>

  <ParamField body="description" type="string | null">
    The description of the short link generated via `api.codeqr.io/metatags`. Will
    be used for Custom Social Media Cards if proxy is true.
  </ParamField>

  <ParamField body="image" type="string | null">
    The image of the short link generated via `api.codeqr.io/metatags`. Will be
    used for Custom Social Media Cards if proxy is true.
  </ParamField>

  <ParamField body="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)
  </ParamField>

  <ParamField body="rewrite" type="boolean" default={false}>
    Whether the short link uses link cloaking.
  </ParamField>

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

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

  <ParamField body="doIndex" type="boolean" default={false}>
    Allow search engines to index your short link. Defaults to `false` if not
    provided. Learn more: [https://d.to/noindex](https://d.to/noindex)
  </ParamField>

  <ParamField body="utm_source" type="string | null">
    The UTM source of the short link. If set, this will populate or override the
    UTM source in the destination URL.
  </ParamField>

  <ParamField body="utm_medium" type="string | null">
    The UTM medium of the short link. If set, this will populate or override the
    UTM medium in the destination URL.
  </ParamField>

  <ParamField body="utm_campaign" type="string | null">
    The UTM campaign of the short link. If set, this will populate or override the
    UTM campaign in the destination URL.
  </ParamField>

  <ParamField body="utm_term" type="string | null">
    The UTM term of the short link. If set, this will populate or override the UTM
    term in the destination URL.
  </ParamField>

  <ParamField body="utm_content" type="string | null">
    The UTM content of the short link. If set, this will populate or override the
    UTM content in the destination URL.
  </ParamField>

  <ParamField body="ref" type="string | null">
    The referral tag of the short link. If set, this will populate or override the
    `ref` query parameter in the destination URL.
  </ParamField>

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

  <ParamField body="webhookIds" type="string[] | null">
    An array of webhook IDs to trigger when the link is clicked. These webhooks
    will receive click event data.
  </ParamField>
</Accordion>

Optionally, you can also pass an `externalId` field which is a unique identifier for the link in your own database to associate it with the link in CodeQR's system.

```typescript index.ts theme={null}
app.post("/create-link", async (req: Request, res: Response) => {
  try {
    const result = await codeqr.links.create({
      url: "https://www.google.com",
      externalId: "12345",
    });

    res.status(200).json(result);
  } catch (error: any) {
    res.status(400).json(error);
  }
});
```

This will let you easily [update the link](#5-update-link) or [retrieve analytics](#6-retrieve-analytics-for-link) for it later on using the `externalId` instead of the CodeQR `linkId`.

## 4. Upsert link

CodeQR TypeScript SDK provides a method to upsert a link – where an existing link is updated if it exists, or a new link is created if it doesn't. so you don't have to worry about checking if the link already exists.

```typescript index.ts theme={null}
app.post("/upsert-link", async (req: Request, res: Response) => {
  try {
    // Update the link if same URL already exists or create a new link
    const result = await codeqr.links.upsert({
      url: "https://www.google.com",
    });

    res.status(200).json(result);
  } catch (error: any) {
    res.status(400).json(error);
  }
});
```

This way, you won't have to worry about checking if the link already exists when you're creating it.

## 5. Update link

Let's update an existing link using the CodeQR TypeScript SDK.

You can do that in two ways:

* Using the link's `linkId` in CodeQR's system.
* Using the link's `externalId` in your own database (prefixed with `ext_`).

```typescript index.ts theme={null}
app.post("/update-link", async (req: Request, res: Response) => {
  try {
    // Update a link by its linkId
    const { shortLink } = await codeqr.links.update(
      "link_rWOKByP0bRMrstK8e4HPjprJ",
      {
        url: "https://www.google.uk", // new URL
      }
    );

    // Update a link by its externalId
    const { shortLink } = await codeqr.links.update("ext_12345", {
      url: "https://www.google.uk", // new URL
    });

    res.status(200).json({ shortLink });
  } catch (error: any) {
    res.status(400).json(error);
  }
});
```

## 6. Retrieve analytics for link

CodeQR allows you to retrieve analytics for a link using the CodeQR TypeScript SDK.

```typescript index.ts theme={null}
import { ClicksTimeseries } from "codeqr/models/components";

app.get("/analytics", async (req: Request, res: Response) => {
  try {
    // Retrieve the timeseries analytics for the last 7 days for a link
    const response = await codeqr.analytics.retrieve({
      linkId: "clv3o9p9q000au1h0mc7r6l63",
      interval: "7d",
      groupBy: "timeseries",
    });

    const timeseries = response as ClicksTimeseries[];

    res.status(200).json(timeseries);
  } catch (error: any) {
    res.status(400).json(error);
  }
});
```

Similarly, you can retrieve analytics for a link using the `externalId` field.

```typescript index.ts theme={null}
// Retrieve the timeseries analytics for the last 7 days for a link
const response = await codeqr.analytics.retrieve({
  externalId: "ext_12345",
  interval: "7d",
  groupBy: "timeseries",
});

const timeseries = response as ClicksTimeseries[];
```

## 7. Examples

<CardGroup cols={2}>
  <Card title="Express Example" icon="github" href="https://github.com/codeqr-io/examples/tree/main/typescript/express" color="#333333">
    See the full example on GitHub.
  </Card>
</CardGroup>
