---
title: "Compare Protocols Endpoint"
method: POST
path: "/protocols/compare"
tags: ["protocols"]
---

# Compare Protocols Endpoint

`POST /protocols/compare`

Compare two UCPs and report the differences that change what a cycler does.

Cosmetic respellings are not differences: regenerated names, number
formatting, redundant nesting, an explicit goto where fall-through was
implicit, and a dropped trailing ``End`` all leave behaviour unchanged.
What is reported is what reaches the cell -- loop counts, setpoints,
terminations, gotos, safety bounds, and block-cumulative durations.

Pair it with ``/protocols/convert`` to check a round trip: convert a UCP to
a vendor format, parse the result back with ``/protocols/parse``, and
compare the two UCPs. A difference there is a conversion that lost
something.

## Request body

- CompareProtocolsRequest — Request body for comparing two UCPs for semantic equality.
  - `left` union, required — First UCP, as a dict or YAML string.
    - object
    - string
  - `right` union, required — Second UCP, as a dict or YAML string.
    - object
    - string

## Response `200`

Successful Response

- CompareProtocolsResponse — Result of comparing two protocols.
  - `equal` boolean, required — True when the protocols would make a cycler do the same thing. Differences that no tolerance explains make this False rather than being ignored.
  - `differences` ProtocolDifference[] — Every difference found, earliest first. Empty when equal.
    - `location` string, required — Where the difference is, e.g. 'Discharge [#2]'.
    - `kind` string, required — Machine-readable category, e.g. 'loop_repeat', 'end_condition', 'setpoint', 'goto_target', 'step_count', 'safety_limits', 'cumulative_block_end'.
    - `severity` string, required — 'behavioural' changes what the cycler does; 'expected' is a re-encoding a target format forces; 'unknown' is a real difference no tolerance explains.
    - `detail` string, required — What changed, in cycler terms, e.g. 'control setpoint changed: Discharge at 1.0 (C-rate) -> Discharge at 2.0 (C-rate)'.
    - `reason` string — Why it matters -- the consequence on hardware, so a caller can judge severity without reading the protocols.
    - `left` unknown
    - `right` unknown

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/ionworks/apis/fastapi.md) · [All operations](https://skmtc.dev/ionworks/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/ionworks/fastapi/revisions/7337a3cbdaf2/schema)
