ObjectOS
Configure

API Access

Generated REST APIs, authentication, and API keys for integrations.

Every object declared in the artifact is exposed through a generated REST API. The same endpoints power the UI, integrations, and customer ETL scripts — there is no separate "integration API" to maintain.

Base URL

https://<project-domain>/api/v1

Notable surfaces:

PathPurpose
/api/v1/data/<object>Generated CRUD for each object (e.g. /api/v1/data/account)
/api/v1/data/<object>/{id}Read/update/delete a single record
/api/v1/actions/<object>/<action>Invoke a declarative action (POST)
/api/v1/auth/*Authentication (sign-in, sessions, OAuth, OIDC)
/api/v1/meta/*Metadata APIs (objects, fields, views) when enabled
/api/v1/keysMint a show-once sys_api_key for the calling user (POST)
/api/v1/batchTransactional cross-object batch (POST) — atomic-only, every operation gated per object
/api/v1/mcpModel Context Protocol server over Streamable HTTP — on by default; disable with OS_MCP_SERVER_ENABLED=false
/api/v1/healthLiveness/readiness probe (no auth)

The prefix defaults to /api/v1 (the API basePath of /api plus the version of v1) and is configurable on the ObjectOS stack.

Controlling what's exposed

API exposure is governed per object in the artifact, not at the gateway:

  • Set apiEnabled: false on an object to keep it off the REST surface entirely (its routes 404).
  • Set an apiMethods whitelist (e.g. ['get', 'list']) to make an object read-only or otherwise restrict which operations are reachable.

Both are enforced at the REST layer — see REST API → Restricting the API surface.

The same gates cover the transactional batch route (16.0): POST /api/v1/batch validates its body, enforces apiEnabled / apiMethods for every operation before opening the transaction, requires ids for update/delete, and rejects unresolvable { $ref } parent references. The route is atomic-only — atomic: false is rejected with 400 BATCH_NOT_ATOMIC; non-atomic bulk stays on the per-object createMany / updateMany endpoints.

Authentication options

Callers can authenticate in four ways:

MethodBest forHow
Session cookieBrowser/UI trafficSign in through /api/v1/auth/*; cookies are scoped to the project hostname
Bearer access tokenMobile, SPA, short-lived server jobsExchange credentials at /api/v1/auth/sign-in/email and pass Authorization: Bearer <token>
API keyServer-to-server, ETL, long-lived integrationsCreate a sys_api_key, pass it as a bearer token
OAuth 2.1 (MCP)AI agents / MCP clients acting as a signed-in userSelf-serve authorization-code + PKCE flow against the deployment itself

All three pass through the same AuthPlugin and resolve to a sys_user context that the SecurityPlugin evaluates against permissions and record access.

API keys

API keys are first-class sys_api_key records. The key value itself is stored hashed — only the prefix and metadata remain queryable, so a leaked key cannot be reconstructed from the database.

Issue a key in either of two ways:

  • Console — sign in to Console → API Keys as an administrator, choose the owning user, optionally set an expiration date, and copy the displayed secret once.

  • Self-serve endpointPOST /api/v1/keys mints a key for the authenticated caller and returns the raw secret exactly once. The key is pinned to the caller's own user, so it cannot be used to impersonate another identity:

    curl -X POST https://app.example.com/api/v1/keys \
      -H "Authorization: Bearer <session-or-access-token>" \
      -H "Content-Type: application/json" \
      -d '{"name": "etl-pipeline"}'
    # → { "id": "...", "name": "etl-pipeline", "prefix": "os_pk_…", "key": "os_pk_live_…" }

Pass the key on subsequent requests as a bearer token, an x-api-key header, or Authorization: ApiKey. The REST data and metadata APIs all authenticate it through the same verifier as MCP, under the key owner's permissions and record-level security:

curl https://app.example.com/api/v1/data/account \
  -H "x-api-key: os_pk_live_…"

To revoke a key, run the revoke_api_key action on the corresponding sys_api_key record (also available in the Console UI). Revocation takes effect immediately on the next request.

MCP clients & OAuth 2.1 (ObjectStack 13+)

Any OAuth-capable MCP client — Claude.ai custom connectors, Claude Desktop, Claude Code — can connect self-serve, without an admin minting API keys:

  • Each deployment acts as its own authorization server (backed by the embedded auth instance), with RFC 8414 / RFC 9728 discovery, dynamic client registration (RFC 7591), authorization-code + PKCE, and resource binding to <origin>/api/v1/mcp. TLS is required (localhost exempt).
  • Users sign in as themselves; tool calls run under their own permissions and row-level security.
  • OAuth scopes establish a hard permission ceiling (ObjectStack 14.5): effective_permission = scope_ceiling ∩ user_grants. data:read grants read-only data access, data:write full CRUD, and actions:execute is required for capability-gated business actions. Tokens missing a scope fail closed.

API keys remain a parallel track for CI and headless agents — x-api-key and Authorization: Bearer osk_… continue to work unchanged.

Pagination, filtering, and sorting

Generated list endpoints accept the standard ObjectStack query parameters:

ParameterMeaning
?limit=Page size (subject to a server-side ceiling)
?offset= or ?cursor=Pagination
?filter=Server-side filtering using the ObjectQL filter syntax
?sort=Sort expression (e.g. -created_at)
?fields=Sparse field selection

Refer to the framework documentation for the full filter grammar — the runtime grammar is the source of truth.

Rate limiting

Use the framework's RateLimiter primitive (or your ingress / API gateway) to apply per-IP and per-identity limits. Recommended starting buckets are documented in Production readiness.

CORS

If callers run in a browser on a different origin, configure CORS at the ingress or via the runtime's middleware. Do not combine wildcard origins with credentialed requests.

OpenAPI / discovery

The runtime can serve an OpenAPI document for the generated REST API when the corresponding capability is included in the image. Customer integrations should generate clients from the per-deployment OpenAPI document rather than hand-rolling URLs, because object names and generated routes follow the deployed artifact.

Discovery also advertises capabilities.transactionalBatch (16.0), so clients can detect the atomic batch route declaratively at connect time instead of probing for 404/405/501.

On this page