{"record":{"id":"f2c49680f9c3e90b","repo":"usestrix/strix","slug":"failed-to-reach-the-postman-api-exc","errorCode":null,"errorMessage":"Failed to reach the Postman API: {exc}","messagePattern":"Failed to reach the Postman API: (.+?)","errorType":"exception","errorClass":"SpecParseError","httpStatus":null,"severity":"error","filePath":"strix/utils/api_spec.py","lineNumber":256,"sourceCode":"def _postman_api_json(url: str, api_key: str, label: str) -> dict[str, Any]:\n    \"\"\"GET a Postman API resource and return the parsed JSON payload.\n\n    Raises :class:`SpecParseError` with an actionable message on auth, network,\n    or shape errors.\n    \"\"\"\n    if not api_key:\n        raise SpecParseError(\n            \"POSTMAN_API_KEY is not set. Export a Postman API key (PMAK-…) to \"\n            \"fetch from the Postman API, or pass a local collection file instead.\",\n        )\n    try:\n        response = requests.get(\n            url,\n            headers={\"X-Api-Key\": api_key, \"Accept\": \"application/json\"},\n            timeout=_POSTMAN_FETCH_TIMEOUT,\n        )\n    except requests.RequestException as exc:\n        raise SpecParseError(f\"Failed to reach the Postman API: {exc}\") from exc\n\n    if response.status_code == 401:\n        raise SpecParseError(\"Postman API rejected the key (401). Check POSTMAN_API_KEY.\")\n    if response.status_code == 404:\n        raise SpecParseError(\n            f\"Postman {label} not found (404). Check the id and that the key can access it.\",\n        )\n    if response.status_code != 200:\n        raise SpecParseError(f\"Postman API returned HTTP {response.status_code} for {label}.\")\n    try:\n        payload = response.json()\n    except ValueError as exc:\n        raise SpecParseError(f\"Postman API returned non-JSON for {label}\") from exc\n    if not isinstance(payload, dict):\n        raise SpecParseError(f\"Unexpected Postman API response shape for {label}\")\n    return payload\n\n","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/utils/api_spec.py#L238-L274","documentation":"SpecParseError raised when requests.get to api.getpostman.com raises RequestException — DNS failure, connection refused, TLS error, or the 30-second timeout (_POSTMAN_FETCH_TIMEOUT). The original exception is chained for detail.","triggerScenarios":"Running in an air-gapped or proxied network where api.getpostman.com is unreachable; corporate TLS interception with an untrusted CA; slow networks exceeding the 30s timeout.","commonSituations":"CI runner without internet egress; Docker sandbox with blocked outbound traffic; missing HTTPS_PROXY setting behind a corporate proxy.","solutions":["Verify connectivity: curl -sS https://api.getpostman.com -o /dev/null -w '%{http_code}'","Set HTTPS_PROXY/HTTP_PROXY if a corporate proxy is required","If egress is blocked, export the collection as a local JSON file and pass that instead"],"exampleFix":"# before: sandboxed CI with no egress\nstrix --api-spec postman:12345-abcdef\n\n# after: export locally, ship the file\ncurl -H \"X-Api-Key: $POSTMAN_API_KEY\" https://api.getpostman.com/collections/12345-abcdef | jq .collection > coll.json\nstrix --api-spec ./coll.json","handlingStrategy":"retry","validationCode":"import socket, os\n\ndef postman_reachable(timeout: float = 5) -> bool:\n    if os.environ.get(\"HTTPS_PROXY\"):\n        return True  # assume proxy handles egress\n    try:\n        socket.create_connection((\"api.getpostman.com\", 443), timeout=timeout).close()\n        return True\n    except OSError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    payload = _postman_api_json(url, key, label)\nexcept SpecParseError as e:\n    if \"Failed to reach\" in str(e) and is_transient(e.__cause__):\n        sleep with backoff once, then fall back to a local export on second failure","preventionTips":["Pre-verify egress to api.getpostman.com in CI before the scan job","Configure proxy env vars where required","Cache collection exports locally so scans do not depend on network"],"tags":["network","postman","timeout","proxy"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}