usestrix/strix · error · SpecParseError

Postman API rejected the key (401). Check POSTMAN_API_KEY.

Error message

Postman API rejected the key (401). Check POSTMAN_API_KEY.

What it means

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).

Source

Thrown at strix/utils/api_spec.py:259

    Raises :class:`SpecParseError` with an actionable message on auth, network,
    or shape errors.
    """
    if not api_key:
        raise SpecParseError(
            "POSTMAN_API_KEY is not set. Export a Postman API key (PMAK-…) to "
            "fetch from the Postman API, or pass a local collection file instead.",
        )
    try:
        response = requests.get(
            url,
            headers={"X-Api-Key": api_key, "Accept": "application/json"},
            timeout=_POSTMAN_FETCH_TIMEOUT,
        )
    except requests.RequestException as exc:
        raise SpecParseError(f"Failed to reach the Postman API: {exc}") from exc

    if response.status_code == 401:
        raise SpecParseError("Postman API rejected the key (401). Check POSTMAN_API_KEY.")
    if response.status_code == 404:
        raise SpecParseError(
            f"Postman {label} not found (404). Check the id and that the key can access it.",
        )
    if response.status_code != 200:
        raise SpecParseError(f"Postman API returned HTTP {response.status_code} for {label}.")
    try:
        payload = response.json()
    except ValueError as exc:
        raise SpecParseError(f"Postman API returned non-JSON for {label}") from exc
    if not isinstance(payload, dict):
        raise SpecParseError(f"Unexpected Postman API response shape for {label}")
    return payload


def fetch_postman_collection(collection_uid: str, api_key: str) -> dict[str, Any]:
    """Fetch a collection from the Postman API and return the raw collection dict.

View on GitHub (pinned to 8551339130)

Solutions

  1. Generate a fresh key in Postman (Workspace → API Keys) and update POSTMAN_API_KEY
  2. Verify it works: curl -H "X-Api-Key: $POSTMAN_API_KEY" https://api.getpostman.com/me
  3. Strip stray whitespace/newlines when copying the secret into CI

Example fix

# before: stale key
export POSTMAN_API_KEY="PMAK-old-key"

# after: rotate and re-export
export POSTMAN_API_KEY="$(cat /run/secrets/postman_key | tr -d '[:space:]')"
Defensive patterns

Strategy: try-catch

Validate before calling

import requests, os

def key_valid() -> bool:
    r = requests.get("https://api.getpostman.com/me",
                     headers={"X-Api-Key": os.environ["POSTMAN_API_KEY"]}, timeout=10)
    return r.status_code == 200

Try / catch

except SpecParseError as e:
    if "rejected the key (401)" in str(e):
        alert the operator to rotate POSTMAN_API_KEY; do not retry with the same key

Prevention

When it happens

Trigger: 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.

Common situations: Key rotated in Postman but the old value still in CI secrets; secret-manager whitespace/newline contamination; personal key used after leaving the team.

Related errors


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/3b0610073f7414d3. Report an issue: GitHub.