Skip to navigation

Authentication and errors

The API reference documents the typed v1 resources under /api/v1. Start with the API resource guide for discovery and evidence semantics. Run it locally from the repository root:

npm run server --workspace @openstack/dashboard

The development base is http://127.0.0.1:8787. Hosted application activation is held. Use a hosted base only after your operator confirms it is serving and grants access.

For programmatic reads, create a key in Settings > API access and set MEDIACONTEXT_API_KEY in your shell or secret store:

curl --fail-with-body \
-H "X-Api-Key: $MEDIACONTEXT_API_KEY" \
'http://127.0.0.1:8787/api/v1/publishers?limit=25&offset=0'

Keys use the mck_ prefix and read or export scopes. An explicit X-Api-Key takes precedence over a Clerk bearer token and never falls back to it. Invalid or revoked keys fail. Key access also requires a current pro entitlement for the owning user. There is no per-key expiry field; revocation and entitlement expiry are separate checks.

Pro workspaces share a limit of 10,000 API requests per UTC calendar month, across all keys and API-key REST and HTTP MCP traffic. The counter is stored in the database and reserved atomically, so concurrent requests and application processes cannot overspend the monthly allowance. It resets at 00:00 UTC on the first day of the next month.

Each authenticated, eligible API-key request reserves one api_calls unit before its handler runs. Later scope denials, workspace minute-limit rejections and handler errors still count. Invalid, revoked or ineligible keys and browser sessions do not count. Once the monthly limit is reached, additional requests return 429 api_quota_exceeded without increasing usage. If accounting is unavailable, access fails with 503 usage_unavailable.

X-API-Quota-Limit, X-API-Quota-Remaining and X-API-Quota-Reset describe the monthly allowance; reset is a Unix timestamp in seconds. A quota rejection includes Retry-After in seconds until reset and structured details containing limit, used, remaining, periodStart and resetAt. The period fields are UTC timestamps. This monthly allowance is separate from the 60-second workspace rate limit.

MCP is metered by authenticated HTTP request, not by tool name. Its initialize and tools-list requests each consume one unit. A tool call consumes one unit for its MCP request plus one for each underlying REST request. Each v1 tool makes one REST request, so a successful HTTP tool call consumes two units. The legacy get_publisher tool still makes three REST reads and can consume four units. Authentication and limits are checked again for those reads; a tool can fail after consuming part of its allowance. A key-backed stdio client consumes units for its REST requests without an outer HTTP MCP charge. HTTP MCP responses carry the lowest remaining allowance observed across their underlying reads and the latest applicable reset or retry time. If an underlying request is quota-limited, the tool reports an error even when the MCP envelope uses HTTP 200; inspect the tool error and Retry-After.

API-key requests share a limit of 100 requests per 60-second window per workspace, across all keys, client addresses and routes. The window begins with the first request. Excess requests return 429 workspace_rate_limited and Retry-After in seconds. X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds) describe that workspace window. Browser sessions do not consume it. The existing per-address/path limit also applies and can reject requests before authentication or usage accounting.

The workspace limiter runs in memory in the pilot’s single active application process and resets on restart. Authentication and usage accounting happen before this check, so it bounds downstream API work rather than all database work. Fixed windows can admit bursts on either side of a reset. Before serving traffic through multiple application processes or replicas, move this counter to shared storage so the allowance cannot multiply.

Workspace changes require a Clerk member session with Authorization: Bearer <session-token>. The active Clerk organization must map to an accessible workspace. Keys cannot add or remove Shortlist members or mutate account lists. Never pass a workspace ID to try to override authentication scope.

V1 list resources are read-only. Existing list mutations remain on the unversioned API. To create a list with a session token stored as MEDIACONTEXT_BEARER:

curl --fail-with-body -X POST \
-H "Authorization: Bearer $MEDIACONTEXT_BEARER" \
-H 'Content-Type: application/json' \
--data '{"name":"Research","domains":["example.com"]}' \
http://127.0.0.1:8787/api/account-lists

A successful result has a list object with its id, revision, domains, createdAt and updatedAt. To update or delete it, send that current revision. A 409 means a concurrent change won; fetch the current list before retrying.

V1 collection responses contain data, page and meta. Offset pagination defaults to limit=25 and offset=0, with a maximum limit of 100. page.total counts matching records before pagination; page.hasMore indicates another page. Signal events use a fixed page size of 50 and an opaque page.nextCursor.

Detail responses contain data and meta. Preserve source provenance, nullable timestamps and unknown evidence rather than converting them to zero or false. Dataset discovery identifies the current served publisher directory; it does not support historical selection. Legacy intelligence reads retain their separate market-snapshot selectors.

Errors currently use either a string ({"error":"not found"}) or a structured object:

{"error":{"code":"insufficient_scope","message":"Requires 'export' scope","requestId":"request-id"}}
StatusMeaningAction
400Invalid JSON, domain, filter or ruleCorrect the request.
401Missing credentials or invalid_api_keySign in or replace the revoked/invalid key.
403insufficient_scope, pro_required or membership denialCheck scope, entitlement and organization access.
404Record absent in the accessible scopeCheck the domain, list or snapshot.
408MCP request body did not arrive within 10 secondsSend the complete body promptly before retrying.
409revision_conflictReload and reapply your change.
413 / 415MCP body exceeds 65,536 bytes or uses the wrong media typeSend a smaller JSON request with Content-Type: application/json.
429workspace_rate_limited or api_quota_exceededRespect Retry-After; a monthly quota rejection requires waiting for the UTC month reset.
500Internal errorKeep the request ID for support.
503Required database, source or service unavailableRetry later; do not treat it as an empty result.

Inspect the HTTP status before parsing success data. Retrying a mutation after an ambiguous connection failure can repeat the operation; read the current resource before retrying. Keep secrets out of URLs and logs.

Operators can pause all API-key access by setting MC_API_KEY_ACCESS_ENABLED=false in the server runtime environment and restarting the application. Key requests, including the key-backed stdio MCP proxy, then return 503 api_access_disabled before credential lookup or usage accounting. Browser/session authentication remains available. Restore access by removing the setting or setting it to true and restarting; existing keys are preserved. This switch does not disable session-authenticated clients.

The v1 built-in MCP implementation uses POST /api/v1/mcp with the same X-Api-Key and read scope. Manufact is selected for managed MCP hosting but is not activated; this route is an implementation reference, not the selected production endpoint. It exposes 13 read-only tools over stateless Streamable HTTP. See MCP client setup for the endpoint, client header requirements and local stdio alternative. The demo preview reports MCP as not configured; it is not a test of real API-key access.