<!-- Cogny documentation. Canonical page: https://cogny.com/docs/report-builder-api-reference -->

# Report Builder API Reference

Comprehensive API reference for generating AI-powered growth reports programmatically, including streaming responses and advanced customization options.

**Author:** Cogny Team  
**Published:** 2025-02-05  
**Updated:** 2026-10-05  
**Canonical:** https://cogny.com/docs/report-builder-api-reference

## Overview

The Report Builder API enables programmatic generation of AI-powered growth reports. Reports are generated asynchronously with optional real-time streaming of analysis progress.

**Base URL:** `https://api.cogny.com/v1/reports`

**Authentication:** Bearer token (see [API Authentication](/docs/api-overview-authentication))

## Create Report

Generate a new AI-powered report from your data warehouse.

### Endpoint

```http
POST /v1/reports
```

### Request Body

```json
{
  "warehouse_id": "wh_123abc",
  "prompt": "Analyze conversion funnel performance for Q1 2025, identify drop-off points and recommend optimizations",
  "context": {
    "date_range": {
      "start": "2025-01-01",
      "end": "2025-03-31"
    },
    "dimensions": ["channel", "device_category", "country"],
    "focus_areas": ["conversion_rate", "revenue", "user_engagement"]
  },
  "options": {
    "include_visualizations": true,
    "include_sql_queries": true,
    "include_recommendations": true,
    "max_iterations": 50,
    "language": "en"
  },
  "metadata": {
    "created_by": "user_456",
    "department": "growth",
    "project": "q1-optimization"
  }
}
```

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `warehouse_id` | string | Yes | ID of the connected data warehouse |
| `prompt` | string | Yes | Natural language description of desired analysis (max 2000 chars) |
| `context` | object | No | Additional context to guide the analysis |
| `context.date_range` | object | No | Date range for analysis |
| `context.dimensions` | array | No | Dimensions to focus on in analysis |
| `context.focus_areas` | array | No | Specific metrics or areas to prioritize |
| `options` | object | No | Report generation options |
| `options.include_visualizations` | boolean | No | Generate charts and graphs (default: true) |
| `options.include_sql_queries` | boolean | No | Include SQL queries used (default: false) |
| `options.include_recommendations` | boolean | No | Generate actionable recommendations (default: true) |
| `options.max_iterations` | integer | No | Max AI tool iterations (default: 50, max: 100) |
| `options.language` | string | No | Report language (default: "en") |
| `metadata` | object | No | Custom metadata for tracking |

### Response

```json
{
  "success": true,
  "data": {
    "id": "rpt_xyz789",
    "warehouse_id": "wh_123abc",
    "status": "processing",
    "prompt": "Analyze conversion funnel performance for Q1 2025...",
    "created_at": "2025-02-05T10:30:00Z",
    "updated_at": "2025-02-05T10:30:00Z",
    "estimated_completion": "2025-02-05T10:33:00Z",
    "url": "https://app.cogny.com/reports/rpt_xyz789",
    "stream_url": "https://api.cogny.com/v1/reports/rpt_xyz789/stream"
  }
}
```

### Example Request (cURL)

```bash
curl -X POST https://api.cogny.com/v1/reports \
  -H "Authorization: Bearer sk_live_abc123xyz789" \
  -H "Content-Type: application/json" \
  -d '{
    "warehouse_id": "wh_123abc",
    "prompt": "Analyze conversion funnel performance for Q1 2025",
    "options": {
      "include_visualizations": true,
      "include_recommendations": true
    }
  }'
```

### Example Request (Python)

```python
import requests

API_KEY = "sk_live_abc123xyz789"
BASE_URL = "https://api.cogny.com/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

payload = {
    "warehouse_id": "wh_123abc",
    "prompt": "Analyze conversion funnel performance for Q1 2025",
    "context": {
        "date_range": {
            "start": "2025-01-01",
            "end": "2025-03-31"
        },
        "focus_areas": ["conversion_rate", "revenue"]
    },
    "options": {
        "include_visualizations": True,
        "include_recommendations": True
    }
}

response = requests.post(
    f"{BASE_URL}/reports",
    headers=headers,
    json=payload
)

report = response.json()["data"]
print(f"Report created: {report['id']}")
print(f"Status: {report['status']}")
print(f"Stream URL: {report['stream_url']}")
```

## Get Report Status

Retrieve current status and details of a report.

### Endpoint

```http
GET /v1/reports/{report_id}
```

### Response

```json
{
  "success": true,
  "data": {
    "id": "rpt_xyz789",
    "warehouse_id": "wh_123abc",
    "status": "completed",
    "prompt": "Analyze conversion funnel performance for Q1 2025...",
    "created_at": "2025-02-05T10:30:00Z",
    "updated_at": "2025-02-05T10:33:45Z",
    "completed_at": "2025-02-05T10:33:45Z",
    "url": "https://app.cogny.com/reports/rpt_xyz789",
    "summary": {
      "total_queries": 12,
      "total_insights": 8,
      "key_findings": [
        "Mobile conversion rate 23% lower than desktop",
        "Cart abandonment peaks at payment step (41%)",
        "Organic traffic has highest conversion rate (4.2%)"
      ]
    },
    "metadata": {
      "created_by": "user_456",
      "department": "growth"
    }
  }
}
```

### Status Values

| Status | Description |
|--------|-------------|
| `queued` | Report is queued for processing |
| `processing` | AI is actively analyzing data |
| `completed` | Report successfully generated |
| `failed` | Report generation failed |
| `cancelled` | Report was cancelled by user |

### Example (Python with Polling)

```python
import time

def wait_for_report(report_id, timeout=300, interval=5):
    """Poll report status until completion"""
    start_time = time.time()

    while time.time() - start_time < timeout:
        response = requests.get(
            f"{BASE_URL}/reports/{report_id}",
            headers=headers
        )

        report = response.json()["data"]
        status = report["status"]

        print(f"Status: {status}")

        if status == "completed":
            return report
        elif status == "failed":
            raise Exception(f"Report failed: {report.get('error')}")

        time.sleep(interval)

    raise TimeoutError("Report generation timed out")

# Usage
report = wait_for_report("rpt_xyz789")
print(f"Report completed: {report['url']}")
```

## Stream Report Generation

Stream real-time updates during report generation using Server-Sent Events (SSE).

### Endpoint

```http
GET /v1/reports/{report_id}/stream
```

### SSE Event Types

#### `status` Event

Status updates during processing:

```
event: status
data: {"status": "processing", "message": "Analyzing conversion funnel data..."}
```

#### `query` Event

SQL query execution updates:

```
event: query
data: {"query": "SELECT event_name, COUNT(*) as count...", "status": "executing"}
```

#### `result` Event

Query results:

```
event: result
data: {"rows": 1247, "columns": ["event_name", "count", "conversion_rate"]}
```

#### `insight` Event

AI-generated insights:

```
event: insight
data: {"type": "finding", "content": "Mobile conversion rate is 23% lower than desktop", "confidence": 0.92}
```

#### `visualization` Event

Chart or graph generated:

```
event: visualization
data: {"type": "line_chart", "title": "Conversion Rate by Channel", "url": "https://cdn.cogny.com/viz_123.png"}
```

#### `completed` Event

Report generation finished:

```
event: completed
data: {"report_id": "rpt_xyz789", "url": "https://app.cogny.com/reports/rpt_xyz789"}
```

#### `error` Event

Error occurred:

```
event: error
data: {"code": "QUERY_FAILED", "message": "Insufficient permissions to access table"}
```

### Example (Python with SSE)

```python
import requests
import json

def stream_report(report_id):
    """Stream report generation progress"""
    url = f"{BASE_URL}/reports/{report_id}/stream"

    with requests.get(url, headers=headers, stream=True) as response:
        response.raise_for_status()

        for line in response.iter_lines():
            if not line:
                continue

            line = line.decode('utf-8')

            # Parse SSE format
            if line.startswith('event:'):
                event_type = line.split(':', 1)[1].strip()
            elif line.startswith('data:'):
                data = json.loads(line.split(':', 1)[1].strip())

                if event_type == 'status':
                    print(f"[STATUS] {data['message']}")
                elif event_type == 'insight':
                    print(f"[INSIGHT] {data['content']}")
                elif event_type == 'completed':
                    print(f"[COMPLETED] {data['url']}")
                    return data
                elif event_type == 'error':
                    raise Exception(f"Error: {data['message']}")

# Usage
report = stream_report("rpt_xyz789")
```

### Example (JavaScript/TypeScript)

```typescript
async function streamReport(reportId: string) {
  const response = await fetch(
    `${BASE_URL}/reports/${reportId}/stream`,
    {
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
      },
    }
  );

  const reader = response.body?.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader!.read();
    if (done) break;

    const chunk = decoder.decode(value);
    const lines = chunk.split('\n');

    let eventType = '';

    for (const line of lines) {
      if (line.startsWith('event:')) {
        eventType = line.substring(6).trim();
      } else if (line.startsWith('data:')) {
        const data = JSON.parse(line.substring(5).trim());

        switch (eventType) {
          case 'status':
            console.log(`[STATUS] ${data.message}`);
            break;
          case 'insight':
            console.log(`[INSIGHT] ${data.content}`);
            break;
          case 'completed':
            console.log(`[COMPLETED] ${data.url}`);
            return data;
          case 'error':
            throw new Error(`Error: ${data.message}`);
        }
      }
    }
  }
}

// Usage
const report = await streamReport('rpt_xyz789');
```

## List Reports

Retrieve all reports for a warehouse with filtering and pagination.

### Endpoint

```http
GET /v1/reports
```

### Query Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `warehouse_id` | string | Filter by warehouse ID |
| `status` | string | Filter by status (queued, processing, completed, failed) |
| `created_after` | string | ISO 8601 timestamp |
| `created_before` | string | ISO 8601 timestamp |
| `limit` | integer | Items per page (max: 100) |
| `cursor` | string | Pagination cursor |

### Response

```json
{
  "success": true,
  "data": [
    {
      "id": "rpt_xyz789",
      "warehouse_id": "wh_123abc",
      "status": "completed",
      "prompt": "Analyze conversion funnel performance...",
      "created_at": "2025-02-05T10:30:00Z",
      "completed_at": "2025-02-05T10:33:45Z",
      "url": "https://app.cogny.com/reports/rpt_xyz789"
    }
  ],
  "pagination": {
    "has_more": true,
    "next_cursor": "eyJpZCI6InJwdF94eXo3ODkifQ",
    "total_count": 47
  }
}
```

### Example

```bash
curl -X GET "https://api.cogny.com/v1/reports?warehouse_id=wh_123abc&status=completed&limit=50" \
  -H "Authorization: Bearer sk_live_abc123xyz789"
```

## Get Report Content

Retrieve the full content of a completed report.

### Endpoint

```http
GET /v1/reports/{report_id}/content
```

### Response

```json
{
  "success": true,
  "data": {
    "report_id": "rpt_xyz789",
    "sections": [
      {
        "title": "Executive Summary",
        "content": "Analysis of Q1 2025 conversion funnel reveals...",
        "insights": [
          {
            "type": "finding",
            "content": "Mobile conversion rate is 23% lower than desktop",
            "confidence": 0.92,
            "data": {
              "mobile_rate": 0.027,
              "desktop_rate": 0.035
            }
          }
        ]
      },
      {
        "title": "Funnel Analysis",
        "content": "The conversion funnel shows significant drop-off...",
        "visualizations": [
          {
            "type": "funnel_chart",
            "title": "Conversion Funnel by Step",
            "url": "https://cdn.cogny.com/viz_123.png",
            "data": {
              "steps": [
                {"name": "Landing", "users": 100000, "rate": 1.0},
                {"name": "Product View", "users": 45000, "rate": 0.45},
                {"name": "Add to Cart", "users": 12000, "rate": 0.12},
                {"name": "Checkout", "users": 7200, "rate": 0.072},
                {"name": "Purchase", "users": 3500, "rate": 0.035}
              ]
            }
          }
        ],
        "queries": [
          {
            "sql": "SELECT event_name, COUNT(DISTINCT user_pseudo_id) as users...",
            "description": "Calculate funnel step conversion rates",
            "rows_returned": 5,
            "execution_time_ms": 1247
          }
        ]
      }
    ],
    "recommendations": [
      {
        "priority": "high",
        "title": "Optimize Mobile Checkout Flow",
        "description": "Mobile users abandon cart at 2x desktop rate...",
        "estimated_impact": "12-18% increase in mobile conversions",
        "effort": "medium",
        "action_items": [
          "Implement one-click checkout for returning users",
          "Reduce form fields from 12 to 6",
          "Add mobile payment options (Apple Pay, Google Pay)"
        ]
      }
    ],
    "metadata": {
      "total_queries": 12,
      "total_insights": 8,
      "generation_time_seconds": 225
    }
  }
}
```

## Cancel Report

Cancel a queued or processing report.

### Endpoint

```http
DELETE /v1/reports/{report_id}
```

### Response

```json
{
  "success": true,
  "data": {
    "id": "rpt_xyz789",
    "status": "cancelled",
    "cancelled_at": "2025-02-05T10:32:00Z"
  }
}
```

## Error Codes

| Code | Description |
|------|-------------|
| `WAREHOUSE_NOT_FOUND` | Specified warehouse doesn't exist |
| `WAREHOUSE_NOT_CONNECTED` | Warehouse is not properly connected |
| `INVALID_PROMPT` | Prompt is empty or exceeds max length |
| `INVALID_DATE_RANGE` | Date range is invalid or too large |
| `INSUFFICIENT_PERMISSIONS` | API key lacks required permissions |
| `QUERY_FAILED` | SQL query execution failed |
| `RATE_LIMIT_EXCEEDED` | Too many concurrent reports |
| `REPORT_NOT_FOUND` | Report ID doesn't exist |

## Best Practices

### 1. Provide Context

Include relevant context to improve report quality:

```python
payload = {
    "warehouse_id": "wh_123abc",
    "prompt": "Analyze conversion funnel performance",
    "context": {
        "date_range": {
            "start": "2025-01-01",
            "end": "2025-03-31"
        },
        "dimensions": ["channel", "device_category"],
        "focus_areas": ["conversion_rate", "revenue"],
        "business_context": "Launched new checkout flow on Feb 1st"
    }
}
```

### 2. Use Streaming for Real-Time Feedback

Stream progress for long-running reports:

```python
# Better user experience with streaming
report_data = stream_report(report_id)

# vs. polling
report_data = wait_for_report(report_id)
```

### 3. Handle Errors Gracefully

Implement proper error handling:

```python
try:
    report = create_report(warehouse_id, prompt)
    result = wait_for_report(report['id'])
except requests.exceptions.HTTPError as e:
    if e.response.status_code == 429:
        print("Rate limit exceeded. Please wait.")
    elif e.response.status_code == 400:
        error = e.response.json()
        print(f"Invalid request: {error['error']['message']}")
    else:
        print(f"API error: {e}")
```

### 4. Store Report IDs

Save report IDs for future reference:

```python
# Store in your database
db.save_report({
    'cogny_report_id': report['id'],
    'user_id': user_id,
    'prompt': prompt,
    'status': report['status'],
    'url': report['url']
})
```

## Next Steps

- [Growth Tickets API](/docs/growth-tickets-api-reference) - Access AI-generated growth recommendations
- [Connect Your Data Sources](/docs/connect-your-data-sources) - Your BigQuery warehouse, the GA4 and Search Console links, and Bring Your Own Data
- [API Authentication](/docs/api-overview-authentication) - Learn about authentication and rate limits

---

In this section:

- Growth Tickets API Reference: https://cogny.com/docs/growth-tickets-api-reference
- **Report Builder API Reference** (this page): https://cogny.com/docs/report-builder-api-reference
- Cogny API Overview and Authentication: https://cogny.com/docs/api-overview-authentication

Source page: https://cogny.com/docs/report-builder-api-reference  
All documentation: https://cogny.com/docs  
Cogny for agents: https://cogny.com/llms.txt
