---
title: "Api Experiments Partial Update"
method: PATCH
path: "/api/experiments/{id}/"
tags: ["experiments"]
---

# Api Experiments Partial Update

`PATCH /api/experiments/{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

- `id` string, required

## Headers

- `Authorization` string, required

## Request body

- PatchedPublicExperimentUpdateRequest
  - `id` string
  - `column_count` integer
  - `created_at` string, date-time
  - `name` string
  - `row_count` integer
  - `status` string
  - `test_id` string
  - `updated_at` string, date-time
  - `variables` string[]
  - `variable_definitions` unknown[]
    - unknown
  - `starred` boolean
  - `created_by` integer
  - `organization` integer
  - `project` string, nullable
  - `tags` string[]

## Response `200`

- PublicExperimentUpdate
  - `id` string
  - `column_count` integer
  - `columns` unknown[], required
    - unknown
  - `created_at` string, date-time
  - `name` string, required
  - `row_count` integer
  - `rows` unknown[], required
    - unknown
  - `status` string
  - `test_id` string
  - `updated_at` string, date-time
  - `variables` string[]
  - `variable_definitions` unknown[]
    - unknown
  - `starred` boolean
  - `created_by` integer, required
  - `organization` integer, required
  - `project` string, nullable
  - `updated_by` integer, nullable, required
  - `tags` string[]

---

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