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

# Sync your data

> Create and keep companies, deals, and people in sync with your own systems.

Most integrations start by pushing your firm's data into Metal: the companies you track, the deals in your pipeline, and the people you know. This guide shows how to create records and keep them current as your source systems change.

## Pick an identifier strategy first

Before you write any data, decide how you'll reconcile Metal records with your source system. Every resource has a Metal-assigned `id`, but you can attach your own identifiers so you never have to store a mapping table.

| Field               | Use it for                                                             |
| ------------------- | ---------------------------------------------------------------------- |
| `externalId`        | A single stable identifier you control (for example, a CRM record ID). |
| `externalReference` | A structured reference to a source system when one ID isn't enough.    |

<Tip>
  Set `externalId` on create. It lets you fetch, update, and de-duplicate records later without tracking Metal's `id` yourself. See the [data model](/concepts/data-model) for the full field reference.
</Tip>

## Create records

A company needs only a `canonicalName`. Supply a `website` when you have one — it dramatically improves [enrichment](/guides/enrich-companies) accuracy.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST https://api.metal.ai/v1/companies \
  -H "x-metal-client-id: $METAL_CLIENT_ID" \
  -H "x-metal-api-key: $METAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "canonicalName": "Acme Industrials",
    "website": "https://acme.example",
    "externalId": "crm-12345"
  }'
```

Deals point at a target company through `companyId`, and people link to a company through `company`:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST https://api.metal.ai/v1/deals \
  -H "x-metal-client-id: $METAL_CLIENT_ID" \
  -H "x-metal-api-key: $METAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme — Project Forge",
    "companyId": "665f1c2a9b1e4a0012a3b4c5",
    "externalId": "crm-deal-987"
  }'
```

## Keep records in sync

When a record changes in your system, update it in Metal. You can address a record by Metal `id` or by the `externalId` you set on create.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Update by Metal id
curl -X PUT https://api.metal.ai/v1/companies/665f1c2a9b1e4a0012a3b4c5 \
  -H "x-metal-client-id: $METAL_CLIENT_ID" \
  -H "x-metal-api-key: $METAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "shortDescription": "Maker of factory automation hardware." }'

# Look up by your external id
curl "https://api.metal.ai/v1/companies/externalId=crm-12345" \
  -H "x-metal-client-id: $METAL_CLIENT_ID" \
  -H "x-metal-api-key: $METAL_API_KEY"
```

## Build an upsert loop

For an ongoing sync, fetch by `externalId`, then create the record if it's missing or update it if it exists. This keeps the job idempotent — safe to re-run without creating duplicates.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
import requests

BASE = "https://api.metal.ai/v1"
headers = {
    "x-metal-client-id": os.environ["METAL_CLIENT_ID"],
    "x-metal-api-key": os.environ["METAL_API_KEY"],
    "Content-Type": "application/json",
}

def upsert_company(record):
    ext = record["externalId"]
    existing = requests.get(f"{BASE}/companies/externalId={ext}", headers=headers)
    if existing.status_code == 200:
        company_id = existing.json()["data"]["id"]
        return requests.put(f"{BASE}/companies/{company_id}", headers=headers, json=record)
    return requests.post(f"{BASE}/companies", headers=headers, json=record)
```

<Note>
  Sync jobs make many calls in a row. Handle [rate limits](/guides/rate-limits) with backoff, and check [errors](/guides/errors) before reading a response body.
</Note>

## Next steps

<CardGroup cols={2}>
  <Card title="Enrich what you sync" icon="sparkles" href="/guides/enrich-companies">
    Fill in firmographics and financials after creating records.
  </Card>

  <Card title="Organize into lists" icon="list" href="/guides/manage-lists">
    Group synced records to work with them in bulk.
  </Card>
</CardGroup>
