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

# Get Deals

> Retrieve deals with flexible filtering, sorting, and pagination.
Returns deal objects with all their properties and relationships.
Use this for real-time data access and integrations.


Retrieve deals with flexible filtering, sorting, and pagination. Returns deal objects with all their properties and relationships.

<Accordion title="Copy for AI context">
  ```text theme={null}
  GET https://app.usehindsight.com/api/v1/deals
  Authorization: Bearer YOUR_API_KEY

  Query Parameters:
    # Pagination
    page_size: number (default: 50, max: 100)
    page_index: number (default: 0)
    count: boolean (return only count, not data)
    
    # Sorting
    sort: string (column name to sort by)
    sort_order: "asc" | "desc" (default: "desc")
    
    # Column selection
    columns: string (comma-separated column names, default: "*")
    
    # Search
    searchQuery: string (fuzzy search across deal names)
    
    # Filters (same canonical names as bulk export; arrays/objects are JSON-encoded)
    deal_ids: string (JSON array of Hindsight deal IDs)
    owner_ids: string (JSON array of owner IDs)
    owner_filter_type: "is any of" | "is not"
    status: string (JSON array of deal stages)
    status_filter_type: "is any of" | "is not"
    close_date: string (JSON object: {"from": "2026-01-01", "to": "2026-03-31"})
    amount: string (JSON object: {"min": 10000, "max": 100000})
    competitors: string (JSON array of any competitor IDs)
    competitors_filter_type: "is any of" | "is not" | "include all of"
    primary_competitor: string (JSON array of primary competitor IDs)
    deal_type: string (JSON array)
    deal_type_filter_type: "is any of" | "is not"
    region: string (JSON array)
    region_filter_type: "is any of" | "is not"
    industry: string (JSON array)
    industry_filter_type: "is any of" | "is not"
    product_labels: string (JSON array of product IDs)
    product_filter_type: "is any of" | "is not" | "include all of"
    analyzed: boolean
    verified: boolean
    # ... and more (see full filter list below)

  200 Response:
  [
    {
      "id": "deal_123",
      "name": "Acme Corp - Enterprise License",
      "amount": 50000,
      "status_id": "negotiation",
      "previous_status_id": "qualification",
      "close_date": "2026-03-15",
      "created_at": "2026-01-10T12:00:00Z",
      "owner_id": "user_abc",
      "salesforce_id": "006xxxxxxxxxxxx",
      "hubspot_id": "789123456",
      "deal_analyzed": true,
      "analysis_verified": null,
      "type": "New Business",
      "region": "North America",
      "summary": {
        "executive_summary": "Executive summary text for the deal…",
        "deal_overview": { "timeline": "…", "stakeholders": [], "deal_context": "…" },
        "decision_drivers": [],
        "competitive_landscape": [],
        "key_quotes": [],
        "lessons_learned": [],
        "recommendations": []
      },
      "driver_ids": ["reason_456", "reason_789"],
      "driver_names": ["Strong product fit", "Pricing competitiveness"],
      "drivers": [
        {
          "name": "Strong product fit",
          "tag": "Product",
          "score": 3,
          "sentiment": "positive",
          "summary": "Unified survey + interview data favored our approach"
        }
      ],
      "competitors": [
        {
          "competitor_id": "comp_123",
          "name": "Crayon",
          "is_primary": true,
          "is_incumbent": false,
          "threat_level": 4,
          "outcome": "lost_to_us",
          "positioning_summary": "Positioned on price and AI-driven analysis",
          "key_differentiators": "Executive-grade reporting"
        }
      ],
      "features": [
        {
          "name": "AI-driven interview analysis",
          "product": "Core",
          "impact_score": 3,
          "sentiment": "positive",
          "influence_summary": "Automated transcript synthesis was a differentiator"
        }
      ],
      "wl_product_fit_score": 4.2,
      "wl_sales_execution_score": 3.8,
      "wl_relationship_score": 4.5
      // ... additional fields based on columns parameter
    }
  ]

  Rate limits: 10 req/min (Essentials), 60 req/min (Growth), 300 req/min (Enterprise)
  ```
</Accordion>

## Overview

Use this endpoint to programmatically access your deal data with real-time filtering and pagination. Unlike bulk export which generates a CSV file, this endpoint returns JSON objects immediately and is ideal for:

* Building custom dashboards and reports
* Syncing deal data to external systems
* Real-time data access for integrations
* Paginating through large datasets

For large datasets or CSV format, use the [Bulk Export Deals](/api-reference/export-deals) endpoint instead.

## Pagination

| Parameter    | Type    | Description                           | Default |
| ------------ | ------- | ------------------------------------- | ------- |
| `page_size`  | number  | Number of deals to return per page    | 50      |
| `page_index` | number  | Zero-based page index                 | 0       |
| `count`      | boolean | If true, returns only the total count | false   |

**Example:**

```
GET /deals?page_size=20&page_index=0  # First 20 deals
GET /deals?page_size=20&page_index=1  # Next 20 deals
GET /deals?count=true                  # Get total deal count
```

## Column Selection

| Parameter | Type   | Description                                                                                                                                                                      |
| --------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `columns` | string | Comma-separated column IDs to return. The same IDs are accepted by bulk export. Use `*` for all columns. See [Available Columns](/api-reference/export-deals#available-columns). |

Limit returned data to only the fields you need to reduce response size and improve performance.

**Example:**

```
GET /deals?columns=deal_id,name,amount,deal_status,close_date,scorecard
GET /deals?columns=*  # All columns (default)
```

<Note>
  A set of internal columns is always omitted from the response, even when you request `*` or name them explicitly: full-text search vectors, sync bookkeeping, sharing configuration, and raw aggregate blobs (e.g. `fts`, `joined_fts`, `keywords`, `sync_run_id`, `client_id`, `org_sharing_enabled`, `processing_in_progress`). The `close_date` column is returned under that name (it maps to the internal `proposal_due` field); you may request it as either `close_date` or `proposal_due`.

  The relational columns `drivers`, `competitors`, and `features` return flattened arrays (see [Drivers, competitors, and features](#response-format) below) and are included with `*`. `summary` returns the complete structured deal-story object.
</Note>

For a complete list of available columns (standard and dynamic), see the [Available Columns](/api-reference/export-deals#available-columns) section in the Bulk Export Deals documentation.

### CRM properties, custom metrics, and custom answers

GET `/deals` and bulk export accept the same dynamic column selectors:

| Data                        | Column selector                           | Uses                           |
| --------------------------- | ----------------------------------------- | ------------------------------ |
| CRM deal property           | `crm_{property_id}`                       | CRM property ID                |
| Salesforce account property | `crm_salesforce_account_{property_id}`    | Salesforce Account property ID |
| HubSpot account property    | `crm_hubspot_account_{property_id}`       | HubSpot Company property ID    |
| Custom metric score         | `custom_metric_score_{metric_name}`       | Hindsight metric name          |
| Custom metric explanation   | `custom_metric_explanation_{metric_name}` | Hindsight metric name          |
| Custom answer               | `custom_answer_{answer_name}`             | Hindsight answer name          |

CRM selectors use the underlying CRM property ID, not its display label. Custom metric and answer selectors use the names configured in Hindsight. Name matching is case-insensitive and ignores spaces.

Only CRM properties synced into Hindsight are available. A requested property, metric, or answer returns `null` when the deal has no corresponding value.

```bash Dynamic columns theme={null}
curl --get https://app.usehindsight.com/api/v1/deals \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "columns=deal_id,name,crm_LeadSource,crm_salesforce_account_Industry,custom_metric_score_Strategic Fit,custom_metric_explanation_Strategic Fit,custom_answer_Champion identified"
```

The JSON response uses the requested selector as the property name:

```json theme={null}
[
  {
    "deal_id": "deal_123",
    "name": "Acme Corp",
    "crm_LeadSource": "Event",
    "crm_salesforce_account_Industry": "Software",
    "custom_metric_score_Strategic Fit": 4,
    "custom_metric_explanation_Strategic Fit": "Strong alignment with the target market.",
    "custom_answer_Champion identified": "Yes"
  }
]
```

## Search

| Parameter     | Type   | Description                    |
| ------------- | ------ | ------------------------------ |
| `searchQuery` | string | Fuzzy search across deal names |

**Example:**

```
GET /deals?searchQuery=acme
```

## Filters

GET and bulk export use the same canonical filter names and semantics. GET passes arrays and objects as JSON-encoded query parameters; bulk export sends the same values as native JSON in its request body. Simple booleans such as `analyzed=true` do not need JSON array encoding.

### Deal Identification

| Filter                     | Type   | Description                     | Example                   |
| -------------------------- | ------ | ------------------------------- | ------------------------- |
| `deal_ids`                 | string | JSON array of specific deal IDs | `["deal_123","deal_456"]` |
| `owner_ids`                | string | JSON array of owner IDs         | `["user_abc"]`            |
| `owner_filter_type`        | string | Filter type for owners          | `is any of`               |
| `collaborators`            | string | JSON array of collaborator IDs  | `["user_def"]`            |
| `collaborator_filter_type` | string | Filter type for collaborators   | `is any of`               |

### Deal Attributes

| Filter                  | Type   | Description               | Example                         |
| ----------------------- | ------ | ------------------------- | ------------------------------- |
| `status`                | string | JSON array of deal stages | `["Closed Won","Closed Lost"]`  |
| `status_filter_type`    | string | Filter type               | `is any of`                     |
| `deal_type`             | string | JSON array of deal types  | `["New Business","Expansion"]`  |
| `deal_type_filter_type` | string | Filter type               | `is any of`                     |
| `region`                | string | JSON array of regions     | `["North America","EMEA"]`      |
| `region_filter_type`    | string | Filter type               | `is any of`                     |
| `industry`              | string | JSON array of industries  | `["Technology","Healthcare"]`   |
| `industry_filter_type`  | string | Filter type               | `is any of`                     |
| `product_labels`        | string | JSON array of product IDs | `["prod_123"]`                  |
| `product_filter_type`   | string | Filter type               | `is any of` \| `include all of` |

### Date & Amount

| Filter       | Type   | Description                 | Example                                   |
| ------------ | ------ | --------------------------- | ----------------------------------------- |
| `close_date` | string | JSON object with date range | `{"from":"2026-01-01","to":"2026-03-31"}` |
| `amount`     | string | JSON object with min/max    | `{"min":10000,"max":100000}`              |

### Competitive Intelligence

| Filter                           | Type    | Description                                                      | Example        |
| -------------------------------- | ------- | ---------------------------------------------------------------- | -------------- |
| `competitors`                    | string  | JSON array of IDs for competitors appearing anywhere on the deal | `["comp_123"]` |
| `competitors_filter_type`        | string  | `is any of` \| `is not` \| `include all of`                      | `is any of`    |
| `primary_competitor`             | string  | JSON array of primary competitor IDs                             | `["comp_123"]` |
| `primary_competitor_filter_type` | string  | `is any of` \| `is not`                                          | `is any of`    |
| `has_competitor`                 | boolean | Whether the deal has any competitor                              | `true`         |

### Analysis

| Filter     | Type    | Description                            | Example |
| ---------- | ------- | -------------------------------------- | ------- |
| `analyzed` | boolean | Whether the deal has been analyzed     | `true`  |
| `verified` | boolean | Whether the analysis has been verified | `true`  |

### Legacy filter aliases

Existing integrations do not need to change immediately. Both GET and bulk export continue to accept these earlier internal names:

| Legacy GET name              | Canonical name                   |
| ---------------------------- | -------------------------------- |
| `ids`                        | `deal_ids`                       |
| `any_competitor`             | `competitors`                    |
| `any_competitor_filter_type` | `competitors_filter_type`        |
| `competitor`                 | `primary_competitor`             |
| `competitor_filter_type`     | `primary_competitor_filter_type` |
| `deal_analyzed`              | `analyzed`                       |
| `analysis_verified`          | `verified`                       |

Legacy boolean filters may still use JSON arrays such as `deal_analyzed=["true"]`.

### Win-Loss Scores

Filters for deal analysis scores (range queries):

| Filter                           | Format                           | Example             |
| -------------------------------- | -------------------------------- | ------------------- |
| `wl_product_fit_score`           | `{"min": number, "max": number}` | `{"min":3,"max":5}` |
| `wl_sales_execution_score`       | `{"min": number, "max": number}` | `{"min":3,"max":5}` |
| `wl_relationship_score`          | `{"min": number, "max": number}` | `{"min":3,"max":5}` |
| `wl_price_sensitivity_score`     | `{"min": number, "max": number}` | `{"min":1,"max":3}` |
| `wl_competitive_intensity_score` | `{"min": number, "max": number}` | `{"min":3,"max":5}` |
| `wl_customer_fit_score`          | `{"min": number, "max": number}` | `{"min":3,"max":5}` |
| `wl_messaging_fit_score`         | `{"min": number, "max": number}` | `{"min":3,"max":5}` |
| `wl_messaging_accuracy_score`    | `{"min": number, "max": number}` | `{"min":3,"max":5}` |

### CRM Filters (Advanced)

| Filter               | Type   | Description                             | Example                         |
| -------------------- | ------ | --------------------------------------- | ------------------------------- |
| `salesforce_filters` | string | JSON array of Salesforce filter objects | See [CRM Filters](#crm-filters) |
| `hubspot_filters`    | string | JSON array of HubSpot filter objects    | See [CRM Filters](#crm-filters) |

### Segments

| Filter                | Type   | Description                     | Example                 |
| --------------------- | ------ | ------------------------------- | ----------------------- |
| `segment`             | string | JSON array of segment IDs       | `["seg_123","seg_456"]` |
| `segment_filter_type` | string | `is any of` \| `include all of` | `is any of`             |

## Sorting

| Parameter    | Type   | Description            | Default     |
| ------------ | ------ | ---------------------- | ----------- |
| `sort`       | string | Column name to sort by | created\_at |
| `sort_order` | string | `asc` or `desc`        | desc        |

**Available sort columns:**

* `created_at` - Creation date
* `close_date` - Expected/actual close date
* `amount` - Deal value
* `name` - Deal name
* `wl_product_fit_score` - Product fit score
* `wl_sales_execution_score` - Sales execution score
* `wl_relationship_score` - Relationship score
* `wl_price_sensitivity_score` - Price sensitivity score
* `wl_competitive_intensity_score` - Competitive intensity score
* `wl_customer_fit_score` - Customer fit score
* `wl_messaging_fit_score` - Messaging fit score
* `wl_messaging_accuracy_score` - Messaging accuracy score

**Example:**

```
GET /deals?sort=close_date&sort_order=asc
GET /deals?sort=amount&sort_order=desc
```

## Response Format

### Standard Response

Returns an array of deal objects with all requested fields:

```json theme={null}
[
  {
    "id": "deal_123",
    "name": "Acme Corp - Enterprise License",
    "amount": 50000,
    "status_id": "negotiation",
    "previous_status_id": "qualification",
    "close_date": "2026-03-15",
    "created_at": "2026-01-10T12:00:00Z",
    "owner_id": "user_abc",
    "salesforce_id": "006xxxxxxxxxxxx",
    "hubspot_id": "789123456",
    "deal_analyzed": true,
    "analysis_verified": null,
    "type": "New Business",
    "region": "North America",
    "summary": {
      "executive_summary": "Executive summary text for the deal…",
      "deal_overview": { "timeline": "…", "stakeholders": [], "deal_context": "…" },
      "decision_drivers": [],
      "competitive_landscape": [],
      "key_quotes": [],
      "lessons_learned": [],
      "recommendations": []
    },
    "driver_ids": ["reason_456"],
    "driver_names": ["Price"],
    "drivers": [
      {
        "name": "Price",
        "tag": "Pricing",
        "score": 2,
        "sentiment": "negative",
        "summary": "Price too high compared to competitor"
      }
    ],
    "competitors": [
      {
        "competitor_id": "comp_123",
        "name": "Crayon",
        "is_primary": true,
        "is_incumbent": false,
        "threat_level": 4,
        "outcome": "lost",
        "positioning_summary": "Main competitor evaluation",
        "key_differentiators": null
      }
    ],
    "features": [
      {
        "name": "Executive-grade reporting",
        "product": "Core",
        "impact_score": 2,
        "sentiment": "positive",
        "influence_summary": "Filled a gap noted in incumbent tools"
      }
    ],
    "wl_product_fit_score": 4.2,
    "wl_sales_execution_score": 3.8,
    "wl_relationship_score": 4.5
  }
]
```

### Drivers, competitors, and features

These three are **relational** fields, returned as flattened arrays (included with `*`, or by requesting the `drivers`, `competitors`, and `features` columns):

| Field         | Shape                                                                                                                                                                                                              |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `drivers`     | `[{ name, tag, score, sentiment, summary }]` — decision drivers, strongest first. `sentiment` is `"positive" \| "negative" \| "neutral"`. `driver_ids` / `driver_names` are also returned as flat parallel arrays. |
| `competitors` | `[{ competitor_id, name, is_primary, is_incumbent, threat_level, outcome, positioning_summary, key_differentiators }]` — highest threat first.                                                                     |
| `features`    | `[{ name, product, impact_score, sentiment, influence_summary }]` — highest impact first.                                                                                                                          |

### Summary

`summary` returns the complete structured deal story, including `executive_summary`, `deal_overview`, `decision_drivers`, `competitive_landscape`, `key_quotes`, `lessons_learned`, and `recommendations`. It is `null` for deals that haven't been analyzed yet. Legacy plain-text summaries are returned as strings.

### Count Response

When `count=true`, returns only the total count:

```json theme={null}
142
```

## CRM Filters

For advanced filtering using CRM-specific properties:

```
GET /deals?salesforce_filters=[{"property":"Account.Industry","operator":"is","value":"Technology"}]
```

Salesforce filter object structure:

```json theme={null}
{
  "property": "Account.Industry",
  "operator": "is",
  "value": "Technology"
}
```

Supported operators:

* `is`, `is not`
* `is greater than`, `is less than`
* `is greater than or equal to`, `is less than or equal to`
* `is before`, `is after` (for dates)
* `contains`, `does not contain` (for text)

## Rate Limits

| Plan       | Requests per Minute |
| ---------- | ------------------- |
| Essentials | 10                  |
| Growth     | 60                  |
| Enterprise | 300                 |

## Examples

<RequestExample>
  ```bash Get Recent Deals theme={null}
  curl "https://app.usehindsight.com/api/v1/deals?page_size=20&sort=created_at&sort_order=desc" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```bash Get Closed Deals with Analysis theme={null}
  curl "https://app.usehindsight.com/api/v1/deals?status=%5B%22Closed%20Won%22%2C%22Closed%20Lost%22%5D&analyzed=true&page_size=50" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```bash Search Deals by Name theme={null}
  curl "https://app.usehindsight.com/api/v1/deals?searchQuery=acme&page_size=10" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```bash Get Deal Count theme={null}
  curl "https://app.usehindsight.com/api/v1/deals?count=true" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```bash Filter by Close Date and Amount theme={null}
  curl "https://app.usehindsight.com/api/v1/deals?close_date=%7B%22from%22%3A%222026-01-01%22%2C%22to%22%3A%222026-03-31%22%7D&amount=%7B%22min%22%3A50000%7D" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript Node.js - Get Paginated Deals theme={null}
  const API_KEY = 'your_api_key_here';
  const BASE_URL = 'https://app.usehindsight.com/api/v1';

  async function getDeals(page = 0, pageSize = 50) {
    const response = await fetch(
      `${BASE_URL}/deals?page_size=${pageSize}&page_index=${page}`,
      {
        headers: {
          'Authorization': `Bearer ${API_KEY}`
        }
      }
    );
    
    return await response.json();
  }

  // Get first page
  const deals = await getDeals(0, 50);
  console.log(`Retrieved ${deals.length} deals`);
  ```

  ```javascript Node.js - Filter Closed Deals with Competitors theme={null}
  const filters = {
    status: JSON.stringify(['Closed Won', 'Closed Lost']),
    status_filter_type: 'is any of',
    has_competitor: 'true',
    close_date: JSON.stringify({
      from: '2026-01-01',
      to: '2026-03-31'
    })
  };

  const queryParams = new URLSearchParams(filters);

  const response = await fetch(
    `${BASE_URL}/deals?${queryParams.toString()}`,
    {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    }
  );

  const deals = await response.json();
  console.log(`Found ${deals.length} closed deals with competitor mentions`);
  ```

  ```javascript Node.js - Get Total Deal Count theme={null}
  async function getTotalDeals() {
    const response = await fetch(
      `${BASE_URL}/deals?count=true`,
      {
        headers: { 'Authorization': `Bearer ${API_KEY}` }
      }
    );
    
    const count = await response.json();
    return count;
  }

  const total = await getTotalDeals();
  console.log(`Total deals: ${total}`);
  ```

  ```python Python - Iterate Through All Deals theme={null}
  import requests
  import json

  API_KEY = 'your_api_key_here'
  BASE_URL = 'https://app.usehindsight.com/api/v1'

  def get_all_deals(filters=None):
      """Fetch all deals with pagination"""
      all_deals = []
      page = 0
      page_size = 100
      
      while True:
          params = {
              'page_size': page_size,
              'page_index': page
          }
          
          # Add filters if provided
          if filters:
              params.update(filters)
          
          response = requests.get(
              f'{BASE_URL}/deals',
              headers={'Authorization': f'Bearer {API_KEY}'},
              params=params
          )
          response.raise_for_status()
          
          deals = response.json()
          
          if not deals:
              break
              
          all_deals.extend(deals)
          print(f'Fetched page {page + 1}: {len(deals)} deals')
          
          if len(deals) < page_size:
              break
              
          page += 1
      
      return all_deals

  # Get all analyzed deals from Q1 2026
  filters = {
      'analyzed': 'true',
      'close_date': json.dumps({
          'from': '2026-01-01',
          'to': '2026-03-31'
      })
  }

  deals = get_all_deals(filters)
  print(f'Total deals retrieved: {len(deals)}')
  ```

  ```python Python - Filter by Win-Loss Scores theme={null}
  import requests
  import json

  # Get high-performing deals (high product fit and execution)
  filters = {
      'wl_product_fit_score': json.dumps({'min': 4}),
      'wl_sales_execution_score': json.dumps({'min': 4}),
      'status': json.dumps(['Closed Won']),
      'status_filter_type': 'is any of'
  }

  response = requests.get(
      f'{BASE_URL}/deals',
      headers={'Authorization': f'Bearer {API_KEY}'},
      params=filters
  )

  deals = response.json()
  print(f'Found {len(deals)} high-performing won deals')

  for deal in deals[:5]:
      print(f"- {deal['name']}: ${deal['amount']:,.0f}")
  ```
</RequestExample>

## Best Practices

1. **Use Pagination**: Always paginate through large datasets rather than requesting all at once
2. **Select Columns**: Use the `columns` parameter to only fetch fields you need
3. **Cache Counts**: If you need counts frequently, cache them with appropriate TTL
4. **Filter Server-Side**: Apply filters in the API request rather than fetching all data and filtering client-side
5. **Handle Rate Limits**: Implement exponential backoff when you receive 429 responses
6. **Use Bulk Export for Large Datasets**: If you need to analyze thousands of deals, use the bulk export endpoint instead

## Comparison: Get Deals vs Bulk Export

| Feature             | GET /deals                     | POST /deals/export                       |
| ------------------- | ------------------------------ | ---------------------------------------- |
| **Response Format** | JSON                           | CSV                                      |
| **Response Time**   | Immediate                      | 2-3 minutes                              |
| **Use Case**        | Real-time access, integrations | Reports, analysis, backups               |
| **Pagination**      | Built-in                       | N/A (single file)                        |
| **Max Records**     | Unlimited (paginated)          | Unlimited                                |
| **Rate Limits**     | 10-300 req/min                 | 10-300 req/min plus monthly export quota |
| **Data Freshness**  | Real-time                      | Snapshot at export time                  |

## Error Responses

| Status Code | Description                                                        |
| ----------- | ------------------------------------------------------------------ |
| 400         | Invalid request (e.g., invalid filter format, invalid column name) |
| 401         | Invalid or missing API key                                         |
| 403         | Insufficient permissions                                           |
| 429         | Rate limit exceeded                                                |
| 500         | Internal server error                                              |

Example error response:

```json theme={null}
{
  "message": "Invalid filter format: close_date must be a valid JSON object"
}
```


## OpenAPI

````yaml GET /deals
openapi: 3.1.0
info:
  title: Hindsight API
  description: >
    Integrate Hindsight competitive intelligence, win-loss insights, and deal
    data into your applications.


    ## Authentication

    All API requests require a Bearer token in the Authorization header:

    ```

    Authorization: Bearer YOUR_API_KEY

    ```


    Get your API key from the [Hindsight
    dashboard](https://app.usehindsight.com/settings/keys).


    ## Rate Limits


    API and MCP requests are rate-limited per organization. The per-minute rate
    limit is

    shared across API and MCP traffic and uses a 60-second sliding window.
    Direct tool

    calls also consume a monthly usage bucket; `select-deal` and `get-deal`
    consume one

    read each from the shared reads bucket after authorization and validation
    succeed.


    | Plan | Per Minute | Per Month |

    |------|-----------|----------|

    | Essentials | 10 | 10,000 |

    | Growth | 60 | 30,000 |

    | Enterprise | 300 | 100,000 |


    Successful direct-tool responses include `X-RateLimit-Limit`,
    `X-RateLimit-Remaining`,

    `X-RateLimit-Reset` (Unix milliseconds), `X-Usage-Used`, `X-Usage-Limit`,

    `X-Usage-Remaining`, and `X-Usage-Period-End`. When a limit is exceeded, the
    API

    returns a `429` response with the relevant headers.
  version: 1.0.0
  contact:
    name: Hindsight Support
    url: https://usehindsight.com/support
    email: support@hindsight.com
servers:
  - url: https://app.usehindsight.com/api/v1
    description: Production server
security:
  - bearerAuth: []
tags:
  - name: Chat
    description: AI-powered chat completions with competitive intelligence
  - name: Deals
    description: Access and export deal data
  - name: Documents
    description: Upload and manage documents
  - name: Interviews
    description: Create and manage win-loss interview requests
  - name: Tools
    description: Structured Hindsight tool calls for application-controlled workflows
paths:
  /deals:
    get:
      tags:
        - Deals
      summary: Get deals with filtering and pagination
      description: |
        Retrieve deals with flexible filtering, sorting, and pagination.
        Returns deal objects with all their properties and relationships.
        Use this for real-time data access and integrations.
      operationId: getDeals
      parameters:
        - name: page_size
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
          description: Number of deals per page
        - name: page_index
          in: query
          schema:
            type: integer
            default: 0
          description: Zero-based page index
        - name: count
          in: query
          schema:
            type: boolean
          description: If true, returns only the total count
        - name: sort
          in: query
          schema:
            type: string
            enum:
              - created_at
              - updated_at
              - close_date
              - amount
              - name
          description: Column to sort by
        - name: sort_order
          in: query
          schema:
            type: string
            enum:
              - asc
              - desc
            default: desc
          description: Sort direction
        - name: columns
          in: query
          schema:
            type: string
          description: Comma-separated list of columns to return
        - name: searchQuery
          in: query
          schema:
            type: string
          description: Fuzzy search across deal names
        - name: status
          in: query
          schema:
            type: string
          description: JSON array of deal stages
        - name: owner_ids
          in: query
          schema:
            type: string
          description: JSON array of owner IDs
        - name: close_date
          in: query
          schema:
            type: string
          description: 'JSON object: {"from": "2026-01-01", "to": "2026-03-31"}'
        - name: amount
          in: query
          schema:
            type: string
          description: 'JSON object: {"min": 10000, "max": 100000}'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                oneOf:
                  - type: array
                    items:
                      $ref: '#/components/schemas/Deal'
                  - type: integer
                    description: Total count when count=true
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  schemas:
    Deal:
      type: object
      properties:
        id:
          type: string
          description: Hindsight deal ID
          example: deal_123
        name:
          type: string
          description: Deal name
          example: Acme Corp - Enterprise License
        amount:
          type: number
          description: Deal value
          example: 50000
        status_id:
          type: string
          description: Current deal stage ID
          example: negotiation
        previous_status_id:
          type: string
          nullable: true
          description: Previous deal stage ID
          example: qualification
        close_date:
          type: string
          format: date
          description: 'Expected or actual close date (internal field name: proposal_due)'
          example: '2026-03-15'
        created_at:
          type: string
          format: date-time
          description: Deal creation timestamp
        owner_id:
          type: string
          description: Deal owner ID
        salesforce_id:
          type: string
          nullable: true
          description: Salesforce Opportunity ID
        hubspot_id:
          type: string
          nullable: true
          description: HubSpot Deal ID
        deal_analyzed:
          type: boolean
          description: Whether deal has been analyzed
        analysis_verified:
          type: boolean
          description: Whether analysis has been verified
        type:
          type: string
          nullable: true
          description: Type of deal
          example: New Business
        region:
          type: string
          nullable: true
          description: Geographic region
        deal_competitor_associations:
          type: array
          items:
            type: object
            properties:
              competitor_id:
                type: string
              is_primary:
                type: boolean
              is_incumbent:
                type: boolean
          description: Array of competitor associations
        drivers:
          type: array
          items:
            type: object
            properties:
              reason_id:
                type: string
              positive:
                type: boolean
                nullable: true
              summary:
                type: string
          description: Array of deal drivers/reasons
        wl_product_fit_score:
          type: number
          nullable: true
          description: Product fit score (1-5)
        wl_sales_execution_score:
          type: number
          nullable: true
          description: Sales execution score (1-5)
        wl_relationship_score:
          type: number
          nullable: true
          description: Relationship score (1-5)
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Error code
              example: unauthorized
            message:
              type: string
              description: Human-readable error message
              example: Invalid API key
            details:
              type: object
              description: Additional error details
              additionalProperties: true
  responses:
    BadRequest:
      description: Bad request - invalid parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: bad_request
              message: Invalid parameters
              details:
                missing_fields:
                  - file_name
    Unauthorized:
      description: Unauthorized - invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: unauthorized
              message: Invalid API key
    RateLimitExceeded:
      description: >-
        Too many requests - per-minute rate limit or monthly usage quota
        exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: rate_limit_exceeded
              message: >-
                Rate limit exceeded. Please retry after the reset time in the
                response headers.
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
          description: Requests allowed in the current 60-second window.
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: Requests remaining in the current 60-second window.
        X-RateLimit-Reset:
          schema:
            type: integer
            format: int64
          description: Unix timestamp in milliseconds when the rate-limit window resets.
        X-Usage-Used:
          schema:
            type: integer
          description: Requests consumed from the applicable monthly bucket.
        X-Usage-Limit:
          schema:
            type: integer
          description: Monthly allowance for the applicable usage bucket.
        X-Usage-Remaining:
          schema:
            type: integer
          description: Requests remaining in the applicable monthly usage bucket.
        X-Usage-Period-End:
          schema:
            type: string
            format: date-time
          description: ISO timestamp when the monthly usage period resets.
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: internal_error
              message: An unexpected error occurred
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key from Hindsight dashboard

````