QFM API Guide

QuickFreeze QFM API

Read live status and control your QFM units from your WMS or building-automation system — set cycle times, record what is on the pallet, pause and resume fans.

Your software addresses each unit by its QFM serial number (printed on the unit) plus the rack location you have on file for it. Everything runs through one secured endpoint, scoped to your facility’s own units. The serial is permanent — when a control box is replaced, the API resolves the serial to whichever box is installed at that moment, so a swap needs no change on your side.

Connection

Endpoint
https://qfreeze.com/wp-json/qf/v1/qfm
the same address for every customer — your key scopes it to your units
Auth header
X-QF-API-Key: {your-api-key} — issued per facility; TLS 1.2+ required
Methods
HTTP GET (query parameters) or POST (JSON body)
Responses
Reads return 200 with the unit’s live state; commands return 202 accepted. Every failure is JSON with a stable error code — a missing or wrong key returns 401.
User-Agent
Please send an identifying agent, e.g. YourCompany-WMS/1.0. Our edge blocks a few known automated-client signatures; if you ever receive an HTML 403 instead of JSON, tell us and we will allow your client.

1. Identifying a unit

Every request carries two identifiers, and both must match our records:

ParameterExampleNotes
QFM_SERIALQFM-12107Printed on the unit. Permanent — survives control-box swaps.
RACK_LOCATION2X-001BThe rack position we have recorded for that QFM.
WAREHOUSE_IDDC-EASTOptional. Your own site or warehouse code, echoed back unchanged — a label for multi-site systems, not a permission.

If the serial exists but the rack does not match, the request is refused and the reply tells you which rack we have on file (409 rack_mismatch). A stale or mis-keyed mapping in the WMS can never make us act on the wrong unit. A serial belonging to another customer returns 403, even with a correct rack.

2. Poll a unit (read latest)

COMMAND=poll is the default and may be omitted. Polling is read-only and cannot affect equipment.

curl -H "X-QF-API-Key: {your-api-key}" -H "User-Agent: YourCompany-WMS/1.0" \
  "https://qfreeze.com/wp-json/qf/v1/qfm?QFM_SERIAL=QFM-12107&RACK_LOCATION=2X-001B&COMMAND=poll"

→ 200 {"ok":true,"QFM_SERIAL":"QFM-12107","RACK_LOCATION":"2X-001B",
       "controlBox":"F8B3B74E6E7C","ts":1786143610000,"state":"READY",
       "airtF":3.4,"airtC":-15.89,"deltap":0.01,
       "remaining":172800,"active":true,"SKU":"I1-123456"}
FieldMeaning
oktrue on success. Always present.
RACK_LOCATIONThe rack we have on file for the unit.
controlBoxThe control box installed right now. Opaque to you — quote it when reporting an issue.
tsTime of the reading, epoch milliseconds UTC. Always check it: an offline unit returns its last known values with an older timestamp.
stateCurrent unit state, e.g. READY, RUNNING, COMPLETE, PAUSE, BAD SEAL.
airtF / airtCAir temperature in both scales. Units measure in Celsius — read airtF if you work in Fahrenheit; do not assume an unlabelled value is °F.
deltapDifferential pressure across the unit (seal quality).
remainingSeconds remaining in the current cycle; 0 when not running.
activeWhether the unit is currently running.
SKUItem code stamped on the cycle in progress (always a string). Empty when no cycle is running — the unit clears it at cycle end.

3. Commands

Three commands are available: set_cycle, pause and resume. Commands are asynchronous: we validate and authorise the request, return 202, then apply it to the unit a moment later. Anything we cannot act on is rejected up front with a 4xx and an error code — we never return 202 for a command that would quietly do nothing. To confirm a change reached the unit, poll it afterwards.

Set cycle time and cycle details — set_cycle

ParameterNotes
INCUBATIONRun time in hours, whole or fractional (48, 12.5). Persists until changed; if the unit is offline it takes effect at its next check-in.
ITEM_NUMBER (or SKU)Your item code. Stamped on the unit for this cycle, and can supply the run time from your SKU library (below).
PALLET_TAG, POPallet / LP / LPN and purchase order, recorded against the cycle for reporting.

Send any combination — at least one. Only PO? Fine. Pallet details on a cycle that is already running, without touching its run time? Fine. If you send any of these fields without a COMMAND, we treat it as set_cycle.

curl -H "X-QF-API-Key: {your-api-key}" -H "User-Agent: YourCompany-WMS/1.0" \
  "https://qfreeze.com/wp-json/qf/v1/qfm?QFM_SERIAL=QFM-12107&RACK_LOCATION=2X-001B\
&COMMAND=set_cycle&INCUBATION=48&ITEM_NUMBER=I1-123456&PALLET_TAG=LP-4471&PO=PO12345"

→ 202 {"ok":true,"accepted":true,"QFM_SERIAL":"QFM-12107","RACK_LOCATION":"2X-001B",
       "controlBox":"F8B3B74E6E7C","COMMAND":"set_cycle",
       "applied":{"cycleTimeHours":48,"SKU":"I1-123456","PALLET_TAG":"LP-4471","PO":"PO12345"},
       "cycleTimeChanged":true}

applied lists exactly what we acted on and cycleTimeChanged says whether the run time moved — you never have to assume. An INCUBATION we cannot use rejects the whole call; we will not quietly apply just the metadata.

Cycle time from the SKU

Let the item code decide the run time instead of sending INCUBATION every call: &COMMAND=set_cycle&ITEM_NUMBER=I1-123456. The library builds itself from your calls: the first call that carries an item code with an explicit INCUBATION teaches us that item’s run time, and later calls can send the code alone. A new item without hours is registered but the run time is left unchanged — the reply says so with cycleTimeChanged:false and a warning. An explicit INCUBATION always wins.

Pause / resume fans

pause stops the fans and freezes the cycle timer in place; resume continues from exactly where it stopped. DURATION (minutes, optional) is a dead-man auto-resume: if your system never sends resume, the unit restores itself. We recommend sending it on every pause.

curl -H "X-QF-API-Key: {your-api-key}" \
  "https://qfreeze.com/wp-json/qf/v1/qfm?QFM_SERIAL=QFM-12107&RACK_LOCATION=2X-001B&COMMAND=pause&DURATION=30"

curl -H "X-QF-API-Key: {your-api-key}" \
  "https://qfreeze.com/wp-json/qf/v1/qfm?QFM_SERIAL=QFM-12107&RACK_LOCATION=2X-001B&COMMAND=resume"
Pause only holds on a unit that is actually running a cycle. An idle QFM returns itself to READY a moment after being paused — that is the unit behaving correctly, not a failed command. Check state and active first if it matters to your workflow.

Repeating a command

All three commands are safe to send again — set_cycle sets a value rather than adding to one, and pause/resume set a state. Re-sending after a timeout will not compound.

4. Error responses

Alert on the error code, not the message text — messages may be reworded, codes will not change.

{"ok":false,"error":"rack_mismatch",
 "message":"RACK_LOCATION does not match the rack recorded for QFM-12107. Refusing to act on a possibly wrong unit.",
 "expectedRackLocation":"2X-001B"}
HTTPerrorMeaningWhat to do
400missing_serial / missing_rack_locationA required identifier is absentFix the request
400bad_commandUnrecognised COMMANDFix the request
400nothing_to_setset_cycle with nothing to applySend at least one field
400poll_is_read_onlyCOMMAND=poll sent with fields that would writeOmit COMMAND, or use set_cycle
400bad_cycle_timeINCUBATION not a positive numberFix the value — nothing was applied
401unauthorizedMissing or wrong API keyCheck the header; alert
403not_authorizedThat unit is not on your accountCheck the serial; alert
404unknown_serialNo QFM with that serialTypo or decommissioned unit; alert
409rack_mismatchSerial is yours, rack does not matchAlert. Your mapping is stale — expectedRackLocation tells you ours
409ambiguous_serialSerial matches more than one unitContact us — a data issue on our side
502upstream_errorWe could not reach the monitoring platformRetry with backoff; alert if sustained

Retries: poll and all commands are safe to retry. Use exponential backoff on 502; do not retry 4xx — they will not succeed without a change to the request.

Identity & safety

  • Each facility authenticates with its own API key and is authorised to its own units only.
  • RACK_LOCATION must match the location mapped to that QFM_SERIAL or the request is refused — this prevents adjusting the wrong unit.
  • Units are addressed by QFM serial, which stays stable across control-box swaps; controlBox in every response shows which box answered.
  • Keep your API key out of email threads and shared files. QuickFreeze may rate-limit excessive request volumes.

Getting started

QuickFreeze issues your API key and the QFM_SERIAL ↔ RACK_LOCATION map for your units. A good first call is a poll against one live unit, then a deliberately wrong rack location to see 409 rack_mismatch come back. Send us your SKU list with cycle times if you want ITEM_NUMBER alone to set run times from day one.

To request access, contact your QuickFreeze representative.