{
  "info": {
    "name": "ConstellationOS API",
    "description": "Contract-true collection for the ConstellationOS tenant API.\n\nAuth: set the `apiKey` collection variable to your tenant key; it is sent as the `x-api-key` header on every request except the open `/health*` endpoints. Tenant identity derives from the key, never from the hostname.\n\nEnvironments: `baseUrl` defaults to production. The `prodBaseUrl`, `devBaseUrl`, and `sandboxBaseUrl` variables document all three environments; point `baseUrl` at one of them, or create Postman environments named prod/dev/sandbox that each define `baseUrl` and `apiKey`.\n\nLimits to expect while exploring: 1000 records and 1 MB per telemetry POST, 100 link_ids per predictions call, per-IP 30 requests/min, per-tenant 60 requests/min. 429 and 503 responses carry a Retry-After header and a retry_after_seconds field.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      { "key": "key", "value": "x-api-key", "type": "string" },
      { "key": "value", "value": "{{apiKey}}", "type": "string" },
      { "key": "in", "value": "header", "type": "string" }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.constellation.space",
      "description": "Active base URL. Point at prodBaseUrl, devBaseUrl, or sandboxBaseUrl."
    },
    {
      "key": "apiKey",
      "value": "",
      "description": "Tenant API key (x-api-key header). Store real keys in a Postman environment or vault, not in the shared collection."
    },
    {
      "key": "prodBaseUrl",
      "value": "https://api.constellation.space",
      "description": "Production environment."
    },
    {
      "key": "devBaseUrl",
      "value": "https://dev.api.constellation.space",
      "description": "Development environment."
    },
    {
      "key": "sandboxBaseUrl",
      "value": "https://sandbox.api.constellation.space",
      "description": "Sandbox environment (hosts the live SNR inference endpoint)."
    }
  ],
  "item": [
    {
      "name": "Health",
      "description": "Liveness and subsystem health. Open endpoints: no API key required.",
      "auth": { "type": "noauth" },
      "item": [
        {
          "name": "GET /health",
          "request": {
            "method": "GET",
            "description": "Always returns 200 when the API is reachable.",
            "url": {
              "raw": "{{baseUrl}}/health",
              "host": ["{{baseUrl}}"],
              "path": ["health"]
            }
          }
        },
        {
          "name": "GET /health/telemetry",
          "request": {
            "method": "GET",
            "description": "Real downstream ping; 503 when degraded.",
            "url": {
              "raw": "{{baseUrl}}/health/telemetry",
              "host": ["{{baseUrl}}"],
              "path": ["health", "telemetry"]
            }
          }
        },
        {
          "name": "GET /health/topology",
          "request": {
            "method": "GET",
            "description": "Real downstream ping; 503 when degraded.",
            "url": {
              "raw": "{{baseUrl}}/health/topology",
              "host": ["{{baseUrl}}"],
              "path": ["health", "topology"]
            }
          }
        },
        {
          "name": "GET /health/predictions",
          "request": {
            "method": "GET",
            "description": "Real downstream ping; 503 when degraded.",
            "url": {
              "raw": "{{baseUrl}}/health/predictions",
              "host": ["{{baseUrl}}"],
              "path": ["health", "predictions"]
            }
          }
        }
      ]
    },
    {
      "name": "Topology",
      "description": "Latest-sample-per-entity projection over your telemetry.",
      "item": [
        {
          "name": "GET /topology",
          "request": {
            "method": "GET",
            "description": "measurement must be one of link, satellite, ground_station, weather, telemetry (400 invalid_input otherwise). freshness_seconds accepts 1 to 604800. as_of_utc defaults to now. Reads cap at 50000 rows; no pagination.",
            "url": {
              "raw": "{{baseUrl}}/topology?measurement=link&freshness_seconds=3600",
              "host": ["{{baseUrl}}"],
              "path": ["topology"],
              "query": [
                {
                  "key": "measurement",
                  "value": "link",
                  "description": "link | satellite | ground_station | weather | telemetry"
                },
                {
                  "key": "freshness_seconds",
                  "value": "3600",
                  "description": "1 to 604800"
                },
                {
                  "key": "as_of_utc",
                  "value": "2026-07-09T00:00:00Z",
                  "description": "ISO 8601; defaults to now",
                  "disabled": true
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "Telemetry",
      "description": "Telemetry ingestion. Body is a bare JSON array; tenant_key is stamped server-side from your API key.",
      "item": [
        {
          "name": "POST /telemetry",
          "request": {
            "method": "POST",
            "description": "At most 1000 records (413 batch_too_large) and 1 MB (413 request_too_large) per request. Responds 202 with {write_id, accepted_count, rejected_count, rejected_indices}. Partial rejections return rejected_indices into this body.",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "[\n  {\n    \"measurement\": \"link\",\n    \"time\": \"2026-07-09T12:00:00Z\",\n    \"tags\": { \"entity_id\": \"gs-madrid--sat-041\" },\n    \"fields\": { \"snr_db\": 12.4, \"elevation_deg\": 34.1 }\n  },\n  {\n    \"measurement\": \"ground_station\",\n    \"time\": \"2026-07-09T12:00:00Z\",\n    \"tags\": { \"entity_id\": \"gs-madrid\" },\n    \"fields\": { \"rain_rate_mm_h\": 0.0, \"status\": \"nominal\" }\n  }\n]",
              "options": {
                "raw": { "language": "json" }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/telemetry",
              "host": ["{{baseUrl}}"],
              "path": ["telemetry"]
            }
          }
        }
      ]
    },
    {
      "name": "Predictions",
      "description": "GET only; there is no POST /predictions. snr is the only shipped model family; value fields are p50, p10, p90. link_ids cap is 100 (400 too_many_link_ids).",
      "item": [
        {
          "name": "GET /predictions (cached)",
          "request": {
            "method": "GET",
            "description": "Cached read; returns a PredictionSet {model_family, captured_at, items[]}.",
            "url": {
              "raw": "{{baseUrl}}/predictions?model_family=snr&link_ids=gs-madrid--sat-041&horizon_minutes=15",
              "host": ["{{baseUrl}}"],
              "path": ["predictions"],
              "query": [
                { "key": "model_family", "value": "snr" },
                {
                  "key": "link_ids",
                  "value": "gs-madrid--sat-041",
                  "description": "Repeat this key for more ids; at most 100."
                },
                {
                  "key": "link_ids",
                  "value": "gs-svalbard--sat-007",
                  "disabled": true
                },
                { "key": "horizon_minutes", "value": "15" },
                {
                  "key": "as_of_utc",
                  "value": "2026-07-09T00:00:00Z",
                  "description": "ISO 8601; defaults to now",
                  "disabled": true
                }
              ]
            }
          }
        },
        {
          "name": "GET /predictions (live)",
          "request": {
            "method": "GET",
            "description": "Runs inference; returns an InferencePayload {schema_version, tenant_key, served_at, predictions[], provenance} where provenance carries served_from, model_version, feature_source, input window, telemetry_points_used, fill_policy, and horizons_minutes.",
            "url": {
              "raw": "{{baseUrl}}/predictions?model_family=snr&link_ids=gs-madrid--sat-041&live=true",
              "host": ["{{baseUrl}}"],
              "path": ["predictions"],
              "query": [
                { "key": "model_family", "value": "snr" },
                {
                  "key": "link_ids",
                  "value": "gs-madrid--sat-041",
                  "description": "Repeat this key for more ids; at most 100."
                },
                { "key": "live", "value": "true" }
              ]
            }
          }
        }
      ]
    }
  ]
}
