> ## 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.

# API v2 Overview

> Heffl REST API v2 — resource-oriented endpoints with consistent envelopes

# API v2 Overview <Badge color="orange">Beta</Badge>

Heffl API v2 is the current REST API for programmatic access to your workspace. System and custom object records are exposed at resource paths such as `/contacts`, `/companies`, `/deals`, `/quotations`, and `/tasks` with a consistent response envelope and structured errors.

<Warning>
  API v2 is in **beta**. Endpoints, schemas, and behavior may change as we expand coverage. Prefer it for new integrations, but expect breaking changes until GA. [Legacy API v1](https://docs.heffl.com/using-the-heffl-api) remains fully supported for existing integrations.
</Warning>

## Base URL

```
https://api.heffl.com/api/v2
```

All endpoints are served over HTTPS.

## What's new in v2

| Feature        | v1 (legacy)                                                                               | v2                                                                                                                 |
| -------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Response shape | Flat resource object                                                                      | List: `{ data, meta }` envelope; create/update/delete return the resource directly                                 |
| Error shape    | `{ code, message }`                                                                       | `{ error: { code, message, details? } }`                                                                           |
| Resource paths | Flat (`/clients`)                                                                         | Resource-based (`/contacts`, `/companies`)                                                                         |
| Contacts       | `POST /clients` with `type: "contact"`                                                    | `GET /contacts`, `POST /contacts`, `PATCH /contacts/{id}`, `DELETE /contacts/{id}`                                 |
| Companies      | `POST /clients` with `type: "company"`                                                    | `GET /companies`, `POST /companies`, `PATCH /companies/{id}`, `DELETE /companies/{id}`                             |
| Deals          | `GET /deals`, `POST /deals`, `GET /deals/{id}`, `PATCH /deals/{id}`, `DELETE /deals/{id}` | `GET /deals`, `POST /deals`, `GET /deals/{id}`, `PATCH /deals/{id}`, `DELETE /deals/{id}`                          |
| Quotations     | —                                                                                         | `GET /quotations`, `POST /quotations`, `GET /quotations/{id}`, `PATCH /quotations/{id}`, `DELETE /quotations/{id}` |
| Tasks          | `GET /tasks`, `POST /tasks`, `GET /tasks/{id}`, `PATCH /tasks/{id}`, `DELETE /tasks/{id}` | `GET /tasks`, `POST /tasks`, `PATCH /tasks/{id}`, `DELETE /tasks/{id}`                                             |

## Contacts

| Method   | Path             | Description                           |
| -------- | ---------------- | ------------------------------------- |
| `GET`    | `/contacts`      | List contacts (paginated, filterable) |
| `POST`   | `/contacts`      | Create a contact                      |
| `PATCH`  | `/contacts/{id}` | Update a contact                      |
| `DELETE` | `/contacts/{id}` | Delete a contact                      |

## Companies

| Method   | Path              | Description                            |
| -------- | ----------------- | -------------------------------------- |
| `GET`    | `/companies`      | List companies (paginated, filterable) |
| `POST`   | `/companies`      | Create a company                       |
| `PATCH`  | `/companies/{id}` | Update a company                       |
| `DELETE` | `/companies/{id}` | Delete a company                       |

## Deals

| Method   | Path          | Description                        |
| -------- | ------------- | ---------------------------------- |
| `GET`    | `/deals`      | List deals (paginated, filterable) |
| `GET`    | `/deals/{id}` | Get a deal                         |
| `POST`   | `/deals`      | Create a deal                      |
| `PATCH`  | `/deals/{id}` | Update a deal                      |
| `DELETE` | `/deals/{id}` | Delete a deal                      |

List active deals in a pipeline:

```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"]}}'
```

Create a deal by linking a client, pipeline, and stage:

```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"
  }'
```

## Quotations

| Method   | Path               | Description                                |
| -------- | ------------------ | ------------------------------------------ |
| `GET`    | `/quotations`      | List quotations (paginated, filterable)    |
| `GET`    | `/quotations/{id}` | Get a quotation with line items and totals |
| `POST`   | `/quotations`      | Create a quotation                         |
| `PATCH`  | `/quotations/{id}` | Update a quotation                         |
| `DELETE` | `/quotations/{id}` | Delete a quotation                         |

Create a quotation for a client with line items:

```bash theme={null}
curl -X POST "https://api.heffl.com/api/v2/quotations" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "clt_abc123",
    "templateId": "tpl_abc123",
    "date": "2026-05-31T00:00:00.000Z",
    "subject": "Website redesign proposal",
    "quotationProducts": [
      {
        "name": "Discovery workshop",
        "quantity": 1,
        "price": 2500,
        "taxRateId": "txr_abc123"
      }
    ]
  }'
```

`clientId` is a contact or company ID (`clt_` prefix) — use the `id` from `GET /contacts` or `GET /companies`. Optional `contactId` (`clt_`) sets the contact person when the client is a company.

`templateId` is required (`tpl_` prefix). List quotation templates with `GET /document-templates?type=quotations` — see [Document templates](https://docs.heffl.com/api-v2/document-templates). Pass `dealId` (`dl_` prefix) to link the quote to a deal, and `tags` with `tag_` IDs. Custom fields use `cf_*` keys — see [Custom fields](https://docs.heffl.com/api-v2/custom-fields).

## Document templates

Templates used for **documents** in Heffl — quotations, invoices, proforma invoices, purchase orders, and similar (not project or email templates). List by `type` to get the `templateId` for API creates.

| Method | Path                       | Description                                              |
| ------ | -------------------------- | -------------------------------------------------------- |
| `GET`  | `/document-templates`      | List document templates (filter by type, search by name) |
| `GET`  | `/document-templates/{id}` | Get a template with template-scoped custom fields        |

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

## Tasks

| Method   | Path          | Description                        |
| -------- | ------------- | ---------------------------------- |
| `GET`    | `/tasks`      | List tasks (paginated, filterable) |
| `POST`   | `/tasks`      | Create a task                      |
| `PATCH`  | `/tasks/{id}` | Update a task                      |
| `DELETE` | `/tasks/{id}` | Delete a task                      |

Link a task to a deal, lead, or project using `entity` and `entityId`:

```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"
  }'
```

## Quick start

List contacts with your API key:

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

Response:

```json theme={null}
{
  "data": [
    {
      "id": "clt_abc123",
      "number": "CON001",
      "firstName": "Jane",
      "lastName": "Smith",
      "email": "jane@example.com",
      "phone": "+971501234567",
      "createdAt": "2025-01-15T10:30:00.000Z",
      "cf_industry": "Technology"
    }
  ],
  "meta": {
    "nextCursor": null,
    "hasMore": false
  }
}
```

Update a contact (partial update — only send fields you want to change):

```bash theme={null}
curl -X PATCH "https://api.heffl.com/api/v2/contacts/clt_abc123" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jobTitle": "Head of Sales",
    "companyId": "clt_company456"
  }'
```

Response:

```json theme={null}
{
  "id": "clt_abc123",
  "number": "CON001",
  "firstName": "Jane",
  "lastName": "Smith",
  "jobTitle": "Head of Sales",
  "companyId": "clt_company456",
  "createdAt": "2025-01-15T10:30:00.000Z"
}
```

Delete a contact:

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

Response:

```json theme={null}
{
  "id": "clt_abc123",
  "deleted": true
}
```

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

## Authentication

Same as v1 — include your API key in the `x-api-key` header on every request. See [Authentication](https://docs.heffl.com/api-v2/authentication).

## Response shape

**List endpoints** return a paginated envelope:

```json theme={null}
{
  "data": [ ... ],
  "meta": {
    "nextCursor": null,
    "hasMore": false
  }
}
```

**Create, update, and delete** return the resource (or delete result) directly — not wrapped in `data`:

```json theme={null}
{
  "id": "clt_abc123",
  "firstName": "Jane",
  "lastName": "Smith"
}
```

**Custom fields** are returned as top-level `cf_*` keys on each resource (for example `cf_industry`), not in a `customFields` object. See [Custom fields](https://docs.heffl.com/api-v2/custom-fields).

## Next steps

* [Agent workflows](https://docs.heffl.com/api-v2/agent-workflows) — multi-step sequences (create deal, close deal, tasks)
* [ID prefixes](https://docs.heffl.com/api-v2/id-prefixes) — `clt_`, `dpl_`, `dps_`, `dl_`, and other ID formats
* [Authentication](https://docs.heffl.com/api-v2/authentication) — API keys and permissions
* [Errors](https://docs.heffl.com/api-v2/errors) — error codes and validation details
* [Pagination](https://docs.heffl.com/api-v2/pagination) — cursor-based paging with `pageSize`
* [Listing & filters](https://docs.heffl.com/api-v2/listing-and-filters) — search, sort, and structured filters
* [Custom fields](https://docs.heffl.com/api-v2/custom-fields) — `cf_*` field conventions; discover keys via `GET /custom-fields`
* [Document templates](https://docs.heffl.com/api-v2/document-templates) — templates for quotations, invoices, proforma invoices, and other documents
* Browse endpoint reference in the sidebar
