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

# Fetch Statements Reporting

> Extracts commission statement records from a statement reporting data structure. Statements represent the final calculated commissions—what each person earned in each period. Use this endpoint for payroll integration, commission reports, earnings history analysis, and compliance audit trails.

## Overview

This endpoint extracts commission statement records from a statement reporting data structure. Statements represent the **final calculated commissions** — what each person earned in each period.

**Use this endpoint for:**

* Payroll integration (sending commissions to payroll systems)
* Commission reports and dashboards
* Earnings history analysis
* Compliance and audit trails

<Info>
  **Statements = Results.** This endpoint gives you the output of Qobra's
  commission calculations, not the underlying deals/activities.
</Info>

***

## Pagination

This endpoint uses **ID-based pagination** for consistent performance with large datasets.

### Basic Pagination Pattern

```python theme={null}
url = f"https://api.qobra.co/v2/reporting/{table_id}/statements"
params = {"limit": 2000}

while True:
    response = requests.get(url, headers=headers, params=params)
    result = response.json()

    # Process records
    for record in result["data"]:
        process(record)

    # Check if more pages exist
    if not result["meta"]["has_more"]:
        break

    # Use next_url for next page
    url = result["meta"]["next_url"]
```

<Tip>
  **Use `next_url` for simplicity:** The API returns a pre-constructed
  `next_url` in the response meta—just follow it instead of manually building
  the next request.
</Tip>

***

## Filtering by modification date

Use `last_modified_after` to implement incremental sync (only fetch new/updated records).

### Incremental sync pattern

```python theme={null}
from datetime import datetime, timezone

def incremental_sync(table_id: str, api_key: str):
    # Load last sync time from your database
    last_sync = get_last_sync_time()  # e.g., 2024-01-14T00:00:00Z

    url = f"https://api.qobra.co/v2/reporting/{table_id}/statements"
    headers = {"X-API-Key": api_key}
    params = {
        "limit": 2000,
        "last_modified_after": last_sync.isoformat()
    }

    new_records = []

    while True:
        response = requests.get(url, headers=headers, params=params)
        result = response.json()

        new_records.extend(result["data"])

        if not result["meta"]["has_more"]:
            break

        url = result["meta"]["next_url"]

    # Save current time as last sync
    save_last_sync_time(datetime.now(timezone.utc))

    return new_records

# Usage: Daily incremental sync
new_statements = incremental_sync(table_id, api_key)
print(f"Found {len(new_statements)} new/updated statements since last sync")
```

**Benefits:**

* ✅ **10-100x faster** than full extracts
* ✅ Reduces API load
* ✅ Keeps your data warehouse up-to-date with minimal overhead

***

## Performance & best practices

<CardGroup cols={2}>
  <Card title="Use ID-based pagination" icon="forward">
    Always use `next_url` for large datasets (10K+).

    ```python theme={null}
    url = result["meta"]["next_url"]
    ```
  </Card>

  <Card title="Implement incremental sync" icon="clock">
    Use `last_modified_after` for daily/hourly updates.

    ```python theme={null}
    params = {"last_modified_after": last_sync}
    ```
  </Card>

  <Card title="Use Limit 2000" icon="gauge">
    Optimal balance between network overhead and response time.

    ```python theme={null}
    params = {"limit": 2000}
    ```
  </Card>
</CardGroup>


## OpenAPI

````yaml get /v2/reporting/{table_id}/statements
openapi: 3.0.2
info:
  version: 2.0.0
  title: Qobra API v2
  description: >-
    Modern data extraction API for Qobra - Optimized for high-volume data
    extraction with ID-based pagination and flexible schema discovery.
  license:
    name: Proprietary
    url: https://www.qobra.co/terms
servers:
  - url: https://api.qobra.co
    description: Production API
security: []
paths:
  /v2/reporting/{table_id}/statements:
    get:
      tags:
        - public_api
        - v2
        - reporting
      summary: Fetch Statements Reporting
      description: >-
        Extracts commission statement records from a statement reporting data
        structure. Statements represent the final calculated commissions—what
        each person earned in each period. Use this endpoint for payroll
        integration, commission reports, earnings history analysis, and
        compliance audit trails.
      operationId: GET_/v2/reporting/(table_id)/statements
      parameters:
        - name: table_id
          in: path
          required: true
          schema:
            type: string
            format: ObjectId
          description: ID of a statement reporting structure (from /v2/data-structures)
        - name: start_id
          in: query
          required: false
          schema:
            type: string
            format: ObjectId
          description: Start after this record ID (for ID-based pagination, recommended)
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 2000
            default: 2000
          description: Number of records per page (1-2000)
        - name: last_modified_after
          in: query
          required: false
          schema:
            type: string
            format: date-time
          description: >-
            ISO 8601 datetime - Only return records modified after this date
            (for incremental sync)
        - name: last_modified_before
          in: query
          required: false
          schema:
            type: string
            format: date-time
          description: ISO 8601 datetime - Only return records modified before this date
      responses:
        '200':
          description: >-
            Successfully retrieved statement records. Returns an array of
            commission statements with pagination metadata for navigating
            through large datasets. 
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StatementsResponse'
              examples:
                statements-success:
                  $ref: '#/components/examples/StatementsResponseExample'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvalidErrorResponse'
              examples:
                invalid-error:
                  $ref: '#/components/examples/InvalidErrorResponseExample'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedErrorResponse'
              examples:
                unauthorized-error:
                  $ref: '#/components/examples/UnauthorizedErrorResponseExample'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFoundErrorResponse'
              examples:
                not-found-error:
                  $ref: '#/components/examples/NotFoundErrorResponseExample'
      security:
        - api_key: []
components:
  schemas:
    StatementsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/StatementRecordModel'
          description: List of statement records
        meta:
          $ref: '#/components/schemas/MetaModel'
      required:
        - data
        - meta
    InvalidErrorResponse:
      type: object
      properties:
        count:
          type: number
          description: Number of errors
        errors:
          type: array
          items:
            type: object
            properties:
              error:
                type: string
                description: Error type
              resource:
                type: string
                description: Resource that caused the error
              description:
                type: string
                description: Description of the error
            required:
              - error
              - resource
              - description
      required:
        - count
        - errors
    UnauthorizedErrorResponse:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message
        type:
          type: string
          enum:
            - UnauthorizedError
          description: Type of the error
      required:
        - message
        - type
    NotFoundErrorResponse:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message
        resource:
          type: string
          description: Resource that caused the error
        type:
          type: string
          enum:
            - NotFoundError
          description: Type of the error
      required:
        - message
        - resource
        - type
    StatementRecordModel:
      type: object
      description: >-
        Statement record with dynamic fields based on the data structure schema.
        Common standard fields are prefixed with 'standard.', custom metrics
        with 'custom.', and data table fields with 'datatable.'.
      properties:
        standard.id:
          type: string
          format: ObjectId
          description: Unique record identifier
        standard.user:
          type: object
          description: User who earned the commission
          properties:
            id:
              type: string
              format: ObjectId
            email:
              type: string
              format: email
          required:
            - id
            - email
        standard.date:
          type: string
          description: Commission date (e.g., '2024-01-01')
        standard.total_commission:
          type: object
          properties:
            value:
              type: number
            currency:
              type: string
          required:
            - value
            - currency
        standard.status:
          type: string
          format: enum
          enum:
            - paid
            - pending
            - validated
            - cancelled
          description: Payment status
        custom.quota_attainment:
          type: number
          format: percentage
          description: Quota attainment
      required:
        - standard.id
        - standard.user
        - standard.date
        - standard.total_commission
        - standard.status
        - custom.quota_attainment
      additionalProperties: true
    MetaModel:
      type: object
      properties:
        next_start_id:
          type: string
          format: ObjectId
          nullable: true
          description: ID to use for the next page (null if no more records)
        has_more:
          type: boolean
          description: Whether more records exist after this page
        next_url:
          type: string
          nullable: true
          description: Pre-built URL for the next page (null if no more records)
      required:
        - has_more
        - next_url
        - next_start_id
  examples:
    StatementsResponseExample:
      value:
        data:
          - standard.id: 65a1b2c3d4e5f6g7h8i9j0k1
            standard.user:
              id: 507f191e810c19729de860ea
              email: sarah.johnson@company.com
            standard.date: '2024-01-01'
            standard.total_commission:
              value: 8500
              currency: USD
            standard.status: paid
            custom.quota_attainment: 0.92
            custom.tier: Accelerator
          - standard.id: 65a1b2c3d4e5f6g7h8i9j0k2
            standard.user:
              id: 507f191e810c19729de860eb
              email: michael.chen@company.com
            standard.date: '2024-01-01'
            standard.total_commission:
              value: 12750
              currency: USD
            standard.status: validated
            custom.quota_attainment: 1.15
            custom.tier: Overachievement
        meta:
          next_start_id: 65a1b2c3d4e5f6g7h8i9j999
          has_more: true
          next_url: >-
            https://api.qobra.co/v2/reporting/507f1f77bcf86cd799439011/statements?start_id=65a1b2c3d4e5f6g7h8i9j999&limit=1000
    InvalidErrorResponseExample:
      value:
        count: 1
        errors:
          - error: ValidationError
            resource: start_id
            description: >-
              Can't parse value for param 'start_id' : Value error, Invalid
              ObjectId
    UnauthorizedErrorResponseExample:
      value:
        message: You're trying to access resource you're not authorized to.
        type: UnauthorizedError
    NotFoundErrorResponseExample:
      value:
        message: We couldn't find the requested resource
        resource: ObjectModel
        type: NotFoundError
  securitySchemes:
    api_key:
      type: apiKey
      name: X-API-Key
      in: header
      description: Your Qobra API key. Generate it from Settings > API Keys in Qobra.

````