---
title: "Confirm extend upload; stitch series and recompute steps"
method: POST
path: "/cell_measurements/{measurement_id}/confirm-extend"
tags: ["Cell Measurements"]
---

# Confirm extend upload; stitch series and recompute steps

`POST /cell_measurements/{measurement_id}/confirm-extend`

## Request

- Base URL: `https://api.ionworks.com`
- URL: `https://api.ionworks.com/cell_measurements/{measurement_id}/confirm-extend`
- Auth: none declared

Confirm an extend upload; stitch series and recompute steps.

## Path parameters

- `measurement_id` string, uuid, required

## Response `200`

Successful Response

- CreateMeasurementResponse: Flat response after confirming a signed URL upload. Measurement fields (id, name, measurement_type, etc.) are at the top level, alongside the parent instance and upload metadata.
  - `is_failed` boolean: Whether it was reported as failed.
  - `failure_reason` string, nullable: Why it failed.
  - `failed_at` string, date-time, nullable: When it was reported.
  - `failed_by` string, nullable: User who reported it.
  - `name` string, required
  - `protocol` object, nullable: Protocol information. Typical keys: 'name' (str), 'ambient_temperature_degc' (float), 'definition' (dict | str — a UCP protocol definition or another protocol format).
  - `start_time` string, date-time, nullable: ISO 8601 datetime with timezone (UTC preferred) marking when the test started.
  - `end_time` string, date-time, nullable: ISO 8601 datetime with timezone (UTC preferred) marking when the test finished. Leave null while the test is still running; set it once the measurement is complete. A null end_time means the cell is still considered 'on test' in the Lab view.
  - `estimated_end_time` string, date-time, nullable: ISO 8601 datetime with timezone (UTC preferred) forecasting when a still-running test will finish. Distinct from end_time (the actual finish): this is an estimate. Null when no estimate has been computed yet.
  - `estimated_end_time_note` string, nullable: Free-text explanation of how estimated_end_time was derived.
  - `estimated_end_time_calculated_at` string, date-time, nullable: ISO 8601 datetime with timezone marking when estimated_end_time was last computed.
  - `test_setup` object, nullable: Physical test setup. Typical keys: 'cycler' (model), 'operator', 'lab', 'channel_number'. Readers also record what the cycler header carries, drawn from one shared vocabulary so the shape does not vary by cycler: 'test_name', 'cell_label' (the cycler's own label for the cell, which need not match the cell instance), 'instrument', 'cycler_serial_number', 'software_version', 'temperature_setpoint_degc', 'notes', 'end_time', plus export provenance -- 'export_date', 'source_file_path', 'barcode_comment', and 'source_file_id' (an id in the cycler's own id space, not a cross-system identifier). Which of these a file can fill depends on its format; keys the header does not carry are omitted rather than set empty.
  - `notes` string, nullable: Free-text notes about the cell measurement
  - `measurement_type` 'time_series' | 'file' | 'properties': Shape of the data stored in a cell measurement. - ``time_series`` — cycling / diagnostic data uploaded as columnar time series (and optional step summaries). Default for new measurements. - ``file`` — an opaque file upload (raw cycler export, image, other binary). Metadata about the file is captured in ``file_metadata``; the file content lives in object storage. - ``properties`` — a flat key/value set of measured properties (thickness, mass, DCIR, initial capacity, …) with no time-series data. Numeric values use the Quantity format.
  - `properties` object, nullable: Flat key/value measurements, populated only when measurement_type is 'properties'. Numeric values use the Quantity format. Example: {'thickness': {'value': 0.52, 'unit': 'mm'}, 'DCIR': {'value': 12, 'unit': 'mohm'}}.
  - `file_metadata` object, nullable: Metadata about uploaded files (MIME types, dimensions, etc.)
  - `channel_id` string, nullable: Optional ID of the channel this measurement ran on.
  - `protocol_id` string, nullable: Optional ID of the experiment template (protocol) this measurement was run against.
  - `program_id` string, nullable: Optional catalog program for this measurement (copied from a linked planned measurement when present).
  - `tags` string[]: Free-form labels for organising and filtering measurements, e.g. ['baseline', 'batch-7']. Whitespace is trimmed, duplicates are dropped case-insensitively, and a tag already used in the project keeps its existing spelling. At most 50 tags of up to 50 characters.
  - `id` string, required
  - `cell_instance_id` string, required
  - `organization_id` string, required: Organization this measurement belongs to.
  - `project_id` string, required: Project this measurement belongs to
  - `created_by` string, nullable: User ID of the user who created this measurement
  - `created_by_email` string, nullable: Email of the user who created this measurement
  - `processing_status` 'pending' | 'running' | 'ready' | 'failed' | 'awaiting_extend' | 'extending': Lifecycle of a measurement's step processing, shared with extend. - ``pending`` — confirm-upload task enqueued. - ``running`` — worker parsing the upload or calculating steps. - ``ready`` — terminal success; default for ``file``/``properties``. - ``failed`` — permanent; see ``processing_error``. - ``awaiting_extend`` — claim held, signed URL out, no task queued. - ``extending`` — delta staged, stitch queued or running. Only ``ready`` may start an extend, so it cannot overlap step processing (both write ``steps.parquet``). A failed extend returns to ``ready``.
  - `processing_error` string, nullable: Reason processing failed, when processing_status is 'failed'. Also carries why an extend did not apply, in which case the status is back to 'ready' and this is advisory only.
  - `source_etag` string, nullable
  - `row_count` integer, nullable
  - `time_series_bytes` integer, nullable
  - `recorded_duration_s` number, nullable
  - `accepts_raw_updates` boolean
  - `estimated_end_time_status` 'estimating' | 'ready' | 'failed': Lifecycle of a duration estimate computed by a background simulation. Used by both estimates: a planned test's total duration (``planned_measurements.estimated_duration_*``) and a running test's remaining duration (``cell_measurements.estimated_end_time_*``). One enum because the lifecycle is identical -- only what is being estimated differs. ``estimating`` while the job is in flight, ``ready`` once a value came from it, ``failed`` with the reason in the accompanying note. ``None`` means no estimate was ever requested.
  - `estimated_end_time_job_id` string, nullable
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `extend_claim_id` string, nullable: Opaque token identifying the in-flight extend that holds this measurement, and the staging prefix its delta is uploaded to. Non-null exactly while processing_status is 'awaiting_extend' or 'extending'.
  - `extend_in_progress_at` string, date-time, nullable: Deprecated and always null. Use processing_status.
  - `extend_claimed_at` string, date-time, nullable: When the in-flight extend claim was taken. Written only by the claim itself, so an unrelated update to the measurement does not age it. Null when no extend holds the measurement.
  - `instance` CellInstance, required: Model representing a cell instance as returned by the API.
    - `is_failed` boolean: Whether it was reported as failed.
    - `failure_reason` string, nullable: Why it failed.
    - `failed_at` string, date-time, nullable: When it was reported.
    - `failed_by` string, nullable: User who reported it.
    - `name` string, required: Name of the cell instance (serial number)
    - `batch_id` string, uuid, nullable: Manufacturing lot (cell batch) this cell came from. Must be a batch of the same cell specification.
    - `date_manufactured` string, date, nullable: Date of manufacture
    - `measured_properties` object, nullable: Measured (not designed) properties of this specific cell, grouped by component. Numeric values use the Quantity format. Example: {'cathode': {'loading': {'value': 7.06, 'unit': 'mg.cm-2'}}, 'cell': {'initial_capacity': {'value': 1.08, 'unit': 'A.h'}}}. Designed properties (target loading, rated capacity) belong on the cell specification.
    - `notes` string, nullable: Free-text notes about the cell instance
    - `id` string, required: Unique identifier for the cell instance
    - `cell_specification_id` string, required: Foreign key to the cell specification
    - `organization_id` string, required: Organization this cell instance belongs to.
    - `project_id` string, required: Project this cell instance belongs to
    - `created_by` string, nullable: User ID of the user who created this instance
    - `created_by_email` string, nullable: Email of the user who created this instance
    - `created_at` string, date-time, required: Timestamp when the instance was created
    - `updated_at` string, date-time, required: Timestamp when the instance was last updated
    - `batch_name` string, nullable: Name of the batch ``batch_id`` points at. Read-only.
    - `measurement_ids` object[], nullable: List of measurement IDs associated with the cell instance
  - `steps_created` integer, required

## Other responses

- `422`: Validation Error

## Changes

- **2026-10-24** `f4c74e855466`: 8 info
  - added the optional property `failed_at` to the response with the `200` status
  - added the optional property `failed_by` to the response with the `200` status
  - added the optional property `failure_reason` to the response with the `200` status
  - added the optional property `instance/failed_at` to the response with the `200` status
  - …4 more
- **2026-10-09** `d01ecf131915`: 1 info
  - added the optional property `accepts_raw_updates` to the response with the `200` status
- **2026-10-04** `1f50d4b61910`: 1 warning, 3 info
  - removed the optional property `instance/batch` from the response with the `200` status
  - added the optional property `instance/batch_id` to the response with the `200` status
  - added the optional property `instance/batch_name` to the response with the `200` status
  - added the optional property `tags` to the response with the `200` status
- **2026-09-30** `ea3d377fec1a`: 1 breaking, 1 warning
  - for the `path` request parameter `measurement_id`, the format changed from no format to `uuid`
  - removed the optional property `step_labels_validated` from the response with the `200` status
- **2026-09-14** `7baccf056192`: 1 info
  - added the optional property `recorded_duration_s` to the response with the `200` status

[Operation history](https://skmtc.dev/ionworks/apis/ionworks-api/changes/cell_measurements/:measurement_id/confirm-extend/post.md)

---

[API](https://skmtc.dev/ionworks/apis/ionworks-api.md) - [All operations](https://skmtc.dev/ionworks/apis/ionworks-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ionworks/apis/ionworks-api/revisions/abebbbc5f60a?raw)
