---
name: unified-api
description: >-
  Build against the Unified.to API — the REST fundamentals shared by every
  category (CRM, ATS, HRIS, accounting, commerce, messaging, ticketing, and
  more). Use when a coding task calls the Unified.to API directly and needs the
  request shape, authentication, connections, pagination, filtering, field
  selection, and error handling that apply across all 389+ integrations.
license: MIT
metadata:
  category: api
  api_base: https://api.unified.to
  docs: https://docs.unified.to/reference/rest
---

# Build against the Unified.to API

Unified.to puts one REST API and one data model in front of 389+ integrations.
Address a specific customer's connected app with a `connection_id`; Unified.to
maps the unified request to that provider's native API. Learn the shape once and
it works for every provider in a category. This skill teaches an agent the
fundamentals that every category API shares.

## When to use this skill

Use this skill when the task is to:

- Call the Unified.to REST API directly for any category
- Authenticate requests and resolve a `connection_id`
- List, retrieve, create, update, or delete unified records
- Page, filter, sort, or trim responses across providers
- Handle errors and per-provider capability differences

For category-specific object shapes, also load the matching skill (e.g.
`unified-crm`, `unified-ats-jobboard`, `unified-accounting-invoicing`).

## Prefer an SDK

For most code, use an official SDK over hand-rolled HTTP — it is typed, handles
auth, and matches this data model exactly.

```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: 20 });
```

SDKs for Python, PHP, Java, Go, C#, and Ruby: https://docs.unified.to/reference/sdks.
Fall back to raw REST (below) when no SDK is available.

## Prerequisites

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

## Core concepts

- **Workspace API key** — authenticates every call. Sent as a Bearer token.
- **Connection** — one authorized link between a workspace and a customer's app
  instance. Its `id` is the `connection_id` in every data path. List connections
  with `GET /unified/connection`.
- **Category** — the object family: `crm`, `ats`, `hris`, `accounting`,
  `commerce`, `messaging`, `ticketing`, `lms`, `calendar`, and more.
- **Object** — the resource within a category: `contact`, `deal`, `candidate`,
  `invoice`, `message`, …

## Base URL

Pick the data center the workspace lives in:

- NA (default) — `https://api.unified.to`
- EU — `https://api-eu.unified.to`
- AU — `https://api-au.unified.to`

## Request shape

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

Authenticate every request:

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

| Operation | Method & path                                     |
| --------- | ------------------------------------------------- |
| List      | `GET    /{category}/{connection_id}/{object}`      |
| Retrieve  | `GET    /{category}/{connection_id}/{object}/{id}` |
| Create    | `POST   /{category}/{connection_id}/{object}`      |
| Update    | `PATCH  /{category}/{connection_id}/{object}/{id}` |
| Delete    | `DELETE /{category}/{connection_id}/{object}/{id}` |

Update is idempotent — safe to retry. When creating with `POST`, don't blindly
retry a timeout without first listing to check whether the record landed.

```bash
curl https://api.unified.to/crm/CONNECTION_ID/contact?limit=20 \
  -H "Authorization: Bearer $UNIFIED_API_KEY"
```

## Discovering data (start here)

You cannot guess IDs. Always begin from a **list** endpoint to find records, then
use the returned `id` for retrieve/update/delete.

## Listing: filter first, then page

Filtering narrows the result set before pagination; reach for filters before
paging through everything.

- **Per-resource filters** — self-documenting, e.g. `?company_id=...`,
  `?contact_id=...`, `?type=...`. The available filters are listed per endpoint in
  the API reference.
- `query=` — free-text search (e.g. an email or name) where the provider supports it.
- `updated_gte=YYYY-MM-DDTHH:MM:SSZ` — return only records updated at/after this
  time (ideal for incremental sync).
- `limit` (max 100) and `offset` (zero-based) — page through results.
- `sort` (`name`, `created_at`, `updated_at`) and `order` (`asc` / `desc`).

A returned count `< limit` means you are on the last page. List responses are a
JSON array of objects. See https://docs.unified.to/reference/pagination.

## Field selection & the `raw` field

Responses omit the bulky provider-specific `raw` blob by default. Request only
the fields you need with `fields=` (a comma-delimited allow-list) to cut response
size and token cost. To include the provider payload, request `fields=raw`, or
pull nested values with `fields=raw.some_field`.

## Not every provider supports every operation

An object, field, or operation valid in the unified model may be unsupported by a
given provider. Check the **Feature Support** tab on the integration page in
`app.unified.to`; a `501` response means the operation is unsupported. Treat
capability as per-connection, not per-category.

## Error handling

| Code | Meaning & action                                       |
| ---- | ------------------------------------------------------ |
| 400  | Validation error — check the message for the field.    |
| 401  | Connection broken or bad key — re-authorize the user.  |
| 403  | Missing scopes / IP restriction — fix app + scopes.    |
| 404  | Record not found.                                      |
| 429  | Provider rate limit — back off; prefer webhook sync.   |
| 501  | Operation unsupported by provider — check Feature Support. |

## Keeping data in sync (recommended)

- Register **webhooks** 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, provider-independent queries.

## References

- REST basics: https://docs.unified.to/reference/rest
- Pagination & filtering: https://docs.unified.to/reference/pagination
- SDKs: https://docs.unified.to/reference/sdks
- Webhooks: https://docs.unified.to/reference/webhooks
- Embedded components (connections): https://docs.unified.to/concepts/embedded-components
