migration-api-2-19-to-2-29.md
336 lines · skills/opentrons-integration/references/migration-api-2-19-to-2-29.md at 5f2bc03
Migrating API 2.19 Protocols to the Current Baseline
This guide updates protocols written around robot software 7.3.1 and Protocol API 2.19 to the 2026-10-01 baseline:
- Flex: documented maximum Protocol API 2.30; bundled templates retain 2.29.
- OT-2: Protocol API 2.28.
- Flex local simulator:
opentrons==10.0.0. - OT-2 local compatibility simulator:
opentrons==9.0.0, followed by analysis in the current OT-2 App.
Do not mechanically change only the API string. Newer levels can change command validation and behavior.
Raw lines 1 to 141. Identify the Target Robot
API 2.29 and later are not supported on OT-2 at this baseline.
# Flex
requirements = {"robotType": "Flex", "apiLevel": "2.29"}
# OT-2
requirements = {"robotType": "OT-2", "apiLevel": "2.28"}Use one apiLevel declaration. Older files often put it in both metadata and requirements; current analysis rejects that.
Before:
metadata = {"apiLevel": "2.19", "protocolName": "Example"}
requirements = {"robotType": "Flex", "apiLevel": "2.19"}After:
metadata = {"protocolName": "Example"}
requirements = {"robotType": "Flex", "apiLevel": "2.29"}If the protocol must remain compatible with older robot software, keep 2.19 and apply only changes available at that level.
Raw lines 15 to 462. Replace Incorrect Flex Pipette Names
Current Flex load names describe channels and range:
| Old or incorrect pattern | Current choice |
|---|---|
p50_single_flex | flex_1channel_50 |
p50_multi_flex | flex_8channel_50 |
p1000_single_flex | flex_1channel_1000 |
p1000_multi_flex | flex_8channel_1000 |
p300_single_flex | No direct equivalent; choose flex_1channel_50 or flex_1channel_1000 from validated volume needs |
p300_multi_flex | No direct equivalent; choose flex_8channel_50 or flex_8channel_1000 |
Also available:
flex_96channel_200— API 2.25+.flex_96channel_1000.
Do not choose solely by the largest transfer. Check every operation against the pipette's lower and upper range and compatible tip capacities.
OT-2 GEN2 names remain p20_*_gen2, p300_*_gen2, and p1000_single_gen2.
3. Make Flex Trash Explicit
Flex API 2.16+ protocols should load the fixture actually installed:
trash = protocol.load_trash_bin("A3")Or:
chute = protocol.load_waste_chute()OT-2 keeps its fixed trash in slot 12 and does not call load_trash_bin().
If both a trash bin and waste chute exist, set the intended pipette trash container or pass the documented trash_location to complex commands.
4. Update Liquid Loading, API 2.22+
Well.load_liquid() is deprecated, and Well.load_empty() does not exist in the current package.
Before:
reservoir["A1"].load_liquid(liquid=buffer, volume=10_000)
plate["A1"].load_empty()After:
reservoir.load_liquid(
wells=["A1"],
volume=10_000,
liquid=buffer,
)
plate.load_empty(wells=["A1"])For varying volumes:
plate.load_liquid_by_well(
volumes={"A1": 20, "B1": 30},
liquid=sample,
)Raw lines 90 to 1215. Update Adapter Loading
ProtocolContext.load_labware_on_adapter() is not a current method.
Load the adapter, then call the adapter's method:
adapter = protocol.load_adapter(
"opentrons_96_well_aluminum_block",
"D1",
)
plate = adapter.load_labware(
"opentrons_96_wellplate_200ul_pcr_full_skirt"
)Some load_labware() calls also accept an adapter= load name for supported stacks. Use the pattern shown for the exact hardware in current documentation.
6. Fix Flex Magnetic Workflows
The powered Magnetic Module is OT-2-only.
Old Flex pattern:
magnetic_module = protocol.load_module(
"magnetic module gen2",
"C2",
)
magnetic_module.engage(height_from_base=6.5)Current Flex pattern:
magnetic_block = protocol.load_module("magneticBlockV1", "C2")
protocol.move_labware(
labware=plate,
new_location=magnetic_block,
use_gripper=True,
)
protocol.delay(minutes=5)
protocol.move_labware(
labware=plate,
new_location="B2",
use_gripper=True,
)The Magnetic Block is passive and has no engage() or disengage() method.
7. Fix Absorbance Plate Reader Calls
The reader was added in API 2.21 and is Flex-only. It does not accept read(wavelengths=[...]).
Incorrect:
result = plate_reader.read(wavelengths=[450, 650])Correct sequence:
reader = protocol.load_module("absorbanceReaderV1", "D3")
reader.close_lid()
reader.initialize(mode="multi", wavelengths=[450, 650])
reader.open_lid()
protocol.move_labware(
labware=plate,
new_location=reader,
use_gripper=True,
)
reader.close_lid()
result = reader.read(export_filename="absorbance")The plate reader returns zeros during simulation. Avoid divide-by-zero logic in the simulation branch.
Raw lines 174 to 2048. Remove Unsupported Complex-Command Options
Do not preserve options merely because an old reference listed them.
For example, gradient=(start, end) is not a supported generic transfer() option in the current API. Build a validated volume list explicitly:
volumes = [10, 20, 30, 40]
pipette.transfer(
volume=volumes,
source=reservoir["A1"],
dest=plate.wells()[:4],
new_tip="always",
)Check uncommon options against the exact current method and API level. The supported options for standard and liquid-class commands are not identical.
Raw lines 205 to 2249. Revisit Behavior Changes
Raw lines 225 to 226API 2.20
- Liquid presence detection.
- CSV runtime parameters.
- Expanded partial-nozzle layouts.
API 2.21
- Absorbance Plate Reader.
- Liquid presence checks only the first aspiration of a
mix()cycle.
API 2.22
- Labware-level liquid loading.
Well.load_liquid()deprecated.- Low-level robot motor control.
API 2.23
- Meniscus locations.
- Labware lids and lid moves.
- Labware offset behavior aligned with newer App checks.
API 2.24
- Verified and custom liquid classes.
transfer_with_liquid_class(),distribute_with_liquid_class(), andconsolidate_with_liquid_class().- Additional flow, delay, position, and push-out options.
API 2.27
- Concurrent module tasks.
- Dynamic aspirate, dispense, and mix paths.
- Built-in camera capture.
- Explicit tips for liquid-class transfers.
API 2.28
- Flex 20 µL tips.
- Improved return of partially picked-up tips.
- Absolute blowout customization.
- Thermocycler ramp-rate control.
set_empty()tip-rack state.- Errors for unsafe
touch_tip()use in large spaces.
API 2.29
- Step grouping in source and protocol visualization.
- Flex-only at this migration baseline.
API 2.30
- Aspirating at
well.meniscus(target="start")without anend_locationis supported. Older API levels reject that pattern. - The 10.0.0 package exposes
MAX_SUPPORTED_VERSION=2.31, while the official robot support table stops at 2.30. Check the target robot; do not adopt 2.31 from the local constant.
10. Revisit Module and Deck Assumptions
Check for:
- Flex trash or waste chute not represented in old code.
- Staging area and column-3 conflicts.
- New Gripper or lid moves.
- Heater-Shaker latch state.
- Thermocycler generation and footprint.
- Plate-reader caddy and lid travel.
- Stacker shuttle paths.
- Tip-rack adapter requirements for full versus partial 96-channel pickup.
API analysis has improved, so a newly raised deck-conflict error may reveal an old protocol assumption that was never physically safe.
Raw lines 295 to 31011. Revalidate Tip and Volume Policies
Do not assume newer pipetting behavior produces assay-equivalent results.
- Recalculate tip count.
- Recalculate source and dead volume.
- Confirm complex-command expansion in the run log.
- Requalify flow rates, mix behavior, bottom clearances, air gaps, and blowout.
- Recheck contamination policy.
- Recheck multi-channel and partial-nozzle well targeting.
12. Migration Test Plan
- Preserve the original protocol and expected run log.
- Update declarations and load names.
- Replace deprecated or invalid calls.
- Simulate with the robot-specific pin:
opentrons==10.0.0for Flex oropentrons==9.0.0for OT-2. - Compare command order, tip use, source/destination mapping, and module states.
- Test every runtime parameter branch.
- Import into the correct App and target robot.
- Resolve every analysis warning and error.
- Perform a nonhazardous dry run.
- Requalify assay performance before production use.
Do not claim a migration is equivalent solely from a successful simulation.
Raw lines 322 to 336