# API: CRM sync

| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | `/v1/connections/:id/crm-sync/field-maps` | Field maps for a CRM connection: local field ↔ CRM field, direction and precedence per field | `connections:read` |
| PATCH | `/v1/connections/:id/crm-sync/field-maps` | Add or change field maps (keyed by object_type + local_field); remove: true deletes one (web app only) | `connections:write` |
| GET | `/v1/connections/:id/crm-sync/outbox` | Pushes to the CRM (newest first), filterable by status | `connections:read` |
| POST | `/v1/connections/:id/crm-sync/push/:pushId/approve` | Approve a CRM write waiting for approval (an agent's change). Policy evaluates it as you; values changed since it was held are dropped. A held overlay change is written to the CRM, then applied here. (web app only) | `connections:write` |
| POST | `/v1/connections/:id/crm-sync/push/:pushId/dismiss` | Dismiss a failed or held CRM change: it's never sent. A write-through change stays unapplied here; a lead conversion stays converted here. A person's decision: web sessions only. (web app only) | `connections:write` |
| POST | `/v1/connections/:id/crm-sync/push/:pushId/retry` | Retry a blocked, waiting-for-approval or failed push now. Policy evaluates it as you (a person approving it). (web app only) | `connections:write` |
| PATCH | `/v1/connections/:id/crm-sync/settings` | Sync mode (sync: two-way parallel run; overlay: write-through, the CRM is the system of record; migrate: pull only until cut-over) and sync options (web app only) | `connections:write` |
| GET | `/v1/connections/:id/crm-sync/status` | Sync status: mode, cursors, outbox counts by status, open conflicts, p50/p95 pull and push lag over 24 hours (with the published target), last errors | `connections:read` |
| GET | `/v1/crm-sync/conflicts` | Fields both sides changed whose precedence is review (newest first). Filters: status (default open), connection_id, record_id, object_type, field | `connections:read` |
| POST | `/v1/crm-sync/conflicts/:id/resolve` | Resolve a conflict: local (push this app's value), external (take the CRM's value) or value (write a new value here and push it). A person's decision: web sessions only. (web app only) | `connections:write` |

## Examples

### GET /v1/connections/$ID/crm-sync/field-maps

Field maps for a CRM connection: local field ↔ CRM field, direction and precedence per field

```bash
curl -s "https://api.closefinch.com/v1/connections/$ID/crm-sync/field-maps" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/connections/${id}/crm-sync/field-maps`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/connections/$ID/crm-sync/outbox

Pushes to the CRM (newest first), filterable by status

```bash
curl -s "https://api.closefinch.com/v1/connections/$ID/crm-sync/outbox" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/connections/${id}/crm-sync/outbox`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/connections/$ID/crm-sync/status

Sync status: mode, cursors, outbox counts by status, open conflicts, p50/p95 pull and push lag over 24 hours (with the published target), last errors

```bash
curl -s "https://api.closefinch.com/v1/connections/$ID/crm-sync/status" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/connections/${id}/crm-sync/status`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/crm-sync/conflicts

Fields both sides changed whose precedence is review (newest first). Filters: status (default open), connection_id, record_id, object_type, field

```bash
curl -s "https://api.closefinch.com/v1/crm-sync/conflicts" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/crm-sync/conflicts`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

Request and response schemas: [https://www.closefinch.com/openapi.json](https://www.closefinch.com/openapi.json). All resources: [API reference](https://www.closefinch.com/docs/api).
