{"openapi":"3.1.0","info":{"title":"Axiom Rule API","version":"0.1.0","summary":"Rule search, retrieval, provenance, graph, and execution API.","description":"Initial contract for Axiom's rule-native API. Read endpoints are backed by fixtures, static RuleSpec indexes, or GitHub adapters; calculation can use the fixture runtime or an opt-in compiled-package runtime.","contact":{"name":"Axiom Foundation","url":"https://axiom-foundation.org"},"license":{"name":"LicenseRef-Axiom-Proprietary","url":"https://axiom-foundation.org"}},"jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","servers":[{"url":"https://api.staging.axiom-foundation.org","description":"Staging"},{"url":"https://api.axiom-foundation.org","description":"Production"}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"paths":{"/docs/validation":{"get":{"operationId":"getValidationDashboard","summary":"Validation dashboard (HTML): live latency, computation phases, run history, run-over-run diffs","security":[],"responses":{"200":{"description":"Dashboard page (text/html); data loads client-side from the admin endpoints with an admin:analytics key","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/docs":{"get":{"operationId":"getDocumentation","summary":"Human-readable developer documentation (HTML)","security":[],"responses":{"200":{"description":"Documentation page (text/html)","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/v1/health":{"get":{"operationId":"getHealth","summary":"Check API liveness","security":[],"responses":{"200":{"description":"API is live","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HealthResponse"}}}]}}}}}}},"/v1/ready":{"get":{"operationId":"getReadiness","summary":"Check dependency readiness","security":[],"responses":{"200":{"description":"API dependencies are ready","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ReadyResponse"}}}]}}}},"503":{"description":"One or more required dependencies are unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/version":{"get":{"operationId":"getVersion","summary":"Read deployed API version metadata","security":[],"responses":{"200":{"description":"Version metadata","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/VersionResponse"}}}]}}}}}}},"/v1/openapi.json":{"get":{"operationId":"getOpenApiDocument","summary":"Read the OpenAPI 3.1 document","security":[],"responses":{"200":{"description":"OpenAPI document","content":{"application/json":{"schema":{"type":"object","description":"The OpenAPI 3.1 document itself (not wrapped in the success envelope).","additionalProperties":true}}}}}}},"/v1/capabilities":{"get":{"operationId":"getCapabilities","summary":"Read machine-readable API, repository, and runtime capabilities","responses":{"200":{"description":"Capabilities manifest","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CapabilitiesResponse"}}}]}}}},"401":{"description":"A valid API key is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"API key lacks the required scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"API key rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/programs":{"get":{"operationId":"listPrograms","summary":"List available programs","responses":{"200":{"description":"Program list","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["programs"],"properties":{"programs":{"type":"array","items":{"$ref":"#/components/schemas/ProgramSummary"}}}}}}]}}}}}}},"/v1/runtime/packages":{"get":{"operationId":"listRuntimePackages","summary":"List programs executable by the configured calculation runtime","responses":{"200":{"description":"Runtime package list","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["packages"],"properties":{"packages":{"type":"array","items":{"$ref":"#/components/schemas/RuntimePackageSummary"}}}}}}]}}}}}}},"/v1/runtime/packages/{jurisdiction}/{program_id}":{"get":{"operationId":"getRuntimePackage","summary":"Read executable package inputs, outputs, aliases, and sample request","parameters":[{"name":"jurisdiction","in":"path","required":true,"schema":{"type":"string"}},{"name":"program_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Runtime package detail","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["package"],"properties":{"package":{"$ref":"#/components/schemas/RuntimePackageDetail"}}}}}]}}}},"404":{"description":"Runtime package not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/graph/compose":{"get":{"operationId":"composeRuleGraph","summary":"Compose a dependency graph for any encoded rule or file","description":"Builds a viewer-ready rule graph on demand by walking RuleSpec imports across the live encoding mirror, starting from a rule legal id (us:regulations/47-cfr/54/403#basic_lifeline_support_amount) or a file legal id. No compiled runtime package is required; the result reflects the encodings' declared structure, not an executable compilation.","parameters":[{"name":"focus","in":"query","required":true,"schema":{"type":"string"},"description":"Rule or file legal id: jurisdiction:bucket/path[#rule_name]."}],"responses":{"200":{"description":"Composed rule graph","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["graph","files","truncated"],"properties":{"graph":{"$ref":"#/components/schemas/ProgramGraph"},"files":{"type":"array","items":{"type":"string"}},"truncated":{"type":"boolean"}}}}}]}}}},"400":{"description":"focus is not a valid rule or file legal id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No encoded file exists for this focus","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Rulespec mirror not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runtime/packages/{jurisdiction}/{program_id}/graph":{"get":{"operationId":"getRuntimePackageGraph","summary":"Read the rule dependency graph (DAG) for an executable package","description":"Returns the program's rules, inputs, relations, and terminal outputs as a directed acyclic graph derived from the compiled artifact. Intended for visualizing how a program's outputs are computed.","parameters":[{"name":"jurisdiction","in":"path","required":true,"schema":{"type":"string"}},{"name":"program_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Program rule graph","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["graph"],"properties":{"graph":{"$ref":"#/components/schemas/ProgramGraph"}}}}}]}}}},"404":{"description":"No compiled graph is available for this program","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/analytics":{"get":{"operationId":"getAnalytics","summary":"Read in-process API usage analytics: per-route traffic, latency, per-key usage, and auth/security events","description":"Requires the admin:analytics scope. Counters are collected in process memory since instance start; they reset on deploy and are per-instance when the API runs on more than one instance.","parameters":[{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["local","global"]},"description":"Use global to merge flushed snapshots from every instance when a shared store is configured."}],"responses":{"200":{"description":"Analytics snapshot","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"oneOf":[{"$ref":"#/components/schemas/AnalyticsSnapshot"},{"type":"object","description":"Global view (?scope=global): one flushed snapshot per live instance.","required":["scope","store","instances"],"properties":{"scope":{"type":"string","const":"global"},"store":{"type":"string","description":"Name of the shared counter store."},"instances":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsSnapshot"}}}}]}}}]}}}},"401":{"description":"A valid API key is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"API key lacks the required scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared analytics store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/validation/migration":{"get":{"operationId":"getMigrationSummary","summary":"Migration ledger: partner demand (from the PE usage inventory) joined with Axiom's current variable and state coverage","responses":{"200":{"description":"Demanded variables with mapped/awaiting status, demand weights, and covered states","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}]}}}},"404":{"description":"Partner demand data is not bundled in this deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/validation/runs":{"post":{"operationId":"recordValidationRun","summary":"Publish a validation-run report (comparison harness) to the run history","description":"Requires the admin:analytics scope. The report's per-variable rows and per-case latency/timings are stored (180-day retention) with version identity (api_version, contract hash, PE model versions) for dashboard trends and run-over-run diffs.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","rows"],"properties":{"kind":{"type":"string"},"rows":{"type":"array","items":{"type":"object","additionalProperties":true}},"cases":{"type":"array","items":{"type":"object","additionalProperties":true}},"api_version":{"type":["string","null"]},"base_url":{"type":["string","null"]},"model_versions":{"type":["object","null"],"additionalProperties":true}}}}}},"responses":{"201":{"description":"Run recorded; returns the run summary","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ValidationRunSummary"}}}]}}}},"400":{"description":"Invalid run submission","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared run store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listValidationRuns","summary":"List validation-run summaries, newest first","responses":{"200":{"description":"Run summaries","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["runs"],"properties":{"runs":{"type":"array","items":{"$ref":"#/components/schemas/ValidationRunSummary"}}}}}}]}}}},"503":{"description":"The shared run store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/validation/runs/{run_id}":{"get":{"operationId":"getValidationRun","summary":"Read one validation run with its full per-variable rows and per-case timings","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Full run record","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}]}}}},"404":{"description":"Validation run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared run store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/usage":{"get":{"operationId":"getMonthlyUsage","summary":"Durable per-key request counts aggregated by calendar month (UTC)","description":"Requires the admin:analytics scope. Counters are retained ~13 months in the shared store. ?month=YYYY-MM selects a month (default: current).","parameters":[{"name":"month","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}}],"responses":{"200":{"description":"Per-key request counts for the month","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["month","usage","store"],"properties":{"month":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$","description":"Calendar month (UTC) the counts cover."},"usage":{"type":"array","items":{"$ref":"#/components/schemas/UsageRow"},"description":"Sorted by request count, descending."},"store":{"type":"string","description":"Name of the shared counter store."}}}}}]}}}},"400":{"description":"Invalid month format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared usage store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/audit":{"get":{"operationId":"getAuditTrail","summary":"Durable audit trail of admin actions (newest first, 90-day retention)","responses":{"200":{"description":"Audit entries","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["entries","store"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/AuditEntry"},"description":"Newest first; at most 200 entries."},"store":{"type":"string","description":"Name of the shared counter store."}}}}}]}}}},"503":{"description":"The shared audit store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/keys/trial":{"post":{"operationId":"issueTrialKey","summary":"Issue a self-service trial API key (raw value returned exactly once)","description":"No authentication required. Trial keys carry the rules:read, sources:read, graphs:read, and calculate:run scopes, expire after 14 days, default to a 10,000 compute-unit lifetime quota, and are rate-limited to 30 requests per minute. Issuance is capped per client and globally per day; only the key's sha256 hash is persisted, and issuance is recorded in the audit trail.","security":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","maxLength":120,"description":"Optional note describing what the key is for; stored as the key's note."}}}}}},"responses":{"201":{"description":"Trial key issued; the raw value appears only in this response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["key","key_id","scopes","expires_at","rate_limit","quota_cu","ttl_days","durable","warning"],"properties":{"key":{"type":"string","description":"The raw API key. Shown exactly once; only its hash is persisted."},"key_id":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time"},"rate_limit":{"type":"object","required":["requests","window_seconds"],"properties":{"requests":{"type":"integer"},"window_seconds":{"type":"integer"}}},"quota_cu":{"type":"integer","minimum":1},"ttl_days":{"type":"integer"},"durable":{"type":"boolean","description":"False when the store is per-instance memory (local development)."},"warning":{"type":"string"}}}}}]}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Trial key issuance limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared key store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/kill":{"get":{"operationId":"getTrialKillSwitches","summary":"Read durable trial traffic and mint kill switches","responses":{"200":{"description":"Current kill-switch state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"503":{"description":"The shared store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"setTrialKillSwitch","summary":"Engage or disengage a durable trial kill switch","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["switch","engaged","reason"],"properties":{"switch":{"type":"string","enum":["trial_traffic","trial_mint"]},"engaged":{"type":"boolean"},"reason":{"type":"string","minLength":1,"maxLength":500}}}}}},"responses":{"200":{"description":"Kill switch updated and audit record written","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/keys":{"post":{"operationId":"issueApiKey","summary":"Issue a new API key at runtime (raw value returned exactly once)","description":"Requires the admin:keys scope. Only the key's sha256 hash is persisted, to the shared store; the new key authenticates within ~15 seconds on all instances. Issuance is recorded in the audit trail.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueKeyRequest"}}}},"responses":{"201":{"description":"Key issued; the raw value appears only in this response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/IssuedKey"}}}]}}}},"400":{"description":"Invalid issuance request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"An API key with this id already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared key store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listApiKeys","summary":"List configured API key metadata (ids, scopes, status, limits) without key material","responses":{"200":{"description":"API key metadata list","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["keys","store"],"properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyMetadata"}},"store":{"type":"string","description":"Name of the shared counter store."}}}}}]}}}},"401":{"description":"A valid API key is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"API key lacks the required scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"API key configuration cannot be loaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/keys/{key_id}/revoke":{"post":{"operationId":"revokeApiKey","summary":"Revoke an API key at runtime via the shared store","description":"Runtime revocation takes effect within the revocation cache window (30s) per instance. Remove the key from the registry for permanence.","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Key revoked","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["id","revoked","durable","note"],"properties":{"id":{"type":"string","description":"Revoked key id."},"revoked":{"type":"boolean"},"durable":{"type":"boolean","description":"True when the revocation is shared across instances via a distributed store."},"note":{"type":"string","description":"Durability guidance for operators."}}}}}]}}}},"401":{"description":"A valid API key is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"API key lacks the required scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"API key id not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/parity/cases":{"get":{"operationId":"listParityCases","summary":"List canonical runtime parity cases, expected outputs, trace variables, and active-runtime support","responses":{"200":{"description":"Canonical parity case list","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["cases"],"properties":{"cases":{"type":"array","items":{"$ref":"#/components/schemas/ParityCase"}}}}}}]}}}},"401":{"description":"A valid API key is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/parity/run":{"post":{"operationId":"runParityCases","summary":"Run active-runtime-supported parity cases with comparison and trace outputs","responses":{"200":{"description":"Parity run summary, variable-level diffs, trace outputs, and calculation trace","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["summary","results","skipped_cases"],"properties":{"summary":{"type":"object","required":["total","matching","different","errored","skipped"],"properties":{"total":{"type":"integer"},"matching":{"type":"integer"},"different":{"type":"integer"},"errored":{"type":"integer"},"skipped":{"type":"integer"}}},"results":{"type":"array","items":{"$ref":"#/components/schemas/ParityRunResult"}},"skipped_cases":{"type":"array","items":{"type":"object","required":["id","description","program_id","jurisdiction","reason"],"properties":{"id":{"type":"string"},"description":{"type":["string","null"]},"program_id":{"type":"string"},"jurisdiction":{"type":"string"},"reason":{"type":"string"}}}}}}}}]}}}},"401":{"description":"A valid API key is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/search":{"post":{"operationId":"searchRules","summary":"Search encoded and source-linked rules","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}}},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchResults"}}}]}}}},"400":{"description":"Invalid search request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the configured size limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rules/{rule_id}":{"get":{"operationId":"getRule","summary":"Read one rule by stable rule id or citation path","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Rule detail","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["rule"],"properties":{"rule":{"$ref":"#/components/schemas/RuleDetail"}}}}}]}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rules/{rule_id}/sources":{"get":{"operationId":"getRuleSources","summary":"Read source and provenance references for one rule","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Source references","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["rule","sources"],"properties":{"rule":{"$ref":"#/components/schemas/RuleSummary"},"sources":{"type":"array","items":{"$ref":"#/components/schemas/SourceReference"}}}}}}]}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rules/{rule_id}/dependencies":{"get":{"operationId":"getRuleDependencies","summary":"Read upstream and downstream rule graph edges","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Rule dependency graph","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["rule","dependencies","dependents"],"properties":{"rule":{"$ref":"#/components/schemas/RuleSummary"},"dependencies":{"type":"array","items":{"type":"string"},"description":"Rule ids this rule depends on."},"dependents":{"type":"array","items":{"type":"string"},"description":"Rule ids that depend on this rule."}}}}}]}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/household/{country_id}/calculate":{"post":{"operationId":"calculateHouseholdCompat","summary":"Migration-only: calculate a PolicyEngine v1 wire-format household (existing PE partners)","description":"Migration surface for existing PolicyEngine household-API integrations; requires the dedicated compat:policyengine scope (ordinary keys receive 403). New integrations should use POST /v1/calculate with native Axiom variables. Accepts the PolicyEngine household API request shape (entity groups with period-keyed variables; null means compute) and mirrors its response envelope (status/message/result) so migrating partners can switch base URLs without code changes. The `axiom` sidecar reports which variables Axiom computed and which are not yet covered. Only country_id `us` is supported; `axes` are not supported. See docs/pe-household-compat.md.","parameters":[{"name":"country_id","in":"path","required":true,"schema":{"type":"string","enum":["us"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["household"],"properties":{"household":{"type":"object","description":"PolicyEngine v1 household: entity groups (people, tax_units, spm_units, families, households, marital_units) whose variables map period keys to values; null values are computed.","additionalProperties":true}}}}}},"responses":{"200":{"description":"PolicyEngine-shaped envelope: status, message, result (household with computed values filled), plus an axiom sidecar with computed/unsupported variables","content":{"application/json":{"schema":{"type":"object","required":["status","result","axiom"],"properties":{"status":{"type":"string","const":"ok"},"message":{"type":["string","null"]},"result":{"type":"object","additionalProperties":true},"axiom":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid body, unsupported country, axes present, or invalid household","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeCompatError"}}}},"422":{"description":"No executable Axiom package for the program","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeCompatError"}}}},"502":{"description":"The calculation engine failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeCompatError"}}}}}}},"/v1/calculate/batch":{"post":{"operationId":"calculateBatch","summary":"Run up to 25 calculations in one synchronous request","description":"Entries execute concurrently and results return positionally: results[i] corresponds to requests[i], each independently ok or error. Invalid entries fail the whole request with a positional message before execution.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"}}}},"responses":{"200":{"description":"Positional batch results with a summary","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["summary","results"],"properties":{"summary":{"type":"object","required":["total","succeeded","failed"],"properties":{"total":{"type":"integer"},"succeeded":{"type":"integer"},"failed":{"type":"integer"}}},"results":{"type":"array","items":{"$ref":"#/components/schemas/BatchResult"},"description":"Positional: results[i] corresponds to requests[i]."}}}}}]}}}},"400":{"description":"Invalid batch request (message names the failing entry)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the configured size limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/calculate":{"post":{"operationId":"submitCalculateJob","summary":"Submit up to 50 calculations as a detached async job","description":"Returns 202 with a job id and status URL. Execution proceeds with bounded concurrency; progress and results are written to the shared store and retained for 24 hours.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"}}}},"responses":{"202":{"description":"Job accepted; poll the status URL","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","required":["job_id","status","total","status_url","durable"],"properties":{"job_id":{"type":"string"},"status":{"type":"string","enum":["pending","running","succeeded","failed"],"description":"Job status at submission time."},"total":{"type":"integer","description":"Number of calculation entries submitted."},"status_url":{"type":"string","description":"Poll this path for progress and results."},"durable":{"type":"boolean","description":"True when the job record lives in a distributed store shared across instances."}}}}}]}}}},"400":{"description":"Invalid job request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared job store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{job_id}":{"get":{"operationId":"getCalculateJob","summary":"Poll a submitted calculation job","description":"Jobs are visible only to the API key that created them; unknown and foreign ids are both 404.","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status, progress, and results when finished","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/JobRecord"}}}]}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The shared job store is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/calculate":{"post":{"operationId":"calculateHousehold","summary":"Calculate rule outputs for a household","description":"Experimental calculation endpoint. The default runtime is fixture-backed for API integration and parity harness development; environments can opt into generic compiled RuleSpec package execution with package registry metadata.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalculateRequest"}}}},"responses":{"200":{"description":"Calculation result with outputs and trace","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CalculateResponse"}}}]}}}},"400":{"description":"Invalid calculation request or household","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the configured size limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Program is not supported by the configured runtime","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key"},"BearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"ValidationRunSummary":{"type":"object","description":"Summary of one published validation run: parity/drift/coverage totals, real average per-case latency, and version identity.","required":["id","kind","recorded_at","contract_hash","totals"],"properties":{"id":{"type":"string"},"kind":{"type":"string"},"recorded_at":{"type":"string"},"api_version":{"type":["string","null"]},"contract_hash":{"type":"string","description":"sha256 prefix of the serving OpenAPI document at record time"},"base_url":{"type":["string","null"]},"model_versions":{"type":["object","null"],"additionalProperties":true},"totals":{"type":"object","required":["variables","covered","parity_match","parity_diff","drift_diff","uncovered"],"properties":{"variables":{"type":"integer"},"covered":{"type":"integer"},"parity_match":{"type":"integer"},"parity_diff":{"type":"integer"},"drift_diff":{"type":"integer"},"uncovered":{"type":"integer"}}},"avg_case_latency_ms":{"type":["integer","null"]}}},"PeCompatError":{"type":"object","description":"PolicyEngine-envelope error used only by the household compatibility endpoint.","required":["status","message"],"properties":{"status":{"type":"string","const":"error"},"message":{"type":"string"},"result":{"type":"null"},"axiom":{"type":"object","additionalProperties":true}}},"Meta":{"type":"object","description":"Request metadata attached to every enveloped JSON response.","required":["request_id","api_version","environment"],"properties":{"request_id":{"type":"string","description":"Unique id for this request; also echoed in the x-request-id response header."},"api_version":{"type":"string","description":"Deployed API version.","examples":["0.1.0"]},"environment":{"type":"string","enum":["local","dev","staging","production"],"description":"Deployment environment that served the request."}}},"SuccessEnvelope":{"type":"object","description":"Success envelope wrapping every 2xx JSON payload. Endpoint responses compose this with an endpoint-specific `data` schema via allOf.","required":["status","data","meta"],"properties":{"status":{"type":"string","const":"ok"},"data":{"description":"Endpoint-specific payload."},"meta":{"$ref":"#/components/schemas/Meta"}}},"Error":{"type":"object","description":"Error envelope returned for every non-2xx JSON response.","required":["status","error","meta"],"properties":{"status":{"type":"string","const":"error"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code, e.g. invalid_request, unauthorized, insufficient_scope, rate_limited, not_found, payload_too_large, unsupported_program, unsupported_parameter, invalid_household, key_id_conflict, store_unavailable, not_ready, internal_error."},"message":{"type":"string","description":"Human-readable explanation."}}},"meta":{"$ref":"#/components/schemas/Meta"},"data":{"description":"Optional structured context, e.g. dependency detail on 503 /v1/ready or the local analytics snapshot when the shared store is unreachable."}}},"DependencyHealth":{"type":"object","description":"Health of one API dependency.","required":["name","status"],"properties":{"name":{"type":"string"},"status":{"type":"string","enum":["ready","degraded","unavailable"]},"detail":{"type":"string"}}},"HealthResponse":{"type":"object","description":"Liveness signal.","required":["service","live"],"properties":{"service":{"type":"string","const":"axiom-api"},"live":{"type":"boolean"}}},"ReadyResponse":{"type":"object","description":"Readiness of the API and its dependencies. Also embedded as `data` in the 503 error envelope when not ready.","required":["ready","status","source","dependencies"],"properties":{"ready":{"type":"boolean"},"status":{"type":"string","enum":["ready","degraded","unavailable"],"description":"Worst status across all dependencies."},"source":{"type":"string","description":"Active rule repository source, e.g. static-rulespec-index."},"dependencies":{"type":"array","items":{"$ref":"#/components/schemas/DependencyHealth"}}}},"VersionResponse":{"type":"object","required":["api_version","environment"],"properties":{"api_version":{"type":"string","examples":["0.1.0"]},"environment":{"type":"string","enum":["local","dev","staging","production"]}}},"CapabilitiesResponse":{"type":"object","description":"Machine-readable manifest of API version, endpoints, repository, and runtime capabilities.","required":["api_version","environment","openapi_url","endpoints","repository","runtime"],"properties":{"api_version":{"type":"string"},"environment":{"type":"string","enum":["local","dev","staging","production"]},"openapi_url":{"type":"string","examples":["/v1/openapi.json"]},"endpoints":{"type":"object","description":"Well-known endpoint paths.","required":["programs","search","rules","calculate","runtime_packages","parity_cases","parity_run"],"properties":{"programs":{"type":"string"},"search":{"type":"string"},"rules":{"type":"string"},"calculate":{"type":"string"},"runtime_packages":{"type":"string"},"parity_cases":{"type":"string"},"parity_run":{"type":"string"}}},"repository":{"type":"object","required":["source","status","program_count"],"properties":{"source":{"type":"string"},"status":{"type":"string","enum":["ready","degraded","unavailable"]},"program_count":{"type":"integer"}}},"runtime":{"type":"object","required":["name","status","package_count","packages","sample_requests"],"properties":{"name":{"type":"string"},"status":{"type":"string","enum":["ready","degraded","unavailable"]},"detail":{"type":"string"},"package_count":{"type":"integer"},"packages":{"type":"array","items":{"$ref":"#/components/schemas/RuntimePackageSummary"}},"sample_requests":{"type":"array","items":{"type":"object","required":["program_id","jurisdiction","sample_request"],"properties":{"program_id":{"type":"string"},"jurisdiction":{"type":"string"},"sample_request":{"$ref":"#/components/schemas/CalculateRequest"}}}}}}}},"ProgramSummary":{"type":"object","required":["id","name","jurisdiction","description","rule_count","status"],"properties":{"id":{"type":"string","examples":["co-snap"]},"name":{"type":"string"},"jurisdiction":{"type":"string","examples":["us-co"]},"description":{"type":"string"},"rule_count":{"type":"integer"},"status":{"type":"string","enum":["available","partial","planned"]}}},"RuleSummary":{"type":"object","required":["id","citation_path","name","jurisdiction","program_id","document_class","status","source_count"],"properties":{"id":{"type":"string","description":"Stable rule id.","examples":["us-az.des_faa5_na_eligibility_and_benefit_determination_gross_income_test"]},"citation_path":{"type":"string","description":"Human-oriented citation path; also resolvable as a rule id."},"name":{"type":"string"},"jurisdiction":{"type":"string"},"program_id":{"type":"string"},"document_class":{"type":"string","examples":["policy"]},"status":{"type":"string","enum":["encoded","source-linked","planned"]},"source_count":{"type":"integer"}}},"RuleDetail":{"description":"Full rule record: summary fields plus content and provenance.","allOf":[{"$ref":"#/components/schemas/RuleSummary"},{"type":"object","required":["summary","symbols","dependencies","dependents","version","provenance"],"properties":{"summary":{"type":"string","description":"Plain-language summary of the rule."},"symbols":{"type":"array","items":{"type":"string"},"description":"Variables defined or referenced by the rule."},"dependencies":{"type":"array","items":{"type":"string"},"description":"Rule ids this rule depends on."},"dependents":{"type":"array","items":{"type":"string"},"description":"Rule ids that depend on this rule."},"version":{"type":"string","examples":["current"]},"provenance":{"type":"object","required":["rulespec_repo","rulespec_path","rulespec_branch","source_release"],"properties":{"rulespec_repo":{"type":"string"},"rulespec_path":{"type":"string"},"rulespec_branch":{"type":"string"},"source_release":{"type":"string"}}}}}]},"SourceReference":{"type":"object","required":["id","citation_path","label","url","quote","source_type"],"properties":{"id":{"type":"string"},"citation_path":{"type":"string"},"label":{"type":"string"},"url":{"type":["string","null"]},"quote":{"type":["string","null"]},"source_type":{"type":"string","enum":["official","derived","repository"]}}},"SearchRequest":{"type":"object","required":["query"],"properties":{"query":{"type":"string","minLength":2,"maxLength":500,"description":"Full-text query over rule names, ids, and content."},"jurisdiction":{"type":"string","maxLength":120,"description":"Restrict results to one jurisdiction, e.g. us-az."},"program_id":{"type":"string","maxLength":120,"description":"Restrict results to one program, e.g. snap."},"limit":{"type":"number","description":"Maximum results to return; clamped to 1-50.","default":20}},"examples":[{"query":"gross income test","jurisdiction":"us-az","limit":3}]},"SearchResults":{"type":"object","required":["query","results"],"properties":{"query":{"type":"string","description":"The trimmed query that was executed."},"results":{"type":"array","items":{"$ref":"#/components/schemas/RuleSummary"}}}},"Household":{"type":"object","description":"Free-form household definition. By convention it contains entity-group objects keyed by entity id whose members carry input variables; the active runtime package (GET /v1/runtime/packages/{jurisdiction}/{program_id}) documents the entities, inputs, and aliases it reads.","additionalProperties":true,"properties":{"people":{"type":"object","additionalProperties":true,"description":"Person entities keyed by person id, e.g. { \"person_1\": { \"age\": 42 } }."},"spm_units":{"type":"object","additionalProperties":true,"description":"Benefit-unit entities keyed by unit id carrying unit-level inputs such as household_size, snap_gross_monthly_income, and shelter_costs."}}},"CalculateRequest":{"type":"object","required":["program_id","jurisdiction","household"],"properties":{"program_id":{"type":"string","minLength":1,"maxLength":120,"examples":["co-snap"]},"jurisdiction":{"type":"string","minLength":1,"maxLength":120,"examples":["us-co"]},"household":{"$ref":"#/components/schemas/Household"},"variables":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":200},"description":"Output variables to compute; defaults to the runtime package's default_outputs."}},"examples":[{"program_id":"co-snap","jurisdiction":"us-co","household":{"people":{"person_1":{"age":42},"person_2":{"age":9}},"spm_units":{"unit_1":{"household_size":2,"snap_gross_monthly_income":1200,"shelter_costs":900}}},"variables":["snap_benefit_amount","snap_net_income"]}]},"TraceEntry":{"type":"object","description":"One computed variable with the rule and sources that produced it.","required":["rule_id","variable","value","sources"],"properties":{"rule_id":{"type":"string"},"variable":{"type":"string"},"value":{"description":"Computed value (any JSON value)."},"sources":{"type":"array","items":{"type":"string"},"description":"Source references, e.g. rulespec:<rule_id>."}}},"CalculateResponse":{"type":"object","required":["engine","runtime","program_id","jurisdiction","outputs","trace","warnings"],"properties":{"engine":{"type":"string","const":"axiom"},"runtime":{"type":"object","required":["id","mode"],"properties":{"id":{"type":"string","examples":["fixture-snap-runtime"]},"mode":{"type":"string","enum":["fixture","compiled"]}}},"program_id":{"type":"string"},"jurisdiction":{"type":"string"},"outputs":{"type":"object","additionalProperties":true,"description":"Requested output variables keyed by variable name."},"trace":{"type":"array","items":{"$ref":"#/components/schemas/TraceEntry"}},"warnings":{"type":"array","items":{"type":"string"}}}},"ProgramGraph":{"type":"object","required":["rules","inputs","relations","ownOutputs","terminalOutputs"],"description":"Rule dependency graph derived from a compiled program artifact.","properties":{"rules":{"type":"array","description":"Derived and parameter rules with their dependencies and formula.","items":{"type":"object","required":["legalId","name","fileLegalId","kind"],"properties":{"legalId":{"type":"string"},"name":{"type":"string"},"fileLegalId":{"type":"string"},"kind":{"type":"string","enum":["derived","parameter"]},"entity":{"type":"string","nullable":true},"dtype":{"type":"string","nullable":true},"period":{"type":"string","nullable":true},"unit":{"type":"string","nullable":true},"source":{"type":"string","nullable":true},"sourceUrl":{"type":"string","nullable":true,"description":"URL of the rule's primary legal source, when known."},"ruleDeps":{"type":"array","items":{"type":"string"}},"inputDeps":{"type":"array","items":{"type":"string"}},"relationDeps":{"type":"array","items":{"type":"string"}},"formula":{"type":"string","nullable":true}}}},"inputs":{"type":"array","items":{"type":"object","required":["legalId","name","fileLegalId","entity"],"properties":{"legalId":{"type":"string"},"name":{"type":"string"},"fileLegalId":{"type":"string"},"entity":{"type":"string"},"relationLegalId":{"type":"string"}}}},"relations":{"type":"array","items":{"type":"object","required":["legalId","name","fileLegalId","memberInputIds"],"properties":{"legalId":{"type":"string"},"name":{"type":"string"},"fileLegalId":{"type":"string"},"memberInputIds":{"type":"array","items":{"type":"string"}}}}},"ownOutputs":{"type":"array","items":{"type":"string"}},"terminalOutputs":{"type":"array","items":{"type":"string"}}}},"RuntimePackageSummary":{"type":"object","required":["program_id","jurisdiction","runtime_id","mode","status","default_outputs"],"properties":{"program_id":{"type":"string"},"jurisdiction":{"type":"string"},"runtime_id":{"type":"string"},"mode":{"type":"string","enum":["fixture","compiled"]},"status":{"type":"string","enum":["ready","unavailable"]},"default_outputs":{"type":"array","items":{"type":"string"},"description":"Outputs computed when the request omits `variables`."},"output_count":{"type":"integer"},"entity_count":{"type":"integer"},"input_count":{"type":"integer"}}},"RuntimePackageDetail":{"description":"Executable package detail: inputs, outputs, aliases, and a sample request.","allOf":[{"$ref":"#/components/schemas/RuntimePackageSummary"},{"type":"object","required":["outputs","entities"],"properties":{"default_period":{"type":"string","examples":["2026-01"]},"outputs":{"type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"legal_id":{"type":"string"},"alias_for":{"type":"string","description":"Canonical output this name aliases."}}}},"entities":{"type":"array","items":{"type":"object","required":["entity","id_template","inputs"],"properties":{"entity":{"type":"string","examples":["Household"]},"id_template":{"type":"string"},"count":{"type":"integer"},"count_from":{"type":"string","description":"Input variable that determines the entity count."},"inputs":{"type":"array","items":{"type":"object","required":["name","dtype"],"properties":{"name":{"type":"string"},"dtype":{"type":"string","examples":["integer"]},"default":{"description":"Default value (any JSON value)."}}}},"relations":{"type":"array","items":{"type":"object","required":["name","tuple"],"properties":{"name":{"type":"string"},"tuple":{"type":"array","items":{"type":"string"}}}}}}}},"output_aliases":{"type":"object","additionalProperties":{"type":"string"},"description":"Alias output name to canonical output name."},"household_aliases":{"type":"object","additionalProperties":{"type":"string"},"description":"Alias household input name to canonical input name."},"sample_request":{"$ref":"#/components/schemas/CalculateRequest"}}}]},"BatchRequest":{"type":"object","required":["requests"],"properties":{"requests":{"type":"array","minItems":1,"maxItems":50,"items":{"$ref":"#/components/schemas/CalculateRequest"},"description":"At most 25 entries for POST /v1/calculate/batch and 50 for POST /v1/jobs/calculate."}}},"BatchResult":{"description":"One positional batch entry outcome: either a calculation result or an error.","oneOf":[{"type":"object","required":["status","result"],"properties":{"status":{"type":"string","const":"ok"},"result":{"$ref":"#/components/schemas/CalculateResponse"}}},{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","const":"error"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"unsupported_program, invalid_household, or runtime_error."},"message":{"type":"string"}}}}}]},"JobRecord":{"type":"object","description":"Async calculation job record (retained 24 hours).","required":["id","status","created_at","total","completed","api_key_id"],"properties":{"id":{"type":"string","examples":["job_e2e60409-c46f-443b-b344-1011c7a4558e"]},"status":{"type":"string","enum":["pending","running","succeeded","failed"]},"created_at":{"type":"string","format":"date-time"},"started_at":{"type":"string","format":"date-time"},"finished_at":{"type":"string","format":"date-time"},"total":{"type":"integer","description":"Total calculation entries."},"completed":{"type":"integer","description":"Entries finished so far."},"api_key_id":{"type":["string","null"],"description":"Id of the API key that created the job."},"results":{"type":"array","items":{"$ref":"#/components/schemas/BatchResult"},"description":"Present once the job has succeeded; positional."},"error":{"type":"string","description":"Present when the job failed."}}},"RateLimit":{"type":"object","required":["requests","window_seconds"],"properties":{"requests":{"type":"integer","minimum":1},"window_seconds":{"type":"integer","minimum":1}}},"IssueKeyRequest":{"type":"object","required":["id","scopes"],"properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{2,63}$","description":"3-64 lowercase letters, digits, hyphens, or underscores; must be unique."},"scopes":{"type":"array","minItems":1,"items":{"type":"string"},"description":"Granted scopes, e.g. [\"rules:read\", \"calculate:run\"] or [\"*\"]."},"owner":{"type":"string","maxLength":120},"note":{"type":"string","maxLength":500},"expires_at":{"type":"string","format":"date-time"},"rate_limit":{"$ref":"#/components/schemas/RateLimit"}}},"IssuedKey":{"type":"object","description":"Issuance result. The raw key value is returned exactly once; only its sha256 hash is persisted.","required":["key","entry","durable","warning"],"properties":{"key":{"type":"string","description":"Raw API key value; shown only in this response."},"entry":{"type":"object","required":["id","prefix","scopes","status","created_at"],"properties":{"id":{"type":"string"},"prefix":{"type":"string","description":"First characters of the key, for identification."},"scopes":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","revoked"]},"created_at":{"type":"string","format":"date-time"},"owner":{"type":"string"},"note":{"type":"string"},"expires_at":{"type":"string","format":"date-time"},"rate_limit":{"$ref":"#/components/schemas/RateLimit"}}},"durable":{"type":"boolean","description":"True when the key is persisted to a distributed store shared across instances."},"warning":{"type":"string"}}},"ApiKeyMetadata":{"type":"object","description":"API key metadata without key material.","required":["id","source","scopes","status","runtime_revoked"],"properties":{"id":{"type":"string"},"source":{"type":"string","enum":["environment","store"],"description":"Where the key is registered."},"scopes":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","revoked"]},"runtime_revoked":{"type":"boolean","description":"True when the key was revoked at runtime via the shared store."},"prefix":{"type":"string"},"rate_limit":{"$ref":"#/components/schemas/RateLimit"},"owner":{"type":"string"},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"AuditEntry":{"type":"object","description":"One durable admin audit record.","required":["at","action","target","actor","client","request_id"],"properties":{"at":{"type":"string","format":"date-time"},"action":{"type":"string","examples":["key.issued"]},"target":{"type":"string","description":"Acted-on resource id."},"actor":{"type":["string","null"],"description":"API key id that performed the action."},"client":{"type":["string","null"],"description":"Client IP when known."},"request_id":{"type":"string"},"detail":{"type":"object","additionalProperties":true,"description":"Action-specific context, e.g. granted scopes."}}},"UsageRow":{"type":"object","required":["api_key_id","requests"],"properties":{"api_key_id":{"type":"string"},"requests":{"type":"integer"}}},"AnalyticsSnapshot":{"type":"object","description":"In-process analytics snapshot for one API instance since instance start.","required":["instance_id","collected_since","generated_at","totals","auth_events","store_errors","routes","keys"],"properties":{"instance_id":{"type":"string"},"collected_since":{"type":"string","format":"date-time"},"generated_at":{"type":"string","format":"date-time"},"totals":{"type":"object","required":["requests","by_status"],"properties":{"requests":{"type":"integer"},"by_status":{"type":"object","additionalProperties":{"type":"integer"},"description":"Request counts keyed by HTTP status code."}}},"auth_events":{"type":"object","required":["unauthorized","insufficient_scope","rate_limited","auth_throttled","auth_misconfigured"],"properties":{"unauthorized":{"type":"integer"},"insufficient_scope":{"type":"integer"},"rate_limited":{"type":"integer"},"auth_throttled":{"type":"integer"},"auth_misconfigured":{"type":"integer"}}},"store_errors":{"type":"integer"},"routes":{"type":"array","description":"Per-route traffic and latency, sorted by request count.","items":{"type":"object","required":["route","requests","success","client_errors","server_errors","avg_duration_ms","max_duration_ms","latency_buckets"],"properties":{"route":{"type":"string","examples":["GET /v1/health"]},"requests":{"type":"integer"},"success":{"type":"integer"},"client_errors":{"type":"integer"},"server_errors":{"type":"integer"},"avg_duration_ms":{"type":"integer"},"max_duration_ms":{"type":"integer"},"latency_buckets":{"type":"object","additionalProperties":{"type":"integer"},"description":"Counts keyed by bucket, e.g. le_25ms, le_100ms, le_500ms, le_2000ms, gt_2000ms."}}}},"keys":{"type":"array","description":"Per-key usage, sorted by request count.","items":{"type":"object","required":["api_key_id","requests","rate_limited","last_used_at"],"properties":{"api_key_id":{"type":"string"},"requests":{"type":"integer"},"rate_limited":{"type":"integer"},"last_used_at":{"type":"string","format":"date-time"}}}}}},"ParityCase":{"type":"object","description":"Canonical parity case: an Axiom request with expected outputs and optional external engine comparisons.","additionalProperties":true,"required":["id","program_id","jurisdiction","runtime_supported","axiom_request","expected_axiom_outputs"],"properties":{"id":{"type":"string"},"description":{"type":["string","null"]},"program_id":{"type":"string"},"jurisdiction":{"type":"string"},"runtime_supported":{"type":"boolean","description":"True when the active runtime has a package for this case."},"variables":{"type":"array","items":{"type":"string"}},"axiom_request":{"$ref":"#/components/schemas/CalculateRequest"},"expected_axiom_outputs":{"type":"object","additionalProperties":true,"description":"Expected output values keyed by variable name."},"trace_variables":{"type":"array","items":{"type":"string"}},"notes":{"type":"array","items":{"type":"string"}},"external_comparisons":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"External engine comparison (engine, request, mappings, trace_mappings)."}},"tolerance":{"type":"object","additionalProperties":true,"description":"Numeric comparison tolerance, e.g. { amount: 0.01 }."}}},"ParityRunResult":{"type":"object","description":"Outcome of one parity case run: comparison against expected outputs, or the runtime error.","additionalProperties":true,"required":["id","program_id","jurisdiction","status"],"properties":{"id":{"type":"string"},"description":{"type":["string","null"]},"program_id":{"type":"string"},"jurisdiction":{"type":"string"},"status":{"type":"string","enum":["matching","different","errored"]},"outputs":{"type":"object","additionalProperties":true,"description":"Actual outputs for the compared variables."},"expected_outputs":{"type":"object","additionalProperties":true},"trace_outputs":{"type":"object","additionalProperties":true,"description":"Actual values for the case's trace variables."},"calculation_trace":{"type":"array","items":{"$ref":"#/components/schemas/TraceEntry"}},"notes":{"type":"array","items":{"type":"string"}},"comparison":{"type":"object","additionalProperties":true,"description":"Variable-level diff: status (matching|different) plus changed, missing, and extra arrays of { variable, expected, actual, delta? }."},"runtime":{"type":"object","additionalProperties":true,"description":"Runtime that executed the case ({ id, mode })."},"warnings":{"type":"array","items":{"type":"string"}},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}},"description":"Present when status is errored."}}}}}}