---
title: "Annotations In Testset Row List"
method: GET
path: "/evaluations/annotations/in-testset-row/{testset_row_id}/"
tags: ["evaluations"]
---

# Annotations In Testset Row List

`GET /evaluations/annotations/in-testset-row/{testset_row_id}/`

Stamp server-controlled fields at save time — never by mutating
``request.data``.

DRF's contract: ``post()`` → ``create()`` → ``serializer.is_valid()`` →
``perform_create(serializer)`` → ``serializer.save(**kwargs)``. Server values
belong in that final ``save(**kwargs)`` — they override ``validated_data``,
never pass through client validation, and don't need to be *writable*
serializer fields. The matching serializer field becomes ``read_only=True``
(or is dropped from ``fields``), shrinking — not widening — the
mass-assignment surface, and the immutable-``QueryDict`` (multipart) failure
mode of the old ``request.data[...] =`` pattern disappears.

Declare the fields to stamp as ``field -> fn(view) -> value`` maps::

    class ExperimentV2sView(ServerStampedFieldsMixin, ...):
        create_stamped_fields = {"created_by": stamp_request_user_id}
    # + serializer: created_by = ...(read_only=True)

FK columns: when the stamped value is an ``int`` and the field names a
relation on the serializer's ``Meta.model``, the kwarg is rewritten to
``<field>_id`` so ``Model.objects.create`` accepts it (a raw ``int`` on the
FK attribute itself would raise). Non-relation fields (``scorer`` = email)
and instance values pass through unchanged.

Cooperative composition: subclasses that need to stamp *additional* server
values (e.g. ``OrganizationInjectionMixin`` stamping org/project) override
``get_create_save_kwargs`` / ``get_update_save_kwargs`` and merge onto
``super()`` — yielding exactly ONE ``serializer.save()`` per request (calling
``save()`` twice would re-run create/update side effects).

## Path parameters

- `testset_row_id` string, required

## Query parameters

- `page` integer
- `page_size` integer

## Headers

- `Authorization` string, required

## Response `200`

- PaginatedAnnotationList
  - `count` integer, required
  - `next` string, uri, nullable
  - `previous` string, uri, nullable
  - `total_count` integer
  - `current_filters` FilterParamDictPydantic — Pydantic model for FilterParamDict. A dictionary that maps metric names to their filter parameters. Each key is a metric name (str), and each value can be: - A single MetricFilterParamPydantic (one condition) - A List[MetricFilterParamPydantic] (multiple conditions for same metric) - A FilterBundlePydantic (nested filter bundle with connector) Note: Uses extra="allow" for dynamic metric name fields. The __pydantic_extra__ annotation tells Pydantic what types to expect for extra fields, and generates typed additionalProperties in JSON Schema.
  - `filters_data` PaginatedAnnotationListFiltersData
  - `results` Annotation[], required
    - `id` string
    - `project` string, nullable
    - `type` 'numerical' | 'categorical' | 'boolean' — * `numerical` - Numerical * `categorical` - Categorical * `boolean` - Boolean
    - `numerical_value` number, double, nullable
    - `string_value` string, nullable
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `annotation_config` string, required
    - `log` integer, nullable
    - `testset_row` integer, nullable
    - `created_by` integer, required
    - `updated_by` integer, nullable, required
    - `organization` integer, required

---

[API](https://skmtc.net/keywordsai/apis/api-reference.md) · [All operations](https://skmtc.net/keywordsai/apis/api-reference/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/keywordsai/api-reference/versions/c26d550029f8/schema)
