PAI Access

How to generate, use, and revoke Phoenix Internal API (PAI) credentials

What is PAI

PAI (Phoenix Internal API) is the unrestricted internal counterpart to the public /api/v1/* surface, served under /internal/v1/*. It exposes full, un-shaped scoring and enrichment data (no tier-based percentage shaping or field redaction) for other Phoenix services and trusted automation to consume. Because PAI bypasses data_shield.py tier enforcement, every credential and every /internal/v1/* call is gated to global admins only.

Generating a key pair (global-admin only)

PAI credentials are a two-part pair, generated together and shown on screen exactly once:

  1. Sign in as a global admin and open Admin Dashboard.
  2. Select the API Keys tab.
  3. Fill in an optional name and optional IP/domain restrictions, then submit.
  4. The API key and companion token are displayed once in the "Generated" panel — copy both immediately. A best-effort email with the companion token is also sent to your admin account (delivery failures never block generation).
Neither secret is stored in recoverable form on the server (both are hashed at rest). If you lose them, revoke the key and generate a new pair — there is no way to retrieve the original values later.

Call path 1: simple headers

Best for occasional callers. Send both secrets as headers on every request to any /internal/v1/* endpoint:

curl https://phxintel.security/internal/v1/scoring-weights \
  -H "x-api-key: phx_pai_..." -H "x-pai-token: phx_pait_..."

The server checks, in order: IP/domain allowlist (if configured on the key) → API key hash match → companion token hash match → key not revoked.

Call path 2: session JWT

Best for high-volume callers — exchange the root pair once for a short-lived signed session token, then replay only the token on subsequent calls instead of the long-lived secrets:

TOKEN=$(curl -s -X POST https://phxintel.security/internal/v1/pai/session \
  -H "x-api-key: phx_pai_..." -H "x-pai-token: phx_pait_..." | jq -r .access_token)

curl https://phxintel.security/internal/v1/scoring-weights \
  -H "Authorization: Bearer $TOKEN"

The session token is a signed JWT (default TTL: 900 seconds) carrying the key's own IP/domain allowlist, so the same per-key restrictions apply on both paths. Sessions cannot be re-minted from another session token — only from the original API key + companion token pair.

Session-token minting is only available where the operator has enabled it; when disabled, POST /internal/v1/pai/session returns 404.

IP and domain restrictions

When generating a key, you may optionally scope it to specific caller IP addresses or domains. Restrictions are enforced identically on the simple-header path and embedded into minted session JWTs, so a stolen session token cannot be replayed from an unlisted origin. Leaving the fields blank allows calls from any origin within the global PAI allowlist.

Revocation

From the API Keys tab's PAI keys list, click Revoke next to any key. Revocation:

Revocation is permanent. If the key is still needed, generate a new pair and update every caller before revoking the old one.

Security notes