Frequently Asked Questions

Table of Contents


Self-Hosted Gateway

Can I use the Axemere self-hosted gateway without paying for the Axemere Control Plane?

Yes. The self-hosted gateway runs completely standalone with no dependency on Axemere's hosted Control Plane. Policy bundles, credentials, and workload definitions live in local files or a self-hosted Postgres database. See the quickstart guides for standalone setup instructions.

How many self-hosted gateways can I deploy?

As many as you like. There is no limit on the number of self-hosted gateway instances. Each instance registers independently with the Control Plane (if you are using one) using its own node identity.

Does the self-hosted gateway send any information to Axemere?

When a self-hosted gateway is connected to the Axemere Control Plane (cloud-hosted or self-hosted), it periodically sends a minimal check-in message containing:

  • Node ID and software version
  • Last-seen timestamp
  • Aggregate request counts (total allowed, denied, errors); no request content

No request payloads, no credentials, and no attribution data (customer IDs, project IDs) are ever transmitted to Axemere. The check-in interval is controlled by MVGC_CHECKIN_IDLE_THRESHOLD (default: 60 seconds). If MVGC_CP_ADDR is unset, no check-in occurs at all.

Can I disable the check-in telemetry from my self-hosted gateway?

If you are running a fully air-gapped deployment (no MVGC_CP_ADDR set), no check-in ever occurs. If you are connected to a self-hosted Control Plane, set MVGC_CHECKIN_IDLE_THRESHOLD to a high value or use a network policy to restrict outbound gRPC traffic to approved hosts only.

Disabling check-in while connected to Axemere's hosted Control Plane requires an enterprise support agreement.

What features are available without the Control Plane?

Running the gateway in standalone mode (no MVGC_CP_ADDR) gives you:

FeatureStandaloneWith CP
Policy enforcement (allow, deny, rate_limit, require_approval, quarantine)
All 6 provider connectors (OpenAI, Anthropic, Gemini, Azure OpenAI, Cohere, generic HTTP)
Credential management (BYOK + alias)
Execution records (Postgres + JSONL)
Merkle ledger and inclusion proofs
Risk scoring
Budget enforcement
Delegation tokens
SIEM export (webhook, syslog)
Managed policy bundle delivery
Centralized workload and credential sync
Push-based config updates (no restart needed)
Multi-node fleet visibility
Org-level usage reporting

Managed Gateway

What is the Axemere Managed Gateway?

Axemere Managed Gateway is a hosted, multi-tenant gateway service operated by Axemere. You send requests to https://<env>.gcp.gw.axemere.ai authenticated with an API key. The Control Plane manages policy bundles, credentials, and workloads centrally: no infrastructure to run. See the Managed Gateway guide for setup.

How do I create an API key for the managed gateway?

API keys are created via the Axemere Control Plane admin API:

grpcurl -H "Authorization: Bearer $CP_ADMIN_TOKEN" \
  -d '{"org_id": "your-org-id", "name": "my-key", "expires_at": "2027-01-01T00:00:00Z"}' \
  $CP_GRPC_ADDR mvgc.v1.OrgService/CreateAPIKey

The plaintext key is returned once. Store it immediately; it cannot be retrieved again.


Integration Modes

What happens when I add an API key (credential) to the gateway?

In CP-managed deployments, registering a credential via UpsertCredential triggers automatic policy rule generation. The control plane creates auto.allow.{provider} rules in the connectors and credentials layers of your org's policy overlay. This means:

  1. You register the credential (e.g. provider: anthropic, mode: alias, secret_ref: ANTHROPIC_API_KEY).
  2. The CP generates auto.allow.anthropic rules in both the connectors and credentials layers.
  3. Requests to api.anthropic.com are now allowed without any manual policy changes.
  4. If you later delete the credential, the auto-rules are removed atomically.

In self-hosted (standalone) deployments, auto-rules are not generated. Use configs/policies/credential-rules.yaml to add the equivalent credential-selection rules manually.

What is the difference between path-prefix routing and X-MVGC-Target-Host?

Both tell the gateway which upstream AI provider to route to, but they work differently:

Path-prefix routingX-MVGC-Target-Host header
How to useSet SDK base URL: http://localhost:7080/proxy/openaiAdd header: X-MVGC-Target-Host: api.openai.com
Providersopenai, anthropic, gemini, cohere, perplexity (built-in registry)Any hostname
Azure OpenAINot supported (no fixed upstream host)Required
PriorityLower (checked third)Higher (checked first)
Recommended forStandard providers via SDK base URLAzure, custom endpoints, explicit override

The gateway checks resolution in this order: (1) X-MVGC-Target-Host header, (2) HTTP request Host header, (3) /proxy/{provider}/ path prefix, (4) HTTP 400 error.

Can I use different connection methods at the same time?

Yes. All three connection types can be active simultaneously. The gateway assigns connection_type automatically based on how each request arrives: direct_api for POST /v1/actions:execute calls, sdk_redirect for base-URL-redirected SDK traffic, and connect_proxy for OS-level HTTPS proxy connections. Each path goes through the same policy engine and produces execution records tagged with the appropriate connection_type and traffic_class.

What does transparent proxy mode do with requests that are not AI calls?

By default, the gateway passes non-AI traffic through without inspection. If MVGC_PROXY_MITM_ENABLED=true is set, the gateway logs the domain and request count for all outbound domains, which is useful for discovering which AI endpoints your applications call without your knowledge. No payload is retained in this scan-only mode.

Why does my direct/proxy-mode request to Gemini or Perplexity get rejected by the provider (400/401)?

The gateway does no path translation in proxy mode; the path after /proxy/{provider}/ is forwarded verbatim, so it must match that provider's real API convention. Gemini and Perplexity are the two built-in providers most likely to trip this: Perplexity's OpenAI-compat path has no /v1 prefix, and Gemini's native and OpenAI-compat surfaces take different paths and auth headers. See Direct/proxy-mode request returns a provider-side 400/401 for the exact paths and headers, and a header-based way to confirm what path the gateway actually dispatched.

Why is my stored credential being ignored even though I never enabled BYOK or OAuth?

Check whether Combined Passthrough is enabled for that provider. For providers where the gateway can't distinguish an OAuth subscription token from a BYOK API key (currently Anthropic and OpenAI — both send Authorization: Bearer <value>), the console offers a single Combined Passthrough toggle instead of separate OAuth/BYOK toggles. When it's on, any non-empty Authorization header from the client, including SDK placeholder values like "placeholder" or "unused", is forwarded upstream ahead of your stored credential, with no console or log indication that this happened. See Combined Passthrough for the full mechanism and how to check it.


Requests and Policies

Why does my request return 403 even though the policy says allow?

The most common causes:

  1. workload_id not registered — the gateway denies requests from unregistered workloads by default. Register the workload via PUT /v1/admin/workloads.
  2. org_id mismatch — if the gateway is running in managed mode, the org_id in the request must match the org associated with the API key.
  3. Target host not in policy — the policy targets layer restricts which hosts are allowed. Check the decision_trace in the response body for the denial reason.

How do I read the decision trace in a denied response?

All 403 responses from the gateway include a decision_trace object in the JSON body:

{
  "decision_trace": {
    "schema": "mvgc.decision_trace.v1",
    "decision": "deny",
    "reason_codes": ["target_not_allowed"],
    "evaluated_at": "2026-04-01T12:00:00Z",
    "attributes": {
      "policy_bundle_id": "default",
      "connector_id": "openai",
      "target_host": "api.openai.com"
    }
  }
}

The reason_codes array identifies the specific layer that denied the request. See the Troubleshooting guide for a complete list of reason codes.

What happens when require_approval fires?

The gateway returns HTTP 202 with an approval_id. Poll GET /v1/admin/approvals/{approval_id} until the status changes from pending to approved or denied. If MVGC_APPROVAL_ENABLED=false, a require_approval decision returns HTTP 403 instead. See the approval workflows guide.


SSL/TLS and Streaming

Does the gateway handle HTTPS (SSL/TLS) and HTTP?

Yes. In explicit mode (POST /v1/actions:execute), your application connects to the gateway over whatever protocol the gateway is listening on (HTTP or HTTPS). The gateway then makes outbound calls to the upstream provider over HTTPS regardless of how your application connected.

In transparent proxy mode, the gateway acts as an HTTP CONNECT proxy and can handle both plain HTTP and HTTPS tunnels.

Does the gateway support streaming responses (SSE)?

Yes. All five AI provider connectors (OpenAI, Anthropic, Google Gemini, Azure OpenAI, Cohere) support server-sent event (SSE) streaming. Set "stream": true in action.params and the gateway proxies the SSE stream directly to your client. See the streaming section in the Developer Integration Guide.


Billing and Limits

How is cost_usd calculated?

At request time, the gateway estimates cost using the model name and input token count from the request, plus the configured tokens_out_max estimate. When the upstream provider responds, the actual output token count is used instead of the estimate, and the final cost_usd in the execution record reflects real usage.

Pricing rates are defined per model in the gateway's estimator. Unknown models fall back to a conservative default rate. See the Pricing Reference for the full rate table.

What happens when an org exceeds its monthly request limit?

When overage_enabled is false (the default for all plans) and the org has reached its monthly_request_limit, the gateway returns HTTP 403 with reason: "monthly_request_limit_exceeded". When overage_enabled is true, requests continue beyond the limit and are billed at the overage rate. Contact Axemere to adjust limits or enable overage.