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

# Unify TypeScript library

> Install and use the official Unify TypeScript library.

## Overview

Unify provides an official TypeScript library that makes it easy to interact
with the Unify API from your code. The library handles authentication, request
formatting, and response parsing so you can focus on building your integration.

<Info>
  The TypeScript library source code is [available on GitHub](https://github.com/unifygtm/sdk-typescript).
</Info>

## Quick start

<Warning>
  The Unify TypeScript SDK provides **server-side** access to the Unify API. For
  client-side integrations or environments where the API key is exposed, use the
  [Intent Client](/developers/intent-client/overview) instead.
</Warning>

You can install the Unify TypeScript library with your preferred package
manager:

<CodeGroup>
  ```shell npm theme={null}
  npm install @unifygtm/sdk
  ```

  ```shell yarn theme={null}
  yarn add @unifygtm/sdk
  ```

  ```shell pnpm theme={null}
  pnpm add @unifygtm/sdk
  ```

  ```shell bun theme={null}
  bun add @unifygtm/sdk
  ```
</CodeGroup>

Generate an API key in [Settings → Developers](https://app.unifygtm.com/dashboard/settings/integrations/api-keys)
and then initialize the client:

```typescript theme={null}
import Unify from '@unifygtm/sdk';

const client = new Unify({
  // This is the default and can be omitted
  apiKey: process.env['UNIFY_API_KEY'],
});

const objects = await client.data.objects.list();
console.log(objects.data);
```

<Note>
  The TypeScript library reads the `UNIFY_API_KEY` environment variable by
  default. If the variable is set, you can omit the `apiKey` parameter when
  initializing the client.
</Note>

## Usage

<AccordionGroup>
  <Accordion title="List objects">
    Retrieve all objects in your Unify workspace to see what's available:

    ```typescript TypeScript theme={null}
    import Unify from '@unifygtm/sdk';

    const client = new Unify();

    const objects = await client.data.objects.list();

    for (const obj of objects.data) {
      console.log(`${obj.api_name} (${obj.display_name})`);
    }
    ```

    ```text theme={null}
    company (Company)
    person (Person)
    opportunity (Opportunity)
    ...
    ```
  </Accordion>

  <Accordion title="List attributes on an object">
    Retrieve the attributes defined on a specific object to understand its schema:

    ```typescript TypeScript theme={null}
    const attributes = await client.data.attributes.list('person');

    for (const attr of attributes.data) {
      console.log(`${attr.api_name} — ${attr.type} (required: ${attr.is_required})`);
    }
    ```

    ```text theme={null}
    email — Text (required: true)
    first_name — Text (required: false)
    last_name — Text (required: false)
    title — Text (required: false)
    company — Reference (required: false)
    ...
    ```
  </Accordion>

  <Accordion title="Upsert a person record">
    Use the upsert endpoint to create a new record or update an existing one based
    on a unique attribute. This is the recommended approach for syncing data into
    Unify because it handles deduplication automatically.

    ```typescript TypeScript theme={null}
    const record = await client.data.records.upsert('person', {
      match: {
        email: 'jane@acme.com',
      },
      create_or_update: {
        email: 'jane@acme.com',
        first_name: 'Jane',
        last_name: 'Smith',
        title: 'Head of Growth',
        company: {
          match: {
            domain: 'acme.com',
          },
          create_or_update_if_empty: {
            domain: 'acme.com',
            name: 'Acme Corp',
          },
        },
      },
    });

    console.log(`Record ID: ${record.data.id}`);
    console.log(`Created at: ${record.data.created_at}`);
    console.log(`Updated at: ${record.data.updated_at}`);
    ```

    ```text theme={null}
    Record ID: b0fdcba7-a8e5-4fa3-abb0-26ee20f5ba47
    Created at: 2025-04-15T14:30:00Z
    Updated at: 2025-04-15T14:30:00Z
    ```

    Running this again with updated attributes (for example, a new title) will
    update the existing record rather than creating a duplicate, because `email` is
    used as the match key.
  </Accordion>

  <Accordion title="Find a record by unique attribute">
    If you know the value of a unique attribute (like an email address), you can
    look up the record directly without needing the record ID:

    ```typescript TypeScript theme={null}
    const record = await client.data.records.findUnique('person', {
      match: {
        email: 'jane@acme.com',
      },
    });

    console.log(`Record ID: ${record.data.id}`);
    console.log(`Name: ${record.data.attributes.first_name} ${record.data.attributes.last_name}`);
    console.log(`Title: ${record.data.attributes.title}`);
    ```

    ```text theme={null}
    Record ID: b0fdcba7-a8e5-4fa3-abb0-26ee20f5ba47
    Name: Jane Smith
    Title: Head of Growth
    ```
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Send records via API" href="/developers/guides/send-data/overview" icon="rocket" horizontal>
    Send data from external tools and systems via API.
  </Card>

  <Card title="Data API reference" href="/developers/api/data/overview" icon="book" horizontal>
    Explore the full Data API reference.
  </Card>
</CardGroup>
