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

# Limitations

> Real constraints of the v1.0 adapter. Read this before you build — some affect how you model currency, contacts, and deletes.

These are constraints of the canonical model that ingests your data. Each is deliberate;
each has a consequence you should design around. None of them is a bug — they are the shape
of v1.0.

## Currency is not stored

A lead's `price` is stored as a **plain integer with no currency**. The `currency` field you
send is dropped from the mapped columns (it survives only in the raw copy, which analytics
do not read).

<Warning>
  **Consequence:** a connection is effectively **single-currency**. If your leads mix
  currencies, HunterAI sums them as one unit — a `1000` USD deal and a `1000` UZS deal both
  count as `1000`. Revenue totals, averages, and goal progress will be wrong.

  **Design around it:** send `price` in one consistent currency per connection. If you
  operate in several currencies and need correct totals, convert to a single reporting
  currency before sending, or raise a multi-currency requirement with HunterAI.
</Warning>

## Only the first contact on a lead is kept

`contact_ids` is an array, but HunterAI keeps **only the first element**. The rest are
dropped.

<Warning>
  **Consequence:** a multi-contact deal is linked to exactly one contact. Contact-level
  analytics see only the primary.

  **Design around it:** order `contact_ids` so the most representative contact is **first**.
</Warning>

## Tombstones apply to leads only

The only delete signal HunterAI honours is a lead's `is_deleted: true`. There is **no
soft-delete** for contacts, users, tasks, or calls — those entities have no deleted flag in
the canonical model.

<Warning>
  **Consequence:** a contact, task, or call you delete in your CRM is still ingested as
  **active**. HunterAI also never removes a row that simply stops appearing in your
  responses — the upsert only inserts and updates, never deletes.

  **Design around it:** the only deletion you can propagate is a lead via `is_deleted`. For
  everything else, plan for records to persist in HunterAI once synced.
</Warning>

## Stage `kind` must be exactly `open`, `won`, or `lost`

The stage `kind` on [`/pipelines`](/endpoints/pipelines#stage-kind-classification)
must be one of `open`, `won`, or `lost` (matched case-insensitively). Any other value — or a
missing `kind` — is **rejected as an error**: it fails the page and, because `/pipelines`
is required, fails the sync. It is **not** silently classified as `open`.

<Warning>
  **Consequence:** an unrecognised `kind` is a hard error, not a silent fallback. A stage
  that should be "won" but is spelled `"win"` stops the sync outright — you find out
  immediately rather than discovering corrupted win-rate and revenue later.

  **Design around it:** validate that every stage emits exactly `open`, `won`, or `lost`
  before you request a connection.
</Warning>

## Won/lost depends on the stage being synced

A lead's won/lost is resolved from its stage's `kind`, looked up among stages already synced
in the same run.

<Warning>
  **Consequence:** if a lead references a pipeline/stage that was not synced (for example a
  partial sync of only `leads`, or a lead pointing at a stage you did not return on
  `/pipelines`), HunterAI cannot classify it. The lead lands with `is_won = is_lost = false`.
  This is counted and surfaced in the run summary — it is not silent — but the classification
  is wrong until the pipelines/stages are present.

  **Design around it:** always return every stage a lead can reference on `/pipelines`, and
  let full syncs run all entities.
</Warning>

## Fields dropped entirely

Some fields you can send are discarded because the canonical model has no column for them:

| Entity | Field(s) dropped                                                  | Note                                                                |
| ------ | ----------------------------------------------------------------- | ------------------------------------------------------------------- |
| Users  | `phone`                                                           | No phone column on users.                                           |
| Leads  | `currency`                                                        | See [Currency](#currency-is-not-stored). Kept in the raw copy only. |
| Leads  | `contact_ids[1:]`                                                 | Only the first contact is kept.                                     |
| Events | `created_by`                                                      | No actor column on events.                                          |
| Tasks  | `created_at`, and any `task_type` / `duration` / `result`         | Only `updated_at`, `due_at`, `completed_at` are kept.               |
| Calls  | `call_status`, `result`, `recording_link`, `source`, `created_by` | Telephony extras; kept in the raw copy only.                        |

Additionally, **contacts, users, pipelines, stages, and tasks retain no raw copy** — any
field on those entities not listed in the [reference](/endpoints/pipelines) is dropped. Only
**leads, events, and calls** keep your full raw payload for future reprocessing.

## Field truncation limits

Over-length text is **silently truncated** to fit — it never rejects the record. Maximum
accepted lengths:

| Field                                                            | Max chars |
| ---------------------------------------------------------------- | --------- |
| `pipeline.name`, `stage.name`                                    | 255       |
| `stage.color`                                                    | 20        |
| `user.name`, `user.email`                                        | 255       |
| `user.role`                                                      | 100       |
| `contact.name`, `contact.email`                                  | 255       |
| `contact.phone`                                                  | 50        |
| `lead.name`, `lead.source`, `lead.utm.source`, `lead.utm.medium` | 255       |
| `lead.utm.campaign`, `lead.utm.content`, `lead.utm.term`         | 500       |
| `lead.loss_reason`                                               | 500       |
| `event.type`                                                     | 100       |
| `call.phone`                                                     | 32        |
| `task.text`                                                      | unlimited |

## Timestamp handling

* **Accepted formats:** exactly the set every endpoint page documents — an explicit offset,
  a trailing `Z`, no zone at all (read as UTC), a `T` or a single space between date and
  time, or a bare date (time becomes `00:00` UTC). See
  [`/leads` → Timestamp format](/endpoints/leads#timestamp-format) for the canonical list;
  it is identical on every endpoint page. Prefer the explicit-offset form.
* **Unparseable value:** becomes `null` for that field. The record is still ingested — a
  single bad timestamp does not reject the record or fail the page.

<Warning>
  **Consequence:** a `null` `updated_at` means the record cannot participate in the
  [watermark](/concepts/how-sync-works#ordering-and-the-watermark) — an incremental sync may
  not pick it up correctly. Keep `updated_at` valid and always advancing on every change.
</Warning>

## Managers are not linked to HunterAI logins

CRM managers are ingested and used for attribution, but for a custom source they are **not**
automatically turned into HunterAI logins. Per-manager dashboards, scoping, and coaching are
unavailable until invitation-based linking ships. This is a deliberate security decision —
see [Go live → What does not work yet](/guides/connecting#what-does-not-work-yet).
