---
title: "Results Retrieve"
method: GET
path: "/evaluations/results/{id}/"
tags: ["evaluations"]
---

# Results Retrieve

`GET /evaluations/results/{id}/`

Mixin for views that need superadmin access to all resources.

Provides FOUR key features (all bundled - no separate mixins needed):
1. Queryset routing (superadmin sees all, regular user sees own org)
2. Organization injection (post/patch/put auto-inject org)
3. Object ownership checking (auto-registers ObjectOwnershipPermission)
4. Superadmin-only field protection (certain fields can only be modified by superadmins)

Inherits from:
- ObjectOwnershipMixin: Config attributes + auto-permission registration
- OrganizationInjectionMixin: Cross-org write protection + org injection

Config attributes (inherited from ObjectOwnershipMixin):
- ownership_object_field_name: Field on object (default: "organization_id")
- ownership_user_field_name: Field on user (default: "curr_org_id")
- is_allowing_global_object_read: Allow reading global objects (default: False)
- is_allowing_org_admin_access: Allow org admins access to any object in their org (default: False)
- is_requiring_org_admin_for_write: Require org admin for writes (default: False)

Config attributes (superadmin-only fields):
- superadmin_only_fields: List of field names that only superadmins can modify (default: [])
  On CREATE: Fields are stripped from non-superadmin requests (model defaults apply)
  On UPDATE: Non-superadmins trying to change these fields get PermissionDenied

- superadmin_lock_field: Field name that locks the entire object for non-superadmins (default: None)
  When this field is truthy on the instance, non-superadmins cannot modify ANY field.
  Common use case: is_managed=True means Keywords AI manages this resource, users can't edit it.

Note: Writing to global objects (ownership field is None) always requires superadmin.

Usage (detail view):

    class MyDetailView(SuperAdminMixin, JWTAndAPIKeyAuthenticationViewMixin, RetrieveUpdateDestroyAPIView):
        # Optional: customize ownership config (inherited from ObjectOwnershipMixin)
        is_allowing_global_object_read = True

        def get_regular_user_queryset(self):
            return MyModel.objects.filter(organization_id=self.request.user.curr_org_id)

        def get_superadmin_queryset(self):
            return MyModel.objects.all()

Usage (superadmin-only fields):

    class IntegrationView(SuperAdminMixin, JWTAndAPIKeyAuthenticationViewMixin, RetrieveUpdateDestroyAPIView):
        superadmin_only_fields = ['is_managed']  # Only superadmins can modify is_managed
        superadmin_lock_field = 'is_managed'  # When is_managed=True, object is locked for non-superadmins

        def get_regular_user_queryset(self):
            return Integration.objects.filter(organization_id=self.request.user.curr_org_id)

        def get_superadmin_queryset(self):
            return Integration.objects.all()

Usage (related-object org pattern like PromptVersion - PREFERRED: annotate queryset):

    from django.db.models import F

    class PromptVersionView(SuperAdminMixin, JWTAndAPIKeyAuthenticationViewMixin, RetrieveUpdateDestroyAPIView):
        def get_regular_user_queryset(self):
            # Annotate organization_id so ownership checks work automatically
            return PromptVersion.objects.filter(
                prompt__organization_id=self.request.user.curr_org_id
            ).annotate(organization_id=F("prompt__organization_id"))

        def get_superadmin_queryset(self):
            return PromptVersion.objects.annotate(organization_id=F("prompt__organization_id"))

Alternative (override method - only if annotation not possible):

    class PromptVersionView(SuperAdminMixin, JWTAndAPIKeyAuthenticationViewMixin, RetrieveUpdateDestroyAPIView):
        def get_affiliated_object_organization_id(self, instance):
            return instance.prompt.organization_id  # Org is on parent object

DO NOT use inline checks like this:
    # ❌ BAD - easy to forget in branching code
    def get_queryset(self):
        if has_staff_role(self.request.user):
            return MyModel.objects.all()
        return MyModel.objects.filter(...)

## Path parameters

- `id` integer, required

## Headers

- `Authorization` string, required

## Response `200`

- EvalResultDetail — Mixin to handle underscore-prefixed field mapping in serializers. This is used when Django annotations require underscore prefixes to avoid name conflicts with original column names, but we want to expose the clean field names in the API response. Usage: 1. Annotate queryset with underscore prefixes: _field_name 2. This mixin automatically maps _field_name -> field_name in to_internal_value 3. The serializer can then use the clean field names normally
  - `id` string, required
  - `evaluation_id` string, required
  - `human_text_value` string
  - `project` string, nullable
  - `results` string, required
  - `evaluator` EvaluatorDetail, required — Mixin for internal evaluator serializers that work with full configuration format.
    - `version_id` string
    - `eval_class` 'ragas_faithfulness' | 'ragas_noise_sensitivity' | 'ragas_response_relevancy' | 'ragas_answer_relevancy' | 'ragas_context_precision' | 'ragas_context_recall' | 'ragas_context_entity_recall' | 'ragas_factual_correctness' | 'ragas_semantic_similarity' | 'ragas_non_llm_string_similarity' | 'ragas_non_llm_string_presence' | 'ragas_non_llm_exact_match' | 'relari_llm_based_custom_metric' | 'relari_llm_based_answer_correctness' | 'keywordsai_custom_evaluator' | 'keywordsai_custom_llm' | 'output_char_count' | 'output_word_count' | 'custom_code', required — * `ragas_faithfulness` - ragas_faithfulness * `ragas_noise_sensitivity` - ragas_noise_sensitivity * `ragas_response_relevancy` - ragas_response_relevancy * `ragas_answer_relevancy` - ragas_answer_relevancy * `ragas_context_precision` - ragas_context_precision * `ragas_context_recall` - ragas_context_recall * `ragas_context_entity_recall` - ragas_context_entity_recall * `ragas_factual_correctness` - ragas_factual_correctness * `ragas_semantic_similarity` - ragas_semantic_similarity * `ragas_non_llm_string_similarity` - ragas_non_llm_string_similarity * `ragas_non_llm_string_presence` - ragas_non_llm_string_presence * `ragas_non_llm_exact_match` - ragas_non_llm_exact_match * `relari_llm_based_custom_metric` - relari_llm_based_custom_metric * `relari_llm_based_answer_correctness` - relari_llm_based_answer_correctness * `keywordsai_custom_evaluator` - keywordsai_custom_evaluator * `keywordsai_custom_llm` - keywordsai_custom_llm * `output_char_count` - output_char_count * `output_word_count` - output_word_count * `custom_code` - custom_code
    - `editor` Editor, required
      - `id` integer, required
      - `email` string, required
      - `name` string, required
      - `username` string
      - `first_name` string
      - `last_name` string
    - `id` string
    - `version` integer
    - `is_read_only` boolean
    - `version_description` string
    - `evaluator_slug` string
    - `name` string, required
    - `unique_organization_id` string, nullable
    - `description` string
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `score_config` unknown
    - `passing_conditions` union
      - unknown
      - unknown
    - `llm_config` union
      - unknown
      - unknown
    - `code_config` union
      - unknown
      - unknown
    - `type` 'llm' | 'code' | 'human' | 'function' | 'human_numerical' | 'human_categorical' | 'human_boolean' | 'human_text' | 'custom' — * `llm` - Llm * `code` - Code * `human` - Human * `function` - Function * `human_numerical` - Human Numerical * `human_categorical` - Human Categorical * `human_boolean` - Human Boolean * `human_text` - Human Text * `custom` - Custom
    - `score_value_type` 'numerical' | 'boolean' | 'percentage' | 'single_select' | 'multi_select' | 'text' | 'json' | 'comment' | 'categorical' — * `numerical` - Numerical * `boolean` - Boolean * `percentage` - Percentage * `single_select` - Single Select * `multi_select` - Multi Select * `text` - Text * `json` - Json * `comment` - Comment * `categorical` - Categorical
    - `configurations` unknown
    - `custom_required_fields` string[]
    - `categorical_choices` unknown[]
      - unknown
    - `starred` boolean
    - `organization` integer, nullable
    - `project` string, nullable
  - `results_id` integer, required
  - `inputs` string, required
  - `eval_result_unique_id` string
  - `type` 'llm' | 'code' | 'human' | 'function' | 'human_numerical' | 'human_categorical' | 'human_boolean' | 'human_text' | 'custom' — * `llm` - Llm * `code` - Code * `human` - Human * `function` - Function * `human_numerical` - Human Numerical * `human_categorical` - Human Categorical * `human_boolean` - Human Boolean * `human_text` - Human Text * `custom` - Custom
  - `environment` string
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `unique_organization_id` string
  - `eval_class` 'ragas_faithfulness' | 'ragas_noise_sensitivity' | 'ragas_response_relevancy' | 'ragas_answer_relevancy' | 'ragas_context_precision' | 'ragas_context_recall' | 'ragas_context_entity_recall' | 'ragas_factual_correctness' | 'ragas_semantic_similarity' | 'ragas_non_llm_string_similarity' | 'ragas_non_llm_string_presence' | 'ragas_non_llm_exact_match' | 'relari_llm_based_custom_metric' | 'relari_llm_based_answer_correctness' | 'keywordsai_custom_evaluator' | 'keywordsai_custom_llm' | 'output_char_count' | 'output_word_count' | 'custom_code', required — * `ragas_faithfulness` - ragas_faithfulness * `ragas_noise_sensitivity` - ragas_noise_sensitivity * `ragas_response_relevancy` - ragas_response_relevancy * `ragas_answer_relevancy` - ragas_answer_relevancy * `ragas_context_precision` - ragas_context_precision * `ragas_context_recall` - ragas_context_recall * `ragas_context_entity_recall` - ragas_context_entity_recall * `ragas_factual_correctness` - ragas_factual_correctness * `ragas_semantic_similarity` - ragas_semantic_similarity * `ragas_non_llm_string_similarity` - ragas_non_llm_string_similarity * `ragas_non_llm_string_presence` - ragas_non_llm_string_presence * `ragas_non_llm_exact_match` - ragas_non_llm_exact_match * `relari_llm_based_custom_metric` - relari_llm_based_custom_metric * `relari_llm_based_answer_correctness` - relari_llm_based_answer_correctness * `keywordsai_custom_evaluator` - keywordsai_custom_evaluator * `keywordsai_custom_llm` - keywordsai_custom_llm * `output_char_count` - output_char_count * `output_word_count` - output_word_count * `custom_code` - custom_code
  - `evaluator_slug` string
  - `evaluator_name` string, nullable
  - `scorer` string
  - `workflow_version_id` string
  - `source` string
  - `cost` number, double
  - `evaluation_identifier` string, nullable
  - `log_unique_id` string, nullable
  - `customer_identifier` string, nullable
  - `eval_set_id` string, nullable
  - `log_timestamp` string, date-time, nullable
  - `prompt_version_id` string, nullable
  - `pipeline_run_id` string
  - `automation_id` string, nullable
  - `primary_score` number, double, nullable
  - `string_value` string, nullable
  - `json_value` string
  - `boolean_value` boolean, nullable
  - `categorical_value` string[]
  - `secondary_score` number, double, nullable
  - `tertiary_score` number, double, nullable
  - `quaternary_score` number, double, nullable
  - `score_mapping` unknown
  - `human_numerical_value` number, double, nullable
  - `human_categorical_value` string, nullable
  - `passed` boolean, nullable
  - `status` 'pending' | 'completed' | 'failed' — * `pending` - Pending * `completed` - Completed * `failed` - Failed
  - `error_message` string, nullable
  - `storage_object_key` string
  - `updated_by` integer, nullable, required
  - `organization` integer, required
  - `evaluation` string, nullable
  - `annotation_config` string, nullable
  - `log` integer, nullable

---

[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)
