{
  "info": {
    "name": "EMT Compute API — Scientific Experiments, Robotics & AI",
    "description": "# Put GPU computing to work in your research pipeline\n\n**EMT Compute**, developed by **EMT Aerospace Technologies S.r.l.**, connects on-demand GPU resources with scientific experiments, custom code, guided AI training and simulation workflows. EMT works across aerospace R&D, AI, robotics and autonomous systems from Lumezzane, Italy.\n\nExplore the platform at [emtcompute.com](https://emtcompute.com/?utm_source=postman&utm_medium=api_network&utm_campaign=research_integrations). For a research project or commercial integration, contact [info@emtaerospacetechnologies.com](mailto:info@emtaerospacetechnologies.com) with your workload, data size, target outcome and timing. We can scope a paid pilot with agreed technical objectives and budget.\n\n## Release 0.9.1: your code, your data, inspectable results\n\nPrepare a first scientific experiment with a guided configuration, or bring your own Python program, command and input files. Record equations, inputs, outputs and explanations with `ctx.explain(...)` or `EMT_CALCULATION_JSON`. Reports distinguish the execution environment from the device declared by your program; an allocated GPU alone does not establish that arbitrary code used it.\n\nFor AI training, inspect the reproducible recipe and export the complete event history. Recorded events can include training and evaluation loss, learning rate, gradient norm, runtime versions and observed dataset SHA-256 hashes. When resuming a remote dataset, the runner checks its bytes against recorded checkpoint evidence; older checkpoints may not have a comparison baseline.\n\nThe hosted MCP integration now includes four read-only training tools alongside experiments, quotes, GPU nodes and clusters. Prices and budgets are in EUR; no paid operation runs automatically from this collection.\n\n## What you can build\n\n- **Scientific experiments and simulations:** execute supported presets or your own code; inspect results and recorded calculation steps.\n- **AI development:** guided training with dataset, model, method and resource choices, plus checkpoints. The platform also deploys supported one-click models on a suitably sized single machine with an HTTPS endpoint.\n- **Robotics, drones and autonomy:** develop and compare control policies in simulation. Physical deployment and validation remain separate engineering work.\n- **GPU instances, nodes and clusters:** select compatible resources for independent experiments or distributed code. Multiple nodes do not automatically parallelize an arbitrary solver.\n- **Connected workflows:** integrate through the REST API, [MCP](https://emtcompute.com/mcp) or the [downloadable n8n workflow](https://emtcompute.com/integrations).\n\n## Start here\n\n1. Fork this collection into your own workspace.\n2. Run **01 — Discover resources** without a key. Catalog availability changes; an empty catalog is a valid result.\n3. For account requests, create a scoped key in your EMT account. Set `emt_api_key` in a **private, local environment value**. Never publish a key or save authenticated responses in a public workspace. Read requests need `read`; experiment quotes require `rent`.\n4. Explore your jobs and reports in folders 02–04. Set IDs from your own account. Requests with missing variables are skipped.\n5. Use folder 05 to request a fresh quote. **This starter collection does not start or rent compute.** Quotes do not reserve hardware. Prices, credit and budgets are in EUR. Monetary values use integer microEUR: divide by 1,000,000 for EUR. This collection sends `X-EMT-Currency: EUR`; older clients receive `426` until updated.\n\nThe API is documented in the [OpenAPI contract](https://emtcompute.com/openapi.json). This collection deliberately contains discovery, observation and quote requests. Workload launch and lifecycle operations are documented in that contract and in the n8n integration.\n\n## From a quote to an execution\n\nA paid launch requires current account terms, sufficient credit, service eligibility, available compatible hardware and a fresh quote. Review the quoted hourly cost and reserved amount before calling `POST /orders`, `POST /cluster-orders` or `POST /experiment-jobs`. Use the documented request schema and a stable `Idempotency-Key`; after an uncertain response, reconcile the existing operation instead of creating a new key and risking a duplicate rental. Check completion **and resource release**. Cancelling a job is not evidence that all resources have stopped billing.\n\nGuided training has its own prepare, start, stop and resume lifecycle. Model licensing and runtime compatibility apply; the model preset catalog is not an inference endpoint.\n\n## Inspect the calculation\n\nFor jobs executed with the reporting runtime, `GET /experiment-jobs/{id}/reports/{index}` returns a ZIP containing readable reports and provenance. Reports record configuration, runtime, hashes, results and program-declared calculation steps. Custom code must declare intermediate steps through `ctx.explain(...)` or `EMT_CALCULATION_JSON`. Reports do not reconstruct unrecorded operations or independently prove an arbitrary algorithm correct.\n\n## Response handling\n\n- `401`: missing or invalid key.\n- `403`: scope, account eligibility or terms requirement.\n- `404`: an owned resource or file is unavailable.\n- `409`: stale quote, changed capacity or reconciliation required.\n- `503`: service unavailable or not enabled; inspect the response before retrying.\n\nUse current quotes and account settings for pricing. There is no universal cost or performance guarantee for a research workload.\n\n**EMT Aerospace Technologies S.r.l.** · Lumezzane (BS), Italy · VAT IT04772590982 · REA BS-640314  \n[Company](https://www.emtaerospacetechnologies.com/) · [Platform](https://emtcompute.com/) · [Integrations](https://emtcompute.com/integrations) · [info@emtaerospacetechnologies.com](mailto:info@emtaerospacetechnologies.com)\n",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_postman_id": "daa1a023-8e7d-40bd-8094-ccfc84810cd0"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{emt_api_key}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://emtcompute.com/api/v1",
      "type": "string"
    },
    {
      "key": "emt_api_key",
      "value": "",
      "type": "string"
    },
    {
      "key": "order_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "experiment_job_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "training_job_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "result_index",
      "value": "0",
      "type": "string"
    },
    {
      "key": "node_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "cluster_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "cluster_node_1",
      "value": "",
      "type": "string"
    },
    {
      "key": "cluster_node_2",
      "value": "",
      "type": "string"
    },
    {
      "key": "training_after",
      "value": "0",
      "type": "string",
      "description": "Greatest event sequence already received. Start at 0 for a full export."
    },
    {
      "key": "training_latest",
      "value": "false",
      "type": "string",
      "description": "Keep false for paginated full history; true returns only the latest window."
    }
  ],
  "item": [
    {
      "name": "01 — Discover resources (no key)",
      "description": "Public catalog and platform metadata. These requests do not rent resources.",
      "item": [
        {
          "name": "Service health",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/health",
            "description": "GET /health",
            "auth": {
              "type": "noauth"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Public endpoint responds successfully\", function () { pm.expect(pm.response.code).to.equal(200); });"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "GPU catalog — current availability",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/catalog",
            "description": "GET /catalog",
            "auth": {
              "type": "noauth"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Public endpoint responds successfully\", function () { pm.expect(pm.response.code).to.equal(200); });"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Compatible cluster catalog",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/catalog/clusters",
            "description": "Free compatible whole nodes grouped by RDMA fabric",
            "auth": {
              "type": "noauth"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Public endpoint responds successfully\", function () { pm.expect(pm.response.code).to.equal(200); });"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "GPU templates",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/templates",
            "description": "GET /templates",
            "auth": {
              "type": "noauth"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Public endpoint responds successfully\", function () { pm.expect(pm.response.code).to.equal(200); });"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Ready runtime environments",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/environments",
            "description": "Public image and runtime choices for GPU setup.",
            "auth": {
              "type": "noauth"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Public endpoint responds successfully\", function () { pm.expect(pm.response.code).to.equal(200); });"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Supported one-click model presets",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/models",
            "description": "Public model, license, quantization and parallelism metadata. This is not an inference endpoint.",
            "auth": {
              "type": "noauth"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Public endpoint responds successfully\", function () { pm.expect(pm.response.code).to.equal(200); });"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Experiment service configuration",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/experiments/config",
            "description": "Returns the public GPU-compute mode flag. Account-specific launch eligibility still applies.",
            "auth": {
              "type": "noauth"
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Public endpoint responds successfully\", function () { pm.expect(pm.response.code).to.equal(200); });"
                ]
              }
            }
          ],
          "response": []
        }
      ]
    },
    {
      "name": "02 — Account and rental observation",
      "description": "Read your account and existing orders with a private read-scoped key.",
      "item": [
        {
          "name": "Account readiness",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/me",
            "description": "GET /me"
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "List existing rentals",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/orders",
            "description": "GET /orders"
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Rental state and release status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/orders/{{order_id}}",
            "description": "GET /orders/{id}"
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"order_id\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Rental logs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/orders/{{order_id}}/logs",
            "description": "GET /orders/{id}/logs"
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"order_id\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Rental metrics",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/orders/{{order_id}}/metrics",
            "description": "GET /orders/{id}/metrics"
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"order_id\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        }
      ]
    },
    {
      "name": "03 — Scientific experiments and calculation reports",
      "description": "Inspect existing jobs and retrieve recorded results. Your own job IDs are required.",
      "item": [
        {
          "name": "List experiment jobs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/experiment-jobs",
            "description": "Requires read scope. Returns items and available. Each job can contain a sweep of parameter sets."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Experiment progress and results metadata",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/experiment-jobs/{{experiment_job_id}}",
            "description": "Requires read scope. Includes lifecycle, progress, result indices and related order state. Completion and GPU release may occur at different times."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"experiment_job_id\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Download computation report ZIP",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/experiment-jobs/{{experiment_job_id}}/reports/{{result_index}}",
            "description": "Requires read scope. HTML printable as PDF, Markdown, JSON provenance and recorded-series CSV. Includes hashes, assigned node, runtime, method and program-declared calculation steps. Not an independent mathematical proof. Available for jobs run with the reporting runtime; older jobs have no reconstructed report."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"experiment_job_id\", \"result_index\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Download experiment result",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/experiment-jobs/{{experiment_job_id}}/results/{{result_index}}",
            "description": "Requires read scope. Gzip-compressed EMT result JSON for an available zero-based run index."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"experiment_job_id\", \"result_index\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Download experiment input",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/experiment-jobs/{{experiment_job_id}}/inputs/{{result_index}}",
            "description": "Requires read scope and job ownership. Zero-based index in job.files, retaining the original bytes for reproducibility."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"experiment_job_id\", \"result_index\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        }
      ]
    },
    {
      "name": "04 — Guided AI training observation",
      "description": "Inspect existing guided training jobs, recipes and events. Starting training is a separate paid operation.",
      "item": [
        {
          "name": "List training jobs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/training/jobs",
            "description": "List immutable training jobs"
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Training job status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/training/jobs/{{training_job_id}}",
            "description": "Read training job and associated GPU order"
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"training_job_id\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Reproducible training recipe",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/training/jobs/{{training_job_id}}/recipe",
            "description": "Export pinned runtime recipe"
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"training_job_id\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Training events",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/training/jobs/{{training_job_id}}/events?after={{training_after}}&latest={{training_latest}}",
            "description": "Read up to 100 events. For a full export start training_after=0 and training_latest=false, set training_after to the greatest returned seq, and repeat until items is empty. Keep the original export cutoff if collecting a snapshot of a running job. Events contain metrics, runtime and observed dataset hashes only when recorded; do not infer missing measurements. This is a private read and does not start training."
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"training_job_id\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        }
      ]
    },
    {
      "name": "05 — Quote a workload (no rental)",
      "description": "These POST requests calculate a quote without starting compute. A fresh quote and separate launch request are needed to rent.",
      "item": [
        {
          "name": "Quote a scientific experiment",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/experiment-quotes",
            "description": "Requires rent scope and experiment service availability. Does not rent a GPU. Returns ids (one quote per node), hourly and reserve in micro-EUR, expires in Unix milliseconds, nodeInfo and alternatives. Quotes last about two minutes; availability is rechecked at launch.\n\nIllustrative configuration only. Inspect hourly, reserve and expires; use the quote response rather than a fixed advertised price.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"count\": 1,\n  \"nodes\": 1,\n  \"minVram\": 8,\n  \"fp64\": false,\n  \"maxMinutes\": 10,\n  \"environment\": \"emt-lab\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Quote a selected GPU node",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/quotes",
            "description": "POST /quotes\n\nSet node_id from the current GPU catalog. The quote does not rent hardware.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"node\": \"{{node_id}}\",\n  \"count\": 1,\n  \"hours\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"node_id\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "Quote two compatible whole nodes",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-EMT-Currency",
                "value": "EUR",
                "type": "text"
              }
            ],
            "url": "{{base_url}}/cluster-quotes",
            "description": "Validate a selection of 2–16 whole nodes and reserve a price for 120 seconds\n\nChoose two distinct compatible node IDs from the same current cluster group. Each whole node includes all its GPUs.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cluster\": \"{{cluster_id}}\",\n  \"nodes\": [\n    \"{{cluster_node_1}}\",\n    \"{{cluster_node_2}}\"\n  ],\n  \"hours\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const required = [\"cluster_id\", \"cluster_node_1\", \"cluster_node_2\", \"emt_api_key\"];",
                  "const missing = required.filter(k => { const v = pm.variables.get(k); return v === undefined || v === null || String(v).trim() === \"\"; });",
                  "if (missing.length) { console.warn(\"Set private local values for: \" + missing.join(\", \")); pm.execution.skipRequest(); }"
                ]
              }
            }
          ],
          "response": []
        }
      ]
    }
  ]
}
