Management API Reference

For: Customers automating Axemere from IaC, CI/CD, or custom tooling.

A versioned, API-key-authenticated REST API exposing the same operations available in the customer console: credentials, providers, workloads, records, spend, policies, and more. Every managed gateway exposes this API at /mgmt/v1/. If you'd rather have an AI assistant drive the same operations, see the MCP Server Reference.

Internal engineering note: this page documents the customer-facing surface of the Management API + MCP Server Specification in the mvgc repo, which is the source of truth for the implementation (auth model, service architecture, DB schema).

Table of Contents


Base URL

Base URL: https://us.api.axemere.ai/mgmt/v1/

Self-hosted customers run the same endpoints locally via the gateway's own admin listener; see Self-Hosted Mode below.

Authentication

Authorization: Bearer mgk_<random>

Navigation: Create a management key at console.axemere.ai/automation → Management API tab, or via POST /mgmt/v1/keys itself (bootstrapping a first key still requires the console).

When you create a key, in the console or via POST /mgmt/v1/keys, you choose one of two access levels:

Access levelscopesGrants
Read["read"]List/get records, credentials, workloads, providers, spend, policies, nodes, and every other resource below
Read + Write["read", "write"]Everything in Read, plus create/update/delete credentials, toggle providers, update policies, configure rate limits, manage workloads, projects, alert channels, budgets, and every other write operation below

There is no write-only key: write always implies read; a key needs to see a resource before it can be reasoned about as changing it, so the console only ever mints ["read"] or ["read", "write"]. (Older keys created before this rule may still carry ["write"] alone; the API honors whatever scopes are stored on the key record, but new keys can no longer be created that way.)

Requests without a valid key receive 401. Requests with a key lacking the required scope receive 403 with code: insufficient_scope.

Key format: mgk_k3jmP9xQ2vT7bN5wL8hR4dF6sA1cE0gU3iY9oZ2mX7q: mgk (management) or mcpk (MCP) prefix, then a 43-character URL-safe base64 secret. The displayed key prefix (first 16 characters) identifies a key without exposing the secret. The plaintext key is shown exactly once at creation time; store it securely.

Pagination

Cursor-based. All list endpoints accept ?limit=N (default 50, max 500) and ?cursor=<opaque> from the previous response:

{
  "data": [...],
  "next_cursor": "eyJ...",
  "has_more": true
}

Error Format

{
  "error": {
    "code": "key_not_found",
    "message": "key not found or already revoked"
  }
}

HTTP status follows standard semantics: 400 bad request, 401 unauthenticated, 403 forbidden, 404 not found, 409 conflict, 429 rate limited, 500 internal. Errors surfaced from the underlying gateway call (rather than request validation) use the generic code gateway_error with the gateway's message passed through.


Keys

MCP equivalent: Keys — list-only; minting and revocation stay REST-only.

MethodPathScopeDescription
GET/mgmt/v1/keysreadList API keys for this org (no secret values)
POST/mgmt/v1/keyswriteCreate a key: returns the plaintext value once
DELETE/mgmt/v1/keys/{id}writeRevoke a key immediately (no token cache, takes effect on the next request)

POST /mgmt/v1/keys request body: scopes must be ["read"] or ["read", "write"]:

{
  "name": "ci-pipeline",
  "kind": "management",
  "scopes": ["read", "write"],
  "expires_at": "2027-01-01T00:00:00Z"
}

Response (key visible once only):

{
  "id": "key_01jwxyz...",
  "org_id": "org_01jabc...",
  "kind": "management",
  "name": "ci-pipeline",
  "key_prefix": "mgk_k3jmP9xQ",
  "scopes": ["read", "write"],
  "created_at": "2026-06-17T10:00:00Z",
  "expires_at": "2027-01-01T00:00:00Z",
  "key": "mgk_k3jmP9xQ2vT7bN5wL8hR4dF6sA1cE0gU3iY9oZ2mX7q"
}

Credentials

MCP equivalent: Credentials tools.

MethodPathScopeDescription
GET/mgmt/v1/credentialsreadList credentials (no secret values)
PUT/mgmt/v1/credentialswriteCreate or update a credential
PATCH/mgmt/v1/credentials/{id}writeUpdate credential scope/name
DELETE/mgmt/v1/credentials/{id}writeDelete a credential

Providers

MCP equivalent: Providers tools.

Each standard provider exposes up to three independently toggleable modes. Not all providers support all three (e.g. AWS Bedrock has no OAuth flow).

MethodPathScopeDescription
GET/mgmt/v1/providersreadList the org's addon catalog, including per-provider routing/BYOK/OAuth integration status
POST/mgmt/v1/providers/{provider}/routing/enablewriteEnable policy routing for a provider
POST/mgmt/v1/providers/{provider}/routing/disablewriteDisable policy routing
POST/mgmt/v1/providers/{provider}/byok/enablewriteEnable BYOK credential integration
POST/mgmt/v1/providers/{provider}/byok/disablewriteDisable BYOK credential integration
POST/mgmt/v1/providers/{provider}/oauth/enablewriteEnable OAuth integration (if supported)
POST/mgmt/v1/providers/{provider}/oauth/disablewriteDisable OAuth integration

Enabling an unsupported mode (e.g. OAuth on Bedrock) returns 400 with code: mode_not_supported.

GET /mgmt/v1/providers returns a flat list: one entry per addon, including one entry per provider integration mode (routing / BYOK / OAuth are three separate addon entries for the same provider, not a nested object):

{
  "data": [
    {
      "addon_id": "provider-openai",
      "display_name": "OpenAI — Routing",
      "description": "Route requests to OpenAI through policy.",
      "enabled": true,
      "category": "provider",
      "kind": "provider_integration",
      "logo_url": "https://axemere.ai/brand/providers/openai.png",
      "docs_url": "https://platform.openai.com/docs/api-reference"
    },
    {
      "addon_id": "credential-byok-openai",
      "display_name": "OpenAI — BYOK",
      "description": "Bring your own OpenAI API key.",
      "enabled": false,
      "category": "provider",
      "kind": "provider_integration"
    },
    {
      "addon_id": "credential-oauth-openai",
      "display_name": "OpenAI — OAuth",
      "description": "Connect OpenAI via OAuth instead of a static key.",
      "enabled": false,
      "category": "provider",
      "kind": "provider_integration"
    }
  ]
}

Match addon_id against the pattern used by the enable/disable endpoints below to find a specific provider+mode entry: provider-{provider} for routing, credential-byok-{provider} for BYOK, credential-oauth-{provider} for OAuth. A provider with no OAuth support (e.g. AWS Bedrock) simply has no credential-oauth-bedrock entry in the list; enabling an unsupported mode returns 400 with code: mode_not_supported rather than the entry existing in a disabled state.

This same endpoint also returns the org's policy-preset addons (kind: "policy_preset"); it is the full addon catalog, not a providers-only view. The base URL and internal connector configuration for standard providers are not exposed; they are Axemere-managed and not customer-configurable. Custom providers you register yourself are managed separately; see Custom Connectors below.

Custom Connectors (BYOC)

MCP equivalent: Providers tools — custom connector tools are grouped there.

Custom (bring-your-own-connector) providers carry customer-owned configuration: base URL, auth mode, model hints. They're a separate resource from standard providers and don't have an OAuth mode; only routing enable/disable applies.

MethodPathScopeDescription
GET/mgmt/v1/connectorsreadList custom connectors
POST/mgmt/v1/connectorswriteRegister a new custom connector
GET/mgmt/v1/connectors/{id}readGet custom connector config
PUT/mgmt/v1/connectors/{id}writeUpdate custom connector config
DELETE/mgmt/v1/connectors/{id}writeDelete a custom connector
POST/mgmt/v1/connectors/{id}/enablewriteEnable routing
POST/mgmt/v1/connectors/{id}/disablewriteDisable routing

POST /mgmt/v1/connectors request body:

{
  "name": "Internal Llama",
  "base_url": "https://llm.internal.example.com/v1",
  "auth_mode": "bearer_token",
  "default_model": "llama-3-70b",
  "enabled": true
}

Response:

{
  "id": "custom_01jwxyz...",
  "name": "Internal Llama",
  "base_url": "https://llm.internal.example.com/v1",
  "auth_mode": "bearer_token",
  "default_model": "llama-3-70b",
  "enabled": true,
  "created_at": "2026-06-17T10:00:00Z"
}

Workloads

MCP equivalent: Workloads tools.

MethodPathScopeDescription
GET/mgmt/v1/workloadsreadList workloads
PUT/mgmt/v1/workloadswriteCreate or update a workload
DELETE/mgmt/v1/workloads/{id}writeDelete a workload

Projects

MCP equivalent: Projects tools.

Projects are an attribution-scoping resource: a named grouping you can attach credentials and budget limits to, independent of workloads.

MethodPathScopeDescription
GET/mgmt/v1/projectsreadList projects for the org
POST/mgmt/v1/projectswriteCreate a new project
PUT/mgmt/v1/projects/{id}writeUpdate a project's display name, description, or status
DELETE/mgmt/v1/projects/{id}writeDelete a project

POST /mgmt/v1/projects request body:

{
  "project_id": "proj_checkout",
  "display_name": "Checkout Service",
  "description": "Payment and cart flows"
}

Response:

{
  "project_id": "proj_checkout",
  "org_id": "org_01jabc...",
  "display_name": "Checkout Service",
  "description": "Payment and cart flows",
  "status": "active",
  "created_at": "2026-06-17T10:00:00Z"
}

PUT /mgmt/v1/projects/{id} accepts a partial body: omit any field you don't want to change:

{
  "display_name": "Checkout & Cart",
  "status": "active"
}

Records

MCP equivalent: Records tools.

MethodPathScopeDescription
GET/mgmt/v1/recordsreadQuery execution records with filters
GET/mgmt/v1/records/{hash}readGet a single record by hash, including full policy trace

Query parameters for GET /mgmt/v1/records:

Time

ParameterTypeDescription
fromISO8601Start of time window (default: 24h ago)
toISO8601End of time window (default: now)

Request

ParameterTypeDescription
record_idUUIDExact match on record ID
decisionstringallow, deny, or error
traffic_classstringTraffic classification value
workload_idstringFilter by workload ID
providerstringProvider name (e.g. openai, bedrock, anthropic)
modelstringModel name (substring match)
action_typestringAction type value
record_tierstringRecord tier value
connection_typestringdirect, proxy, etc.
target_hoststringTarget hostname (e.g. api.anthropic.com)
stream_outcomestringStreaming result: complete, aborted, error
nodestringGateway node ID

Identity

ParameterTypeDescription
credential_idstringFilter by credential ID
api_key_idstringFilter by API key

Attribution

ParameterTypeDescription
projectstringAttribution project label
accountstringAttribution account label
customerstringAttribution customer label
label_keystringArbitrary label key (use with label_value)
label_valuestringArbitrary label value (use with label_key)

Cost and pagination

ParameterTypeDescription
min_cost_usdfloatMinimum request cost in USD
limitintResults per page (default 50, max 500)
cursorstringOpaque pagination cursor from previous response

Spend and Billing

MCP equivalent: Spend and Dashboard tools.

MethodPathScopeDescription
GET/mgmt/v1/spendreadTime-bucketed allow/deny request counts (despite the name, this is traffic volume, not a dollar figure; see below)
GET/mgmt/v1/billing/summaryreadBilling period summary with cost, request, and token totals

GET /mgmt/v1/spend query parameter: ?window=1h|6h|24h (default 24h; any other value falls back to the 1h bucketing). Response:

{
  "org_id": "org_01jabc...",
  "from": "2026-07-04T18:00:00Z",
  "to": "2026-07-05T18:00:00Z",
  "bucket": "2h",
  "buckets": [
    { "time": "2026-07-04T18:00:00Z", "allow_count": 412, "deny_count": 3 },
    { "time": "2026-07-04T20:00:00Z", "allow_count": 389, "deny_count": 1 }
  ]
}

Naming note: /mgmt/v1/spend currently returns request-volume buckets, not USD spend. For dollar figures, use /mgmt/v1/billing/summary below.

GET /mgmt/v1/billing/summary query parameters: ?from=<YYYY-MM-DD>&to=<YYYY-MM-DD> (both required together; omit both for the current billing period). Response:

{
  "period": "2026-06",
  "period_start": "2026-06-01",
  "total_cost_usd": "42.7100",
  "total_requests": 18420,
  "total_tokens_in": 5210300,
  "total_tokens_out": 1180450,
  "by_workload": {
    "wl_checkout": { "cost_usd": "12.0400", "requests": 4200, "tokens_in": 900000, "tokens_out": 210000 }
  },
  "by_connector": {
    "openai": { "cost_usd": "20.1000", "requests": 9000, "tokens_in": 3000000, "tokens_out": 700000 }
  },
  "by_model": {
    "gpt-4o": { "cost_usd": "15.5000", "requests": 6000, "tokens_in": 2000000, "tokens_out": 500000 }
  },
  "by_day": { "2026-06-01": "1.4000" }
}

Policies

MCP equivalent: Policies tools.

MethodPathScopeDescription
GET/mgmt/v1/policiesreadList policy bundles
PUT/mgmt/v1/policieswriteUpsert org policy overlay
POST/mgmt/v1/policies/reloadwriteForce policy reload on the gateway

Rate Limits

MCP equivalent: Rate Limits tools.

MethodPathScopeDescription
GET/mgmt/v1/ratelimit/configreadCurrent rate limit configuration
PUT/mgmt/v1/ratelimit/configwriteUpdate rate limit configuration
GET/mgmt/v1/ratelimit/keysreadActive rate limit key states

Approvals and Quarantine

MCP equivalent: Approvals and Quarantine tools.

MethodPathScopeDescription
GET/mgmt/v1/approvalsreadPending approval requests
POST/mgmt/v1/approvals/{id}/approvewriteApprove a request
POST/mgmt/v1/approvals/{id}/denywriteDeny a request
GET/mgmt/v1/quarantinereadQuarantined entries
POST/mgmt/v1/quarantine/{id}/releasewriteRelease a quarantine entry

Dashboard and Gateway Health

MCP equivalent: Spend and Dashboard tools and Nodes.

The same summary data visible on the gateway dashboard: request/decision counts plus pending approvals and quarantine entries for a time window.

MethodPathScopeDescription
GET/mgmt/v1/dashboardreadRequest, decision, approval, and quarantine counts for a time window
GET/mgmt/v1/dashboard/decisionsreadDecision counts broken down by decision type
GET/mgmt/v1/nodesreadConnected gateway nodes and their status

Both dashboard endpoints accept ?from=<ISO8601>&to=<ISO8601> (default: last 24h).

GET /mgmt/v1/dashboard response:

{
  "org_id": "org_01jabc...",
  "from": "2026-07-04T18:00:00Z",
  "to": "2026-07-05T18:00:00Z",
  "total_requests": 18420,
  "allow_count": 18100,
  "deny_count": 320,
  "approval_count": 2,
  "quarantine_count": 0
}

GET /mgmt/v1/dashboard/decisions response:

{
  "org_id": "org_01jabc...",
  "from": "2026-07-04T18:00:00Z",
  "to": "2026-07-05T18:00:00Z",
  "decisions": [
    { "decision": "allow", "count": 18100 },
    { "decision": "deny", "count": 320 }
  ]
}

Attribution

MCP equivalent: Attribution tools.

Query attribution-labelled spend and request data, broken down by project, account, customer, or arbitrary label key.

MethodPathScopeDescription
GET/mgmt/v1/attribution/summaryreadSpend and request counts by attribution field
GET/mgmt/v1/attribution/labelsreadAll label keys seen in this org's records
GET/mgmt/v1/attribution/labels/{key}readValues and counts for a specific label key

Query parameter for /mgmt/v1/attribution/summary and /mgmt/v1/attribution/labels: ?from=<ISO8601> (start of window; open-ended through now). There is no to or group_by parameter today; the response includes all attribution dimensions together rather than a single grouped breakdown.

SIEM Export Destinations

MCP equivalent: SIEM Export Destinations tools.

Configure where the gateway ships execution records (webhook or syslog): the programmatic equivalent of the SIEM export UI in the console.

MethodPathScopeDescription
GET/mgmt/v1/export/destinationsreadList configured SIEM export destinations
POST/mgmt/v1/export/destinationswriteCreate an export destination
PUT/mgmt/v1/export/destinations/{id}writeUpdate an export destination
DELETE/mgmt/v1/export/destinations/{id}writeDelete an export destination
POST/mgmt/v1/export/destinations/{id}/testwriteSend a test event and confirm delivery

Provider Pricing

MCP equivalent: Provider Pricing tools.

MethodPathScopeDescription
GET/mgmt/v1/pricingreadList pricing configs for all providers

Read-only, on both REST and MCP. This endpoint is for reading your current effective per-model rates (e.g. to project cost in IaC); there is no write path on either surface. provider_pricing is a single global table shared across every org on the managed fleet, not a per-org resource, so pricing writes are restricted to NOC operators via cert-gated admin routes and are not reachable through a customer-held mgk_/mcpk_ key at all. If you need a rate corrected, go through support.

Org Defaults

MCP equivalent: Org Defaults tools.

Read and update the gateway-level defaults for attribution: the default workload and project applied to requests that don't carry explicit attribution.

MethodPathScopeDescription
GET/mgmt/v1/org/defaultsreadCurrent org-level attribution defaults
PATCH/mgmt/v1/org/defaultswriteUpdate org-level attribution defaults

Budget Alert Channels

MCP equivalent: Alert Channels tools.

Delivery destinations for budget alerts: Slack, Microsoft Teams, Google Chat, Discord, or email. A channel is a reusable target; wire it to specific budget limits via Budget Alert Subscriptions below.

MethodPathScopeDescription
GET/mgmt/v1/alerts/channelsreadList alert channels for the org
POST/mgmt/v1/alerts/channelswriteCreate an alert channel
GET/mgmt/v1/alerts/channels/{id}readGet a single alert channel
PUT/mgmt/v1/alerts/channels/{id}writeUpdate an alert channel (partial, only fields present in the body are changed)
DELETE/mgmt/v1/alerts/channels/{id}writeDelete an alert channel
POST/mgmt/v1/alerts/channels/{id}/testwriteSend a synthetic test alert through the channel to verify delivery

kind is one of slack, teams, google_chat, discord, email. config shape depends on kind:

  • slack / teams / google_chat / discord{"webhook_url": "https://..."}
  • email{"to_addresses": ["ops@example.com", "alerts@example.com"]}

config.webhook_url is a secret: GET /mgmt/v1/alerts/channels and GET /mgmt/v1/alerts/channels/{id} return it masked as "••••••••", the same masking convention used for credential secret_ref. There is no endpoint that returns a webhook URL unmasked after creation; keep your own copy. config.to_addresses (the email kind) is not a secret and is never masked.

POST /mgmt/v1/alerts/channels request body:

{
  "name": "Platform Team Slack",
  "kind": "slack",
  "config": { "webhook_url": "https://hooks.slack.com/services/T000/B000/XXXX" }
}

Response (the create response echoes back the value you just sent, unmasked, since you already have it):

{
  "channel_id": "chan_01jwxyz...",
  "org_id": "org_01jabc...",
  "name": "Platform Team Slack",
  "kind": "slack",
  "config": { "webhook_url": "https://hooks.slack.com/services/T000/B000/XXXX" },
  "enabled": true,
  "created_at": "2026-06-17T10:00:00Z"
}

A later GET /mgmt/v1/alerts/channels/{id} for the same channel returns the masked form:

{
  "channel_id": "chan_01jwxyz...",
  "org_id": "org_01jabc...",
  "name": "Platform Team Slack",
  "kind": "slack",
  "config": { "webhook_url": "••••••••" },
  "enabled": true,
  "created_at": "2026-06-17T10:00:00Z"
}

PUT /mgmt/v1/alerts/channels/{id} is a partial update: to change only the name (or enabled), omit config from the body entirely and the stored webhook URL is left as-is. Sending config in a PUT always replaces the stored value with what you send, so never round-trip a masked value you read back from a GET into a PUT body.

Budget Alert Subscriptions

MCP equivalent: Alert Subscriptions tools.

Subscribes a budget limit to a delivery channel: when the limit crosses a threshold, every subscribed channel gets notified. A limit can have multiple subscriptions (fan out to several channels); a channel can back multiple subscriptions.

MethodPathScopeDescription
GET/mgmt/v1/alerts/subscriptionsreadList alert subscriptions, optionally filtered by limit_id or channel_id
POST/mgmt/v1/alerts/subscriptionswriteCreate a subscription linking a budget limit to a channel
GET/mgmt/v1/alerts/subscriptions/{id}readGet a single subscription
PUT/mgmt/v1/alerts/subscriptions/{id}writeEnable or disable a subscription
DELETE/mgmt/v1/alerts/subscriptions/{id}writeDelete a subscription
GET/mgmt/v1/alerts/historyreadList past alert delivery events, with filters

POST /mgmt/v1/alerts/subscriptions request body: both limit_id and channel_id must belong to the caller's org:

{
  "limit_id": "limit_01jwxyz...",
  "channel_id": "chan_01jwxyz..."
}

Response:

{
  "subscription_id": "sub_01jwxyz...",
  "limit_id": "limit_01jwxyz...",
  "channel_id": "chan_01jwxyz...",
  "channel_name": "Platform Team Slack",
  "channel_kind": "slack",
  "enabled": true,
  "last_alerted_at": null,
  "last_alerted_level": null,
  "created_at": "2026-06-17T10:00:00Z"
}

Budget Limits

MCP equivalent: Budget Limits tools.

Spend caps scoped to an org, project, or workload. A limit can alert, cap traffic once crossed, or both, controlled by actions.

MethodPathScopeDescription
GET/mgmt/v1/budgets/limitsreadList budget limits, enriched with current-period spend
POST/mgmt/v1/budgets/limitswriteCreate a budget limit
DELETE/mgmt/v1/budgets/limits/{id}writeDelete a budget limit

POST /mgmt/v1/budgets/limits request body. scope is one of org, project, workload, provider; scope_id is required unless scope is org. For scope: "provider", scope_id must be a canonical provider ID (e.g. openai, azure_openai) or a custom:/catalog:-prefixed BYOC connector ID; a bare hostname (e.g. api.openai.com) is rejected on create; existing hostname-format rows created before this restriction still work and continue to resolve. period is one of daily, weekly, monthly (default monthly). actions defaults to ["alert"] server-side when omitted: pass an explicit empty array for a draft/no-op limit:

{
  "scope": "project",
  "scope_id": "proj_checkout",
  "limit_usd": "500.00",
  "period": "monthly",
  "warning_threshold_pct": 80,
  "critical_threshold_pct": 100,
  "actions": ["alert", "cap"]
}

Response:

{
  "limit_id": "limit_01jwxyz...",
  "status": "created"
}

Org Budget Config

MCP equivalent: Budget Limits toolsget_org_budget_config is bundled there rather than broken out separately.

Read-only view of the org's budget enforcement posture: what happens to traffic if the control plane or Redis (where live spend counters are tracked) becomes unreachable.

MethodPathScopeDescription
GET/mgmt/v1/budgets/configreadCurrent CP-down / Redis-down failure policy and grace period
{
  "cp_down_policy": "allow",
  "redis_down_policy": "allow",
  "grace_seconds": 300,
  "grace_seconds_override": null,
  "redis_status": "connected"
}

Quickstart: CI Credential Rotation

Rotate a provider credential from a GitHub Actions workflow without manual console access:

# .github/workflows/rotate-credentials.yml
name: Rotate OpenAI credential
on:
  schedule:
    - cron: '0 2 1 * *'  # 2am UTC on the 1st of each month

jobs:
  rotate:
    runs-on: ubuntu-latest
    steps:
      - name: Push new credential
        env:
          MGK_KEY: ${{ secrets.AXEMERE_MGMT_KEY }}
          OPENAI_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          curl -sS -X PUT \
            -H "Authorization: Bearer $MGK_KEY" \
            -H "Content-Type: application/json" \
            -d "{\"id\":\"cred_openai_prod\",\"provider\":\"openai\",\"mode\":\"alias\",\"secret\":\"$OPENAI_KEY\"}" \
            https://us.api.axemere.ai/mgmt/v1/credentials

Self-Hosted Mode

Self-hosted gateways expose the identical /mgmt/v1/ surface directly from the gateway's own admin listener: no separate service to run. Management keys for self-hosted gateways are provisioned via the gateway admin API (POST /v1/admin/mgmt-keys), which validates locally with no control-plane connection required. See the Admin API Reference for gateway-local endpoints, and the MCP Server Reference for running mvgc-mcp locally.


Related: MCP Server Reference | Key Types Reference | Credentials