{"id":425,"date":"2026-06-17T17:50:43","date_gmt":"2026-06-17T17:50:43","guid":{"rendered":"https:\/\/2026.quickfreeze.com\/?page_id=425"},"modified":"2026-06-17T17:50:43","modified_gmt":"2026-06-17T17:50:43","slug":"qfm-api","status":"publish","type":"page","link":"https:\/\/quickfreeze.com\/es\/qfm-api\/","title":{"rendered":"Gu\u00eda de la API de QFM"},"content":{"rendered":"<style>\n.qfm-api-guide{--qf-ink:#1f2d3d;--qf-blue:#0b3d59;--qf-accent:#1f7ac0;--qf-muted:#62788a;\n  font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif;\n  color:var(--qf-ink);max-width:920px;margin:0 auto;padding:8px 4px 48px;line-height:1.55;font-size:16px;}\n.qfm-api-guide *{box-sizing:border-box;}\n.qfm-api-guide h1{font-size:30px;color:var(--qf-blue);margin:0 0 6px;line-height:1.2;}\n.qfm-api-guide .qf-lede{font-size:17px;color:var(--qf-muted);margin:0 0 26px;}\n.qfm-api-guide h2{font-size:22px;color:var(--qf-blue);margin:34px 0 10px;padding-bottom:6px;border-bottom:2px solid #e3e9ef;}\n.qfm-api-guide h3{font-size:17px;color:var(--qf-blue);margin:22px 0 8px;}\n.qfm-api-guide p{margin:0 0 12px;}\n.qfm-api-guide a{color:var(--qf-accent);}\n.qfm-api-guide code{font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",monospace;font-size:.9em;\n  background:#eef4f9;color:#0b3d59;padding:1px 6px;border-radius:4px;}\n.qfm-api-guide pre{background:#0b2233;color:#d7f0ff;padding:14px 16px;border-radius:8px;overflow-x:auto;\n  font-size:13.5px;line-height:1.5;margin:10px 0 16px;white-space:pre;}\n.qfm-api-guide pre code{background:none;color:inherit;padding:0;}\n.qfm-api-guide table{border-collapse:collapse;width:100%;margin:10px 0 16px;font-size:14.5px;}\n.qfm-api-guide th,.qfm-api-guide td{text-align:left;padding:8px 10px;border-bottom:1px solid #e8eef3;vertical-align:top;}\n.qfm-api-guide th{color:var(--qf-muted);font-weight:600;background:#fafcfe;}\n.qfm-api-guide .qf-conn{display:grid;grid-template-columns:130px 1fr;gap:2px 14px;background:#fbfdff;\n  border:1px solid #e3e9ef;border-radius:10px;padding:16px 18px;margin:8px 0 8px;}\n.qfm-api-guide .qf-conn dt{color:var(--qf-muted);font-size:13px;text-transform:uppercase;letter-spacing:.03em;padding-top:7px;}\n.qfm-api-guide .qf-conn dd{margin:0;padding:4px 0;font-size:15px;}\n.qfm-api-guide .qf-pill{display:inline-block;background:#e3f6ea;color:#1d7a44;border-radius:999px;padding:2px 10px;font-size:13px;font-weight:600;}\n.qfm-api-guide .qf-pill.warn{background:#fff3e0;color:#b3640a;}\n.qfm-api-guide .qf-note{background:#fff8ec;border:1px solid #f3e2c0;border-radius:8px;\n  padding:12px 14px;font-size:14.5px;color:#6b5a36;margin:14px 0;}\n.qfm-api-guide .qf-card{border:1px solid #e3e9ef;border-radius:10px;padding:18px 20px;margin:18px 0;background:#fbfdff;}\n.qfm-api-guide .qf-req{color:#a12626;font-weight:600;}\n.qfm-api-guide ul{margin:0 0 14px;padding-left:22px;}\n.qfm-api-guide li{margin:4px 0;}\n@media(max-width:560px){.qfm-api-guide .qf-conn{grid-template-columns:1fr;}.qfm-api-guide .qf-conn dt{padding-top:10px;}}\n<\/style>\n<div class=\"qfm-api-guide\">\n\n<h1>API de QuickFreeze QFM<\/h1>\n<p class=\"qf-lede\">Read live status and control your QFM units from your WMS or building-automation\nsystem &mdash; set cycle times, record what is on the pallet, pause and resume fans.<\/p>\n\n<p>Your software addresses each unit by its <strong>N\u00famero de serie de QFM<\/strong> (printed on the unit)\nplus the <strong>rack location<\/strong> you have on file for it. Everything runs through one secured\nendpoint, scoped to your facility&rsquo;s own units. The serial is permanent &mdash; when a control box is\nreplaced, the API resolves the serial to whichever box is installed at that moment, so a swap needs no\nchange on your side.<\/p>\n\n<h2>Conexi\u00f3n<\/h2>\n<dl class=\"qf-conn\">\n  <dt>Punto final<\/dt><dd><code>https:\/\/qfreeze.com\/wp-json\/qf\/v1\/qfm<\/code><br><span style=\"color:#62788a;font-size:13px;\">the same address for every customer &mdash; your key scopes it to your units<\/span><\/dd>\n  <dt>Encabezado de autenticaci\u00f3n<\/dt><dd><code>X-QF-API-Key: {tu-clave-de-API}<\/code> &mdash; issued per facility; TLS 1.2+ required<\/dd>\n  <dt>M\u00e9todos<\/dt><dd>HTTP <strong>OBTENER<\/strong> (par\u00e1metros de consulta) o <strong>PUBLICAR<\/strong> (Cuerpo JSON)<\/dd>\n  <dt>Respuestas<\/dt><dd>Reads return <span class=\"qf-pill\">200<\/span> with the unit&rsquo;s live state; commands return <span class=\"qf-pill\">202<\/span> accepted. Every failure is JSON with a stable <code>error<\/code> code &mdash; a missing or wrong key returns <strong>401<\/strong>.<\/dd>\n  <dt>User-Agent<\/dt><dd>Please send an identifying agent, e.g. <code>YourCompany-WMS\/1.0<\/code>. 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.<\/dd>\n<\/dl>\n\n<h2>1. Identifying a unit<\/h2>\n<p>Every request carries <strong>two<\/strong> identifiers, and both must match our records:<\/p>\n<table>\n<tr><th>Par\u00e1metro<\/th><th>Example<\/th><th>Notas<\/th><\/tr>\n<tr><td><code>QFM_SERIAL<\/code><\/td><td><code>QFM-12107<\/code><\/td><td>Printed on the unit. Permanent &mdash; survives control-box swaps.<\/td><\/tr>\n<tr><td><code>UBICACI\u00d3N_DEL_RACK<\/code><\/td><td><code>2X-001B<\/code><\/td><td>The rack position we have recorded for that QFM.<\/td><\/tr>\n<tr><td><code>WAREHOUSE_ID<\/code><\/td><td><code>DC-EAST<\/code><\/td><td>Optional. Your own site or warehouse code, echoed back unchanged &mdash; a label for multi-site systems, not a permission.<\/td><\/tr>\n<\/table>\n<p>If the serial exists but the rack does not match, the request is <strong>refused<\/strong> and the reply\ntells you which rack we have on file (<code>409 rack_mismatch<\/code>). A stale or mis-keyed mapping in the\nWMS can never make us act on the wrong unit. A serial belonging to another customer returns\n<code>403<\/code>, even with a correct rack.<\/p>\n\n<h2>2. Poll a unit (read latest)<\/h2>\n<p><code>COMMAND=poll<\/code> is the default and may be omitted. Polling is read-only and cannot affect equipment.<\/p>\n<pre><code>curl -H \"X-QF-API-Key: {your-api-key}\" -H \"User-Agent: YourCompany-WMS\/1.0\" \\\n  \"https:\/\/qfreeze.com\/wp-json\/qf\/v1\/qfm?QFM_SERIAL=QFM-12107&RACK_LOCATION=2X-001B&COMMAND=poll\"\n\n&rarr; 200 {\"ok\":true,\"QFM_SERIAL\":\"QFM-12107\",\"RACK_LOCATION\":\"2X-001B\",\n       \"controlBox\":\"F8B3B74E6E7C\",\"ts\":1786143610000,\"state\":\"READY\",\n       \"airtF\":3.4,\"airtC\":-15.89,\"deltap\":0.01,\n       \"remaining\":172800,\"active\":true,\"SKU\":\"I1-123456\"}<\/code><\/pre>\n<table>\n<tr><th>Field<\/th><th>Significado<\/th><\/tr>\n<tr><td><code>ok<\/code><\/td><td><code>true<\/code> on success. Always present.<\/td><\/tr>\n<tr><td><code>UBICACI\u00d3N_DEL_RACK<\/code><\/td><td>The rack <em>we<\/em> have on file for the unit.<\/td><\/tr>\n<tr><td><code>controlBox<\/code><\/td><td>The control box installed right now. Opaque to you &mdash; quote it when reporting an issue.<\/td><\/tr>\n<tr><td><code>ts<\/code><\/td><td>Time of the reading, epoch milliseconds UTC. Always check it: an offline unit returns its last known values with an older timestamp.<\/td><\/tr>\n<tr><td><code>state<\/code><\/td><td>Current unit state, e.g. <code>LISTO<\/code>, <code>CORRER<\/code>, <code>COMPLETO<\/code>, <code>PAUSA<\/code>, <code>SELLADO DEFECTUOSO<\/code>.<\/td><\/tr>\n<tr><td><code>airtF<\/code> \/ <code>airtC<\/code><\/td><td>Air temperature in both scales. Units measure in Celsius &mdash; read <code>airtF<\/code> if you work in Fahrenheit; do not assume an unlabelled value is &deg;F.<\/td><\/tr>\n<tr><td><code>deltap<\/code><\/td><td>Differential pressure across the unit (seal quality).<\/td><\/tr>\n<tr><td><code>remaining<\/code><\/td><td>Seconds remaining in the current cycle; <code>0<\/code> when not running.<\/td><\/tr>\n<tr><td><code>active<\/code><\/td><td>Whether the unit is currently running.<\/td><\/tr>\n<tr><td><code>SKU<\/code><\/td><td>Item code stamped on the cycle in progress (always a string). Empty when no cycle is running &mdash; the unit clears it at cycle end.<\/td><\/tr>\n<\/table>\n\n<h2>3. Commands<\/h2>\n<p>Three commands are available: <code>set_cycle<\/code>, <code>pausa<\/code> y <code>curr\u00edculum<\/code>.\nCommands are <strong>asynchronous<\/strong>: we validate and authorise the request, return\n<span class=\"qf-pill\">202<\/span>, then apply it to the unit a moment later. Anything we cannot act on is\nrejected up front with a <code>4xx<\/code> and an <code>error<\/code> code &mdash; we never return 202 for a\ncommand that would quietly do nothing. To confirm a change reached the unit, poll it afterwards.<\/p>\n\n<h3>Set cycle time and cycle details &mdash; <code>set_cycle<\/code><\/h3>\n<table>\n<tr><th>Par\u00e1metro<\/th><th>Notas<\/th><\/tr>\n<tr><td><code>INCUBACI\u00d3N<\/code><\/td><td>Run time in <strong>horas<\/strong>, whole or fractional (<code>48<\/code>, <code>12.5<\/code>). Persists until changed; if the unit is offline it takes effect at its next check-in.<\/td><\/tr>\n<tr><td><code>N\u00daMERO DE ART\u00cdCULO<\/code> (or <code>SKU<\/code>)<\/td><td>Your item code. Stamped on the unit for this cycle, and can supply the run time from your SKU library (below).<\/td><\/tr>\n<tr><td><code>PALLET_TAG<\/code>, <code>PO<\/code><\/td><td>Pallet \/ LP \/ LPN and purchase order, recorded against the cycle for reporting.<\/td><\/tr>\n<\/table>\n<p>Send any combination &mdash; at least one. Only <code>PO<\/code>? Fine. Pallet details on a cycle that is\nalready running, without touching its run time? Fine. If you send any of these fields without a\n<code>COMANDO<\/code>, we treat it as <code>set_cycle<\/code>.<\/p>\n<pre><code>curl -H \"X-QF-API-Key: {your-api-key}\" -H \"User-Agent: YourCompany-WMS\/1.0\" \\\n  \"https:\/\/qfreeze.com\/wp-json\/qf\/v1\/qfm?QFM_SERIAL=QFM-12107&RACK_LOCATION=2X-001B\\\n&COMMAND=set_cycle&INCUBATION=48&ITEM_NUMBER=I1-123456&PALLET_TAG=LP-4471&PO=PO12345\"\n\n&rarr; 202 {\"ok\":true,\"accepted\":true,\"QFM_SERIAL\":\"QFM-12107\",\"RACK_LOCATION\":\"2X-001B\",\n       \"controlBox\":\"F8B3B74E6E7C\",\"COMMAND\":\"set_cycle\",\n       \"applied\":{\"cycleTimeHours\":48,\"SKU\":\"I1-123456\",\"PALLET_TAG\":\"LP-4471\",\"PO\":\"PO12345\"},\n       \"cycleTimeChanged\":true}<\/code><\/pre>\n<p><code>applied<\/code> lists exactly what we acted on and <code>cycleTimeChanged<\/code> says whether the\nrun time moved &mdash; you never have to assume. An <code>INCUBACI\u00d3N<\/code> we cannot use rejects the whole\ncall; we will not quietly apply just the metadata.<\/p>\n\n<h3>Cycle time from the SKU<\/h3>\n<p>Let the item code decide the run time instead of sending <code>INCUBACI\u00d3N<\/code> every call:\n<code>&amp;COMMAND=set_cycle&amp;ITEM_NUMBER=I1-123456<\/code>. The library builds itself from your calls: the\nfirst call that carries an item code <em>with<\/em> an explicit <code>INCUBACI\u00d3N<\/code> teaches us that\nitem&rsquo;s run time, and later calls can send the code alone. A new item without hours is registered but\nthe run time is left unchanged &mdash; the reply says so with <code>cycleTimeChanged:false<\/code> and a\n<code>warning<\/code>. An explicit <code>INCUBACI\u00d3N<\/code> always wins.<\/p>\n\n<h3>Detener \/ reanudar los ventiladores<\/h3>\n<p><code>pausa<\/code> stops the fans and <strong>freezes the cycle timer in place<\/strong>; <code>curr\u00edculum<\/code>\ncontinues from exactly where it stopped. <code>DURACI\u00d3N<\/code> (minutes, optional) is a dead-man\nauto-resume: if your system never sends <code>curr\u00edculum<\/code>, the unit restores itself. We recommend sending\nit on every pause.<\/p>\n<pre><code>curl -H \"X-QF-API-Key: {your-api-key}\" \\\n  \"https:\/\/qfreeze.com\/wp-json\/qf\/v1\/qfm?QFM_SERIAL=QFM-12107&RACK_LOCATION=2X-001B&COMMAND=pause&DURATION=30\"\n\ncurl -H \"X-QF-API-Key: {your-api-key}\" \\\n  \"https:\/\/qfreeze.com\/wp-json\/qf\/v1\/qfm?QFM_SERIAL=QFM-12107&RACK_LOCATION=2X-001B&COMMAND=resume\"<\/code><\/pre>\n<div class=\"qf-note\">Pause only holds on a unit that is actually running a cycle. An idle QFM returns\nitself to <code>LISTO<\/code> a moment after being paused &mdash; that is the unit behaving correctly, not a\nfailed command. Check <code>state<\/code> y <code>active<\/code> first if it matters to your workflow.<\/div>\n\n<h3>Repeating a command<\/h3>\n<p>All three commands are safe to send again &mdash; <code>set_cycle<\/code> sets a value rather than adding\nto one, and <code>pausa<\/code>\/<code>curr\u00edculum<\/code> set a state. Re-sending after a timeout will not compound.<\/p>\n\n<h2>4. Error responses<\/h2>\n<p>Alert on the <code>error<\/code> code, not the message text &mdash; messages may be reworded, codes will not change.<\/p>\n<pre><code>{\"ok\":false,\"error\":\"rack_mismatch\",\n \"message\":\"RACK_LOCATION does not match the rack recorded for QFM-12107. Refusing to act on a possibly wrong unit.\",\n \"expectedRackLocation\":\"2X-001B\"}<\/code><\/pre>\n<table>\n<tr><th>HTTP<\/th><th><code>error<\/code><\/th><th>Significado<\/th><th>What to do<\/th><\/tr>\n<tr><td>400<\/td><td><code>missing_serial<\/code> \/ <code>missing_rack_location<\/code><\/td><td>A required identifier is absent<\/td><td>Fix the request<\/td><\/tr>\n<tr><td>400<\/td><td><code>bad_command<\/code><\/td><td>Unrecognised <code>COMANDO<\/code><\/td><td>Fix the request<\/td><\/tr>\n<tr><td>400<\/td><td><code>nothing_to_set<\/code><\/td><td><code>set_cycle<\/code> with nothing to apply<\/td><td>Send at least one field<\/td><\/tr>\n<tr><td>400<\/td><td><code>poll_is_read_only<\/code><\/td><td><code>COMMAND=poll<\/code> sent with fields that would write<\/td><td>Omit <code>COMANDO<\/code>, or use <code>set_cycle<\/code><\/td><\/tr>\n<tr><td>400<\/td><td><code>bad_cycle_time<\/code><\/td><td><code>INCUBACI\u00d3N<\/code> not a positive number<\/td><td>Fix the value &mdash; nothing was applied<\/td><\/tr>\n<tr><td>401<\/td><td><code>unauthorized<\/code><\/td><td>Missing or wrong API key<\/td><td>Check the header; alert<\/td><\/tr>\n<tr><td>403<\/td><td><code>not_authorized<\/code><\/td><td>That unit is not on your account<\/td><td>Check the serial; alert<\/td><\/tr>\n<tr><td>404<\/td><td><code>unknown_serial<\/code><\/td><td>No QFM with that serial<\/td><td>Typo or decommissioned unit; alert<\/td><\/tr>\n<tr><td>409<\/td><td><code>rack_mismatch<\/code><\/td><td>Serial is yours, rack does not match<\/td><td><strong>Alert.<\/strong> Your mapping is stale &mdash; <code>expectedRackLocation<\/code> tells you ours<\/td><\/tr>\n<tr><td>409<\/td><td><code>ambiguous_serial<\/code><\/td><td>Serial matches more than one unit<\/td><td>Contact us &mdash; a data issue on our side<\/td><\/tr>\n<tr><td>502<\/td><td><code>upstream_error<\/code><\/td><td>We could not reach the monitoring platform<\/td><td>Retry with backoff; alert if sustained<\/td><\/tr>\n<\/table>\n<p style=\"font-size:14px;color:#62788a;\">Retries: poll and all commands are safe to retry. Use exponential backoff on 502; do not retry 4xx &mdash; they will not succeed without a change to the request.<\/p>\n\n<h2>Identidad y seguridad<\/h2>\n<ul>\n<li>Each facility authenticates with its own API key and is authorised to <strong>its own units only<\/strong>.<\/li>\n<li><code>UBICACI\u00d3N_DEL_RACK<\/code> debe coincidir con la ubicaci\u00f3n asociada a ese <code>QFM_SERIAL<\/code> or the request is refused &mdash; this prevents adjusting the wrong unit.<\/li>\n<li>Las unidades se identifican mediante <strong>Serie QFM<\/strong>, which stays stable across control-box swaps; <code>controlBox<\/code> in every response shows which box answered.<\/li>\n<li>Keep your API key out of email threads and shared files. QuickFreeze may rate-limit excessive request volumes.<\/li>\n<\/ul>\n\n<div class=\"qf-card\">\n<h3 style=\"margin-top:0;\">Primeros pasos<\/h3>\n<p>QuickFreeze issues your API key and the <code>QFM_SERIAL \u2194 UBICACI\u00d3N_EN_RACK<\/code> map for your units.\nA good first call is a poll against one live unit, then a deliberately wrong rack location to see\n<code>409 rack_mismatch<\/code> come back. Send us your SKU list with cycle times if you want\n<code>N\u00daMERO DE ART\u00cdCULO<\/code> alone to set run times from day one.<\/p>\n<p style=\"margin-bottom:0;\">Para solicitar acceso, comun\u00edquese con su representante de QuickFreeze.<\/p>\n<\/div>\n\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":0,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_seopress_titles_title":"","_seopress_titles_desc":"","_seopress_robots_index":"","_seopress_robots_follow":"","_seopress_robots_imageindex":"","_seopress_robots_snippet":"","_seopress_robots_primary_cat":"","_seopress_robots_breadcrumbs":"","_seopress_robots_freeze_modified_date":"","_seopress_robots_custom_modified_date":"","_seopress_robots_canonical":"","_seopress_social_fb_title":"","_seopress_social_fb_desc":"","_seopress_social_fb_img":"","_seopress_social_fb_img_attachment_id":0,"_seopress_social_fb_img_width":0,"_seopress_social_fb_img_height":0,"_seopress_social_twitter_title":"","_seopress_social_twitter_desc":"","_seopress_social_twitter_img":"","_seopress_social_twitter_img_attachment_id":0,"_seopress_social_twitter_img_width":0,"_seopress_social_twitter_img_height":0,"_seopress_redirections_value":"","_seopress_redirections_enabled":"","_seopress_redirections_enabled_regex":"","_seopress_redirections_logged_status":"","_seopress_redirections_param":"","_seopress_redirections_type":0,"_seopress_analysis_target_kw":"","_kadence_starter_templates_imported_post":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"class_list":["post-425","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/quickfreeze.com\/es\/wp-json\/wp\/v2\/pages\/425","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/quickfreeze.com\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/quickfreeze.com\/es\/wp-json\/wp\/v2\/types\/page"}],"replies":[{"embeddable":true,"href":"https:\/\/quickfreeze.com\/es\/wp-json\/wp\/v2\/comments?post=425"}],"version-history":[{"count":1,"href":"https:\/\/quickfreeze.com\/es\/wp-json\/wp\/v2\/pages\/425\/revisions"}],"predecessor-version":[{"id":426,"href":"https:\/\/quickfreeze.com\/es\/wp-json\/wp\/v2\/pages\/425\/revisions\/426"}],"wp:attachment":[{"href":"https:\/\/quickfreeze.com\/es\/wp-json\/wp\/v2\/media?parent=425"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}