Docs / Gateway

Inference Gateway

Complete reference for the Prova OpenAI-compatible inference proxy. See the gateway landing page for a live demo and quick-start.

Headers reference

X-Prova-KeyYour Prova API key. Required.
X-Prova-Policyobserve | flag | strict. Default: observe.
X-Prova-UpstreamOverride the upstream base URL. Default: https://api.openai.com/v1.optional
X-Prova-Retaintrue | false. Whether to write reasoning text to Prova storage. Default: false.optional
X-Prova-Samples1-5. Extraction consensus samples for this request. Default: 1.optional

Response headers

X-Prova-VerdictVALID | INVALID | UNVERIFIED
X-Prova-CertificateCertificate ID (PRV-YYYY-XXXX) or empty if UNVERIFIED
X-Prova-ConfidenceConfidence score 0-100
X-Prova-Failure-TypeCIRCULAR | CONTRADICTION | UNSUPPORTED_LEAP (INVALID only)INVALID only
X-Prova-ReasonHuman-readable reason (UNVERIFIED only)UNVERIFIED only

Webhook events

Prova can push events to your endpoint as certificates are issued. Set webhook URLs in the dashboard. All events are signed with HMAC-SHA256 using your webhook secret.

cert.issuedFired when any certificate is successfully issued.
{
  "event": "cert.issued",
  "created_at": "2026-04-19T12:00:00Z",
  "data": {
    "certificate_id": "PRV-2026-5573",
    "verdict": "VALID",
    "confidence_score": 97,
    "model": "gpt-4o"
  }
}
cert.invalidFired when a INVALID certificate is issued (subset of cert.issued). Subscribe to this for alerting.
{
  "event": "cert.invalid",
  "created_at": "2026-04-19T12:01:00Z",
  "data": {
    "certificate_id": "PRV-2026-BDC2",
    "verdict": "INVALID",
    "failure_type": "CIRCULAR",
    "confidence_score": 100,
    "model": "gpt-4o"
  }
}
gateway.blockedFired when strict policy blocks a response (HTTP 422 returned to caller).
{
  "event": "gateway.blocked",
  "created_at": "2026-04-19T12:02:00Z",
  "data": {
    "certificate_id": "PRV-2026-3DC6",
    "verdict": "INVALID",
    "failure_type": "UNSUPPORTED_LEAP",
    "policy": "strict"
  }
}

Verifying signatures (Node.js)

import crypto from 'crypto'

export function verifyProvaSignature(
  body: string,
  signature: string,
  secret: string,
): boolean {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  )
}

Verifying signatures (Python)

import hashlib, hmac

def verify_prova_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Test your webhook handler: POST /api/webhooks/test { "url": "https://your-endpoint" }

Streaming

Pass stream: true as normal. Tokens pass through immediately -- time-to-first-byte is identical to a direct OpenAI call. The Prova verdict arrives in the SSE trailer after the final [DONE] chunk:

data: {"choices":[{"delta":{"content":"..."},...}]}

data: [DONE]

# Trailer headers
X-Prova-Verdict: VALID
X-Prova-Certificate: PRV-2026-5573
X-Prova-Confidence: 97

With flag policy, a warning chunk is appended before[DONE] for INVALID responses. With strict policy, streaming is terminated with a 499 status and an error chunk.

Error codes

422strict policy: reasoning invalid. Body includes failure_type and certificate_id.
401Missing or invalid X-Prova-Key.
429Rate limit exceeded. Retry-After header included.
502Upstream model error. Prova proxied the error through.
503Prova unavailable. Fail-open: retry direct to upstream.