---
name: unified-crm
description: >-
  Build CRM and sales-automation features against many CRMs (HubSpot,
  Salesforce, Pipedrive, Zoho, HighLevel, and more) through the single
  Unified.to CRM API. Use when a coding task involves reading or writing
  contacts, companies, deals, leads, or pipelines, or two-way syncing sales data
  across one or more CRM platforms.
license: MIT
metadata:
  category: crm
  api_base: https://api.unified.to
  docs: https://docs.unified.to/crm/overview
---

# Build a CRM / sales-sync app with the Unified.to CRM API

Unified.to normalizes many CRMs behind one REST API. Write your CRM integration
once and it works across every supported platform. This skill teaches an agent
how to build against the Unified CRM API.

## When to use this skill

Use this skill when the task is to:

- Read or write contacts and companies
- Manage deals and pipelines (create, move stage, close)
- Capture and route leads
- Two-way sync sales data across more than one CRM

## Prerequisites

1. A Unified.to workspace with an **API key** and **Workspace ID**
   (`app.unified.to` → Settings → API Keys).
2. An activated CRM integration (e.g. HubSpot) — start in the Sandbox.
3. A **connection ID** from the embedded Authorization component
   (https://docs.unified.to/concepts/embedded-components).

Keep the API key server-side only.

## Core request pattern

```
https://api.unified.to/crm/{connection_id}/{object}
```

Authenticate every request:

```
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

Regional base URLs: `api.unified.to` (NA), `api-eu.unified.to` (EU),
`api-au.unified.to` (AU).

## Data objects

| Object     | Purpose                                     |
| ---------- | ------------------------------------------- |
| `contact`  | A person                                    |
| `company`  | An organization / account                   |
| `deal`     | A deal / opportunity                        |
| `lead`     | A lead                                      |
| `pipeline` | A sales pipeline and its stages             |
| `event`    | An activity/event logged against a record   |
| `picklist` | Enumerated field options (read-only)        |

### Supported operations (contact shown; others follow the same shape)

| Method   | Path                         | Description        |
| -------- | ---------------------------- | ------------------ |
| `GET`    | `/crm/{cid}/contact`         | List contacts      |
| `GET`    | `/crm/{cid}/contact/{id}`    | Get one contact    |
| `POST`   | `/crm/{cid}/contact`         | Create a contact   |
| `PATCH`  | `/crm/{cid}/contact/{id}`    | Update a contact   |
| `DELETE` | `/crm/{cid}/contact/{id}`    | Delete a contact   |

The same verbs apply to `company`, `deal`, `lead`, `pipeline`, and `event`.
`picklist` is read-only.

Not every CRM supports every object or field. Check the **Feature Support** tab
on the integration page in `app.unified.to`; a `501` response means the
operation is unsupported.

## Pagination, filtering & sorting

- `limit` (max 100) and `offset` (zero-based) for paging.
- `updated_gte=YYYY-MM-DDTHH:MM:SSZ` for incremental sync.
- `query=` filters by name or email (integration-specific).
- `sort` (`created_at`, `updated_at`, `name`) + `order` (`asc` / `desc`).

Returned count `< limit` means you are on the last page.

## Example: read and create contacts (fetch)

```javascript
const BASE = 'https://api.unified.to';
const headers = {
    Authorization: `Bearer ${process.env.UNIFIED_API_KEY}`,
    'Content-Type': 'application/json',
};

// List recently updated contacts for a sync
const list = await fetch(
    `${BASE}/crm/${connectionId}/contact?updated_gte=2025-01-01T00:00:00Z&limit=100`,
    { headers }
);
const contacts = await list.json();

// Create a contact
await fetch(`${BASE}/crm/${connectionId}/contact`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
        name: 'Grace Hopper',
        emails: [{ email: 'grace@example.com' }],
        telephones: [{ telephone: '+1-555-0100', type: 'WORK' }],
    }),
});
```

Field names differ slightly by CRM; consult the contact data model at
https://docs.unified.to/crm/contact/model for the canonical fields.

## Example: with the official SDK

```bash
npm install @unified-api/typescript-sdk
```

```typescript
import { UnifiedTo } from '@unified-api/typescript-sdk';

const unified = new UnifiedTo({ security: { jwt: process.env.UNIFIED_API_KEY! } });

const { crmContacts } = await unified.crm.listCrmContacts({ connectionId, limit: 100 });
```

SDKs for Python, PHP, Java, Go, C#, and Ruby: https://docs.unified.to/reference/sdks.

## Keeping data in sync (recommended)

- Register **webhooks** for `contact`, `company`, `deal`, and `lead` events and
  upsert by `id`. See https://docs.unified.to/reference/webhooks and
  https://docs.unified.to/concepts/virtual_webhooks.
- Sync into your own database for fast, consistent, CRM-independent queries.

## Error handling

| Code | Meaning & action                                            |
| ---- | ----------------------------------------------------------- |
| 401  | Connection broken — re-authorize the end-user.              |
| 403  | Missing scopes — fix provider app + Unified.to scopes.      |
| 429  | Provider rate limit — back off; prefer webhook sync.        |
| 501  | Operation unsupported by CRM — check Feature Support.       |

## References

- CRM API overview & data model: https://docs.unified.to/crm/overview
- Contact data model: https://docs.unified.to/crm/contact/model
- REST basics: https://docs.unified.to/reference/rest
- Pagination & filtering: https://docs.unified.to/reference/pagination
