{"record":{"id":"3b0610073f7414d3","repo":"usestrix/strix","slug":"postman-api-rejected-the-key-401-check-postman","errorCode":null,"errorMessage":"Postman API rejected the key (401). Check POSTMAN_API_KEY.","messagePattern":"Postman API rejected the key \\(401\\)\\. Check POSTMAN_API_KEY\\.","errorType":"exception","errorClass":"SpecParseError","httpStatus":null,"severity":"error","filePath":"strix/utils/api_spec.py","lineNumber":259,"sourceCode":"    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\ndef fetch_postman_collection(collection_uid: str, api_key: str) -> dict[str, Any]:\n    \"\"\"Fetch a collection from the Postman API and return the raw collection dict.\n","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/utils/api_spec.py#L241-L277","documentation":"SpecParseError raised when the Postman API answers HTTP 401 for the X-Api-Key header — the key is invalid, revoked, or malformed. The request reached Postman and was authenticated-rejected, distinguishing it from a missing key (128) or a missing resource (131).","triggerScenarios":"An expired or deleted API key; a key copied with extra characters or quotes ('PMAK-…' truncated); a workspace-scoped token used against a global endpoint; the value of the wrong variable exported.","commonSituations":"Key rotated in Postman but the old value still in CI secrets; secret-manager whitespace/newline contamination; personal key used after leaving the team.","solutions":["Generate a fresh key in Postman (Workspace → API Keys) and update POSTMAN_API_KEY","Verify it works: curl -H \"X-Api-Key: $POSTMAN_API_KEY\" https://api.getpostman.com/me","Strip stray whitespace/newlines when copying the secret into CI"],"exampleFix":"# before: stale key\nexport POSTMAN_API_KEY=\"PMAK-old-key\"\n\n# after: rotate and re-export\nexport POSTMAN_API_KEY=\"$(cat /run/secrets/postman_key | tr -d '[:space:]')\"","handlingStrategy":"try-catch","validationCode":"import requests, os\n\ndef key_valid() -> bool:\n    r = requests.get(\"https://api.getpostman.com/me\",\n                     headers={\"X-Api-Key\": os.environ[\"POSTMAN_API_KEY\"]}, timeout=10)\n    return r.status_code == 200","typeGuard":null,"tryCatchPattern":"except SpecParseError as e:\n    if \"rejected the key (401)\" in str(e):\n        alert the operator to rotate POSTMAN_API_KEY; do not retry with the same key","preventionTips":["Run a /me health check once per CI job when a Postman key is used","Rotate keys on a schedule and update secret storage atomically","Trim whitespace when injecting secrets from files/vaults"],"tags":["authentication","postman","http-401"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}