> ## 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 Quota Values

> Extracts the values of a quota: one row per user and per period, with the target set for them. Use this endpoint to compare targets with attainment in a BI tool, or to replicate quotas into a data warehouse. The response is not restricted to a visibility perimeter: the values of every user are returned, unlike in the Qobra app.

## Overview

This endpoint returns the values of a quota — the target assigned to each
person, for each period. Use it to put objectives next to results.

**Use this endpoint for:**

* BI dashboards comparing targets with attainment
* Replicating quotas into a data warehouse
* Feeding forecast models with committed objectives

<Info>
  **Quotas = targets.** This endpoint gives you what each person was *expected*
  to achieve. What they actually earned comes from
  [statements](/api_reference/v2/endpoints/data/fetch_statements).
</Info>

<Note>
  Only quotas from your company's **live environment** are reachable. A
  `quota_id` that belongs to a sandbox environment returns `404 Not Found`, even
  if the id was copied from the Qobra app while viewing that sandbox. Discover
  valid ids with
  [`GET /v2/data-structures`](/api_reference/v2/endpoints/discovery/list_data_structures),
  where every quota is listed with `"type": "quota"`.
</Note>

***

## Your first call

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://api.qobra.co/v2/quotas/QUOTA_ID/values?limit=100' \
    --header 'X-API-Key: YOUR_API_KEY'
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.qobra.co/v2/quotas/QUOTA_ID/values"
  headers = {"X-API-Key": "YOUR_API_KEY"}

  response = requests.get(url, headers=headers, params={"limit": 100})
  values = response.json()["data"]
  ```

  ```javascript JavaScript theme={null}
  const url = "https://api.qobra.co/v2/quotas/QUOTA_ID/values?limit=100";

  const response = await fetch(url, {
    headers: { "X-API-Key": "YOUR_API_KEY" },
  });
  const { data } = await response.json();
  ```
</CodeGroup>

### Example response

```json theme={null}
{
  "data": [
    {
      "standard.id": "65a1b2c3d4e5f60718293a01",
      "standard.user": {
        "id": "507f191e810c19729de860ea",
        "email": "sarah.johnson@company.com"
      },
      "standard.period": "2026-Q1",
      "standard.value": { "value": 120000.0, "currency": "EUR" },
      "standard.source": "local"
    },
    {
      "standard.id": "65a1b2c3d4e5f60718293a02",
      "standard.user": {
        "id": "507f191e810c19729de860eb",
        "email": "michael.chen@company.com"
      },
      "standard.period": "2026-Q1",
      "standard.value": { "value": 95000.0, "currency": "USD" },
      "standard.source": "integration"
    }
  ],
  "meta": {
    "next_start_id": "65a1b2c3d4e5f60718293a02",
    "has_more": true,
    "next_url": "https://api.qobra.co/v2/quotas/507f1f77bcf86cd799439013/values?start_id=65a1b2c3d4e5f60718293a02&limit=100"
  }
}
```

***

## One row per person and per period

The response is flat: one row for each combination of a user and a period. A
quarterly quota covering 40 people over 4 quarters returns up to 160 rows. Only
cells that hold a value produce a row, so a person with no target for a period
is simply absent rather than returned with a zero.

**The response is not grouped by user.** The Qobra app shows one line per person
with their periods side by side — this endpoint does not. Group on
`standard.user.id` yourself if you need the app's shape.

Every row carries the same five keys, whatever the quota's configuration. They
never depend on the column mapping of an integration, so you can hard-code them:

| Field             | What it holds                                           |
| ----------------- | ------------------------------------------------------- |
| `standard.id`     | Id of the quota value                                   |
| `standard.user`   | `{ id, email }` — `email` can be `null`                 |
| `standard.period` | `2026-03`, `2026-Q1`, `2026-S1` or `2026`               |
| `standard.value`  | `{ value, currency }` for an amount, otherwise a number |
| `standard.source` | `local` (set in Qobra) or `integration` (synchronized)  |

If you load several quotas into one table, tag each row with the `quota_id` you
requested — the response does not repeat it.

***

## Periods follow the quota's frequency

| Frequency  | Format    | Example   |
| ---------- | --------- | --------- |
| Monthly    | `YYYY-MM` | `2026-03` |
| Quarterly  | `YYYY-Qn` | `2026-Q1` |
| Semesterly | `YYYY-Sn` | `2026-S1` |
| Annually   | `YYYY`    | `2026`    |

The frequency is not part of the rows. Read it on `standard.period` from
[`GET /v2/data-structures/{quota_id}/fields`](/api_reference/v2/endpoints/discovery/get_fields_schema)
rather than guessing it from the string:

```json theme={null}
{
  "api_key": "standard.period",
  "type": "string",
  "format": "period",
  "frequency": "quarterly"
}
```

<Warning>
  **Periods follow your company's fiscal year.** `2026-Q1` is the first quarter
  of your fiscal year, which is not necessarily January to March.
</Warning>

***

## Everyone's values are returned

This endpoint returns the values of every user in the quota, whoever owns the
API key.

***

## The value depends on the quota type

| Quota type   | `standard.value` | Example                                    |
| ------------ | ---------------- | ------------------------------------------ |
| `amount`     | object           | `{ "value": 120000.0, "currency": "EUR" }` |
| `percentage` | number           | `0.85`                                     |
| `float`      | number           | `42.0`                                     |

<Warning>
  **A percentage is served as stored.** `0.85` means 85%. Multiply it yourself
  if you display a percentage.
</Warning>

`0.85` and `42.0` look alike, so a number on its own does not tell you whether
it is a ratio or an absolute value. What distinguishes them is the `format` of
`standard.value` on the fields endpoint — `currency`, `percentage` or `float`.
Read it once per quota before loading numbers into a typed column.

An amount carries the currency of its own value, so a quota whose people are
paid in different currencies returns rows with different currencies inside the
same page.

Changing a quota's type flips `standard.value` for every existing row without
touching any value. `last_modified_after` will not surface that; the
`schema_hash` on the fields endpoint will.

***

## Pagination

Pages are linked: every response carries a `next_url` that already includes your
`limit` and any date filters you sent. Follow it until `has_more` is `false`.

<CodeGroup>
  ```bash cURL theme={null}
  # First call
  curl --request GET \
    --url 'https://api.qobra.co/v2/quotas/QUOTA_ID/values?limit=2000' \
    --header 'X-API-Key: YOUR_API_KEY'

  # Then call meta.next_url as-is, until meta.has_more is false
  ```

  ```python Python theme={null}
  url = f"https://api.qobra.co/v2/quotas/{quota_id}/values"
  params = {"limit": 2000}

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

      for value in result["data"]:
          process(value)

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

      url = result["meta"]["next_url"]
      params = None
  ```
</CodeGroup>

Two things worth knowing:

* `limit` defaults to its maximum, **2000**. Omitting it gives you the largest
  page, not a small one. It is validated rather than capped, so `?limit=5000`
  returns `400` instead of 2000 rows.
* Rows come in creation order, not by period and not by user.

***

## Filtering by modification date

`last_modified_after` and `last_modified_before` restrict the response to values
modified inside a window. Both bounds are inclusive, and they cannot be equal —
passing the same datetime twice returns `400`.

```python theme={null}
params = {
    "limit": 2000,
    "last_modified_after": "2026-03-01T09:00:00+00:00",
}
```

Always include the timezone in your timestamp, as in the example above. A
timestamp without one is interpreted for you, so a client running in another
timezone shifts its window on every run and permanently misses the rows in the
gap.

The modification timestamp is filterable but never returned, and a change to the
quota itself — switching its type, for instance — moves no value timestamp at
all. Re-walk the whole quota periodically rather than trusting the window alone.

***

## What this endpoint does not do

* **No filter by user or period.** To read part of a quota, paginate through it
  and filter on your side.
* **No writes.** Importing quota values is not part of this endpoint.
* **No attainment.** Targets only — results come from
  [statements](/api_reference/v2/endpoints/data/fetch_statements).

***

## Archived quotas stay readable

Archiving a quota in Qobra does not hide it from the API. It stays listed by
`GET /v2/data-structures` — with `"status": "archived"` — and this endpoint
still serves its values. Read `status` from the discovery response to leave
archived quotas out of a sync.

***

## Errors

| Status | Cause                                                       |
| ------ | ----------------------------------------------------------- |
| `400`  | Invalid pagination parameter, see below                     |
| `401`  | Missing or unknown API key                                  |
| `403`  | The public API is not enabled for your company              |
| `404`  | Unknown id, a sandbox quota, or the id of a reporting table |

A `400` is the one you are most likely to meet. Its causes are a `limit` above
2000, a malformed `start_id`, and a `last_modified_after` equal to or later than
`last_modified_before`.


## OpenAPI

````yaml get /v2/quotas/{quota_id}/values
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/quotas/{quota_id}/values:
    get:
      tags:
        - public_api
        - v2
        - quotas
      summary: Fetch Quota Values
      description: >-
        Extracts the values of a quota: one row per user and per period, with
        the target set for them. Use this endpoint to compare targets with
        attainment in a BI tool, or to replicate quotas into a data warehouse.
        The response is not restricted to a visibility perimeter: the values of
        every user are returned, unlike in the Qobra app.
      operationId: GET_/v2/quotas/(quota_id)/values
      parameters:
        - name: quota_id
          in: path
          required: true
          schema:
            type: string
            format: ObjectId
          description: ID of a quota, listed with the type 'quota' by /v2/data-structures
        - name: start_id
          in: query
          required: false
          schema:
            type: string
            format: ObjectId
          description: >-
            Start after this quota value ID. This is the only pagination this
            endpoint supports
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 2000
            default: 2000
          description: Number of quota values per page (1-2000)
        - name: last_modified_after
          in: query
          required: false
          schema:
            type: string
            format: date-time
          description: >-
            ISO 8601 datetime - Only return values modified at or 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 values modified at or before this
            date
      responses:
        '200':
          description: >-
            Successfully retrieved the values of the quota. Returns one row per
            user and period, ordered by id, with pagination metadata for
            navigating through large quotas.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuotaValuesResponse'
              examples:
                quota-values-amount:
                  $ref: '#/components/examples/QuotaValuesResponseExample'
                quota-values-percentage:
                  $ref: '#/components/examples/QuotaValuesPercentageResponseExample'
        '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'
        '403':
          description: Forbidden - the public API is not enabled for your company
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenErrorResponse'
              examples:
                forbidden-error:
                  $ref: '#/components/examples/ForbiddenErrorResponseExample'
        '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:
    QuotaValuesResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/QuotaValueModel'
          description: List of quota values, one per user and period
        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
    ForbiddenErrorResponse:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message
        type:
          type: string
          enum:
            - ForbiddenError
          description: Type of the error
        error:
          type: string
          description: Machine-readable error code
      required:
        - message
        - type
        - error
    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
    QuotaValueModel:
      type: object
      description: >-
        A single quota value: one user, one period. The keys are the five
        api_key values advertised for this quota by
        /v2/data-structures/{table_id}/fields, and they are the same for every
        quota.
      properties:
        standard.id:
          type: string
          format: ObjectId
          description: Unique identifier of the quota value
        standard.user:
          type: object
          description: >-
            User the target is set for. Its email is null when the user cannot
            be resolved anymore; the id always lets you correlate the row
          properties:
            id:
              type: string
              format: ObjectId
            email:
              type: string
              format: email
              nullable: true
          required:
            - id
            - email
        standard.period:
          type: string
          description: >-
            Period the target applies to. Its format follows the quota's
            frequency, which the field schema declares on standard.period:
            '2026-03' (monthly), '2026-Q1' (quarterly), '2026-S1' (semesterly),
            '2026' (annually). Periods follow your company's fiscal year
        standard.value:
          description: >-
            The target itself. An object {value, currency} for an amount quota,
            a bare number for a percentage or float quota. A percentage is
            served as stored, unscaled: 0.85, not 85
          oneOf:
            - type: object
              properties:
                value:
                  type: number
                currency:
                  type: string
              required:
                - value
                - currency
            - type: number
        standard.source:
          type: string
          format: enum
          enum:
            - local
            - integration
          description: >-
            Where the value comes from: entered in Qobra (local) or synchronized
            from an integration (integration)
      required:
        - standard.id
        - standard.user
        - standard.period
        - standard.value
        - standard.source
      additionalProperties: false
    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:
    QuotaValuesResponseExample:
      value:
        data:
          - standard.id: 6701a3f4d4e5f6a7b8c9d0e1
            standard.user:
              id: 507f191e810c19729de860ea
              email: sarah.johnson@company.com
            standard.period: 2026-Q1
            standard.value:
              value: 120000
              currency: EUR
            standard.source: local
          - standard.id: 6701a3f4d4e5f6a7b8c9d0e2
            standard.user:
              id: 507f191e810c19729de860ea
              email: sarah.johnson@company.com
            standard.period: 2026-Q2
            standard.value:
              value: 135000
              currency: EUR
            standard.source: local
          - standard.id: 6701a3f4d4e5f6a7b8c9d0e3
            standard.user:
              id: 507f191e810c19729de860eb
              email: michael.chen@company.com
            standard.period: 2026-Q1
            standard.value:
              value: 150000
              currency: USD
            standard.source: integration
        meta:
          next_start_id: 6701a3f4d4e5f6a7b8c9d0e3
          has_more: true
          next_url: >-
            https://api.qobra.co/v2/quotas/507f1f77bcf86cd799439013/values?start_id=6701a3f4d4e5f6a7b8c9d0e3&limit=3
    QuotaValuesPercentageResponseExample:
      value:
        data:
          - standard.id: 6701b8a2d4e5f6a7b8c9d1f1
            standard.user:
              id: 507f191e810c19729de860ea
              email: sarah.johnson@company.com
            standard.period: 2026-03
            standard.value: 0.85
            standard.source: local
          - standard.id: 6701b8a2d4e5f6a7b8c9d1f2
            standard.user:
              id: 507f191e810c19729de860eb
              email: null
            standard.period: 2026-03
            standard.value: 1.1
            standard.source: integration
        meta:
          next_start_id: null
          has_more: false
          next_url: null
    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
    ForbiddenErrorResponseExample:
      value:
        message: You don't have permission to access this resource.
        type: ForbiddenError
        error: ForbiddenError
    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.

````