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

# Agent workflows

> Common multi-step API sequences for automation and AI agents

# Agent workflows

These sequences show how to chain API v2 calls for typical automation tasks. All requests require the `x-api-key` header. See [ID prefixes](/api-v2/id-prefixes) for ID formats.

## Create a deal in a pipeline

1. **List pipelines** — get `dpl_` and `dps_` IDs:

```bash theme={null}
curl "https://api.heffl.com/api/v2/pipelines" \
  -H "x-api-key: YOUR_API_KEY"
```

Pick a pipeline `id` and an **ACTIVE** stage `id` from `stages` (check `type` is `ACTIVE`).

2. **Resolve the client** — search contacts or companies, or create one:

```bash theme={null}
curl "https://api.heffl.com/api/v2/contacts?search=acme&pageSize=5" \
  -H "x-api-key: YOUR_API_KEY"
```

3. **Optional: custom fields** — discover valid `cf_*` keys:

```bash theme={null}
curl "https://api.heffl.com/api/v2/custom-fields?entity=deals&pipelineId=dpl_abc123" \
  -H "x-api-key: YOUR_API_KEY"
```

4. **Create the deal**:

```bash theme={null}
curl -X POST "https://api.heffl.com/api/v2/deals" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Enterprise license",
    "clientId": "clt_abc123",
    "pipelineId": "dpl_abc123",
    "stageId": "dps_abc123",
    "price": 25000,
    "expectedCloseDate": "2026-06-30T00:00:00.000Z"
  }'
```

`stageId` is optional; if omitted, the first ACTIVE stage in the pipeline is used.

## Close a deal (won or lost)

**Option A — update stage** (recommended when matching your pipeline):

```bash theme={null}
curl -X PATCH "https://api.heffl.com/api/v2/deals/dl_abc123" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "stageId": "dps_won_stage_id" }'
```

Use a stage with `type` `WON` or `LOST` from `GET /pipelines`.

**Option B — set status directly**:

```bash theme={null}
curl -X PATCH "https://api.heffl.com/api/v2/deals/dl_abc123" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "WON" }'
```

## Create a follow-up task on a deal

```bash theme={null}
curl -X POST "https://api.heffl.com/api/v2/tasks" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Follow up on proposal",
    "type": "call",
    "dueDate": "2026-06-01T10:00:00.000Z",
    "entity": "deals",
    "entityId": "dl_abc123",
    "assigneeIds": ["usr_xyz789"]
  }'
```

`entity` and `entityId` must be sent together. List users with `GET /users` for assignee IDs.

## Create a quotation

1. **List quotation document templates** (layout presets for quotations, not project templates) — get a `tpl_` ID:

```bash theme={null}
curl "https://api.heffl.com/api/v2/document-templates?type=quotations" \
  -H "x-api-key: YOUR_API_KEY"
```

2. **Optional: template custom fields** — `GET /document-templates/{id}` for `customFields` keys to send as `cf_*` on create.

3. **Create the quotation** — see [Document templates](/api-v2/document-templates) and [API v2 overview — Quotations](/api-v2/introduction#quotations).

## List open deals in a pipeline

Pass `filters` as a **JSON-encoded query string** (recommended for agents and curl):

```bash theme={null}
curl -G "https://api.heffl.com/api/v2/deals" \
  -H "x-api-key: YOUR_API_KEY" \
  --data-urlencode 'pageSize=25' \
  --data-urlencode 'filters={"pipelineId":{"operator":"is","values":["dpl_abc123"]},"status":{"operator":"is","values":["ACTIVE"]}}'
```

Paginate with `cursor` from `meta.nextCursor`. See [Listing & filters](/api-v2/listing-and-filters).

## Delete a contact

Deletion fails with `400` if the contact has linked deals, invoices, or quotations:

```bash theme={null}
curl -X DELETE "https://api.heffl.com/api/v2/contacts/clt_abc123" \
  -H "x-api-key: YOUR_API_KEY"
```

## Error handling

All errors use `{ "error": { "code", "message", "details?" } }`. Validation failures include `details.issues` with `field` and `message`. See [Errors](/api-v2/errors). Retry `429` after the rate limit window; do not retry `400` without changing the request.
