ArxDeck
Integrations

Content management (content API)

Headless collections and entries for static sites with CORS, service keys, and assets.

Content management (content API)

Content management exposes a headless content API for static sites and client apps. Project admins manage collections, schemas, entries, CORS origins, service keys, and assets from Settings → Content management.

Enablement

  1. A project admin enables Content management on Settings → Content management (checkbox + save), or approves an MCP proposal (propose_content_management_schema with operation: enable).
  2. Set allowed origins, optional suspend public access, and create service keys on that page.
  3. Use Manage content to create collections, optionally define a schema (recommended before entries), and add entries.

Copy the project ref (project ID) and content service base URL from Settings → Content management — integrators need both for API calls.

Agents on ArxDeck MCP must call get_project_info (Knowledge group, no arguments) for projectRef, contentServiceUrl, capability flags, and published site URLs. Do not pass secrets or env vars into static build pipelines — builds are sandboxed and cannot read platform configuration at build time.

Public reads (no app users)

Public collections can be read anonymously with GET /v1/collections/{slug}/entries, X-Project-Ref, and a listed Origin header. You do not need the Authentication capability for public-only sites.

Service keys and access rights

Create service keys on the content management settings page for server-side access (Authorization: Bearer cbk_…). Per-collection access rights for service keys are managed on each collection's page under Manage content with only Content management enabled (list and revoke, including existing app-user rows). Granting access to app users and the Content API users section on that page require the Authentication capability.

Rights levels are read, write, and admin (admin includes schema and collection settings).

What agents can change (MCP)

  • Schema / collections: propose_content_management_schema (enable, collections, schema revisions)
  • Entries: propose_content_management_data (create, update, delete). Create requires proposalRef and does not send a resource identity; update and delete identify the entry by collection slug and entry key. Applies immediately when the collection has auto-approve MCP writes enabled.

Inspect state with get_content_management_schema, list_content_management_entries, and get_content_management_entry.

API reference

The public integrator API is served by the content service. Browser clients on Publish-hosted sites should call /_arxdeck/api/... on the site origin (gateway forwards to /v1/...). Server-side integrations continue to use {content-service-base}/v1.

Browser base URL (Publish)

https://{your-published-hostname}/_arxdeck/api

Direct base URL (server-side)

{content-service-base}/v1

Replace {content-service-base} with the HTTPS origin shown in Settings → Content management (no trailing slash).

Headers and authentication

HeaderRequiredDescription
X-Project-RefYesProject ref from Settings → Content management (same value as the project ID in the dashboard URL).
OriginBrowser requestsYour static site origin. Must appear in allowed origins for CORS.
AuthorizationService keysBearer cbk_… for server-side automation. Never embed in browser bundles.
CookieSessionscontent_session HttpOnly cookie after POST /v1/auth/login (see Authentication).

Callers resolve as:

  • Public — X-Project-Ref only (read public collections when not suspended).
  • Service key — Authorization: Bearer cbk_… plus matching X-Project-Ref.
  • Session — content_session cookie (or Bearer css_… session token) plus matching X-Project-Ref.

403 responses include Origin not allowed (CORS), Forbidden (insufficient collection rights), X-Project-Ref does not match authenticated scope, and User account is suspended. Project-level suspend public access returns 503 for anonymous callers; per-collection suspend returns 503 for public reads on that collection.

Rate limits

ScopeLimit
Project100 requests per minute (logged access per project).
Login10 POST /v1/auth/login attempts per project per 10 minutes.
Writes60 POST / PATCH / PUT / DELETE requests per project per hour (non-operator callers).

Exceeded limits return 429 with message Rate limit exceeded.

Pagination

List endpoints accept optional query parameters:

ParameterDefaultMaxDescription
limit50200Page size.
cursor——Opaque cursor from the previous response's nextCursor.

Responses include nextCursor (or null when there is no next page).

List payload truncation

GET /collections/{slug}/entries may truncate each entry's data field to 20 KiB UTF-8 for list responses. When truncated, the entry includes "truncated": true. Use GET /collections/{slug}/entries/{entryKey} for the full document.

Suspend public access

When suspend public access is enabled at the project level, anonymous (X-Project-Ref only) requests fail with 503 Public access is suspended. Authenticated service keys and sessions continue to work. Per-collection public access suspended blocks anonymous reads for that collection only.

Schema field types

Collection schemas are JSON objects with a fields array. Supported type values:

TypeDescription
textString with optional min, max, pattern, required, default.
markdownMarkdown string (same constraints as text).
numberFinite number with optional min, max, allowedValues.
booleantrue / false.
datetimeRFC 3339 timestamp string.
enumValue must be in allowedValues (required on enum fields).
assetAsset ID string (from the upload flow).
referenceEntry reference: targetCollections (required), optional multiple, optional deletePolicy (block or nullify).
arrayArray of itemType (text, markdown, number, boolean, datetime, enum, asset, or reference) with optional itemConfig.
objectFreeform JSON object (no subfield validation). Edit as JSON in the dashboard entry editor.

Field key is the stable identifier on entries; label is the optional display name in the dashboard. key must match ^[a-zA-Z][a-zA-Z0-9_]*$. MCP proposals accept legacy aliases with warnings: name as key when key is omitted, integer as number, and string as text (use datetime for RFC 3339 timestamps). Posting a new schema revision increments currentSchemaRevision; existing entries keep their stored revision until updated.

Collections

GET /collections

List collections visible to the caller (public collections for anonymous callers; granted plus public-readable collections for sessions and service keys).

Each item includes access: read, write, or admin for that caller (operator: admin; anonymous/public: read; sessions and keys: explicit grant level or read when public-readable).

curl "{content-service-base}/v1/collections" \
  -H "X-Project-Ref: YOUR_PROJECT_REF" \
  -H "Origin: https://www.example.com"

Example fragment:

{
  "collections": [
    {
      "id": "clx9col00000000000000001",
      "slug": "pages",
      "name": "Pages",
      "visibility": "public",
      "access": "read"
    }
  ]
}

POST /collections

Create a collection (session or service key with rights; creator receives admin on the new collection).

FieldTypeRequiredDescription
slugstringYesLowercase slug (^[a-z0-9][a-z0-9-]*$, max 64).
namestringYesDisplay name (max 200).
descriptionstringNoOptional description (max 2000).
visibilitystringNoprivate (default) or public.
validationModestringNostrict (default) or lax.

GET /collections/{slug}

Get one collection metadata object.

PATCH /collections/{slug}

Update collection fields (name, description, visibility, validationMode, autoApproveMcpWrites). Requires admin on the collection.

DELETE /collections/{slug}

Delete a collection and its entries. Requires admin.

Schema

GET /collections/{slug}/schema

Returns { revision, schema } for the collection's current schema revision.

POST /collections/{slug}/schema

Create a new schema revision (requires admin).

{
  "schema": {
    "fields": [
      { "key": "title", "type": "text", "required": true },
      { "key": "heroImage", "type": "asset" }
    ]
  }
}

GET /collections/{slug}/schema/revisions

List revision metadata (revision, createdAt, createdById).

Entries

Entry keys match ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ (max 128).

GET /collections/{slug}/entries

List entries with pagination. Requires read (or public visibility for anonymous callers).

curl "{content-service-base}/v1/collections/pages/entries?limit=50" \
  -H "X-Project-Ref: YOUR_PROJECT_REF" \
  -H "Origin: https://www.example.com"

GET /collections/{slug}/entries/{entryKey}

Get one entry with full data.

curl "{content-service-base}/v1/collections/pages/entries/home.hero" \
  -H "X-Project-Ref: YOUR_PROJECT_REF" \
  -H "Authorization: Bearer cbk_YOUR_KEY"

POST /collections/{slug}/entries

Create an entry (requires write).

FieldTypeRequiredDescription
entryKeystringYesUnique key within the collection.
dataobjectYesField values validated against the current schema.
publishedbooleanNoDefaults to false.

PATCH /collections/{slug}/entries/{entryKey}

Merge data fields and/or update published (requires write).

DELETE /collections/{slug}/entries/{entryKey}

Delete an entry (requires write). May return 409 when a reference field with deletePolicy: block still points at this entry.

Uploads and assets

Presigned upload URLs expire after 900 seconds (15 minutes). Asset download redirects expire after 300 seconds (5 minutes).

POST /uploads/presign

Requires an authenticated caller (not public). Returns presigned PUT URL and uploadId.

FieldTypeRequiredDescription
filenamestringYesOriginal filename (max 200).
contentTypestringYesAllowed MIME type (images, PDF, fonts, plain text, markdown, video, etc.).
expectedByteSizenumberNoOptional size check against type limits.
curl -X POST "{content-service-base}/v1/uploads/presign" \
  -H "Authorization: Bearer cbk_YOUR_KEY" \
  -H "X-Project-Ref: YOUR_PROJECT_REF" \
  -H "Content-Type: application/json" \
  -d '{ "filename": "hero.png", "contentType": "image/png" }'

PUT file bytes to uploadUrl, then complete:

POST /uploads/{uploadId}/complete

FieldTypeRequiredDescription
byteSizenumberNoOptional verification of uploaded size.

Returns { asset } with id, storageKey, contentType, byteSize, filename, status.

GET /assets/{assetId}

Returns 302 redirect to a short-lived presigned download URL. Requires authentication (not public).

curl -i "{content-service-base}/v1/assets/ASSET_ID" \
  -H "Authorization: Bearer cbk_YOUR_KEY" \
  -H "X-Project-Ref: YOUR_PROJECT_REF"

CORS checklist

  • Published ArxDeck hostnames (production and staging when enabled) are added automatically as platform-managed origins when your site goes live with content or authentication enabled. They appear read-only in Settings → Content management and do not need to be typed manually.
  • Add custom domains and any other browser origins in the manual allowed origins list (one HTTPS URL per line). Wildcards are not supported.
  • Managed and manual lists are separate; saving manual origins never removes platform-managed entries.
  • Enable credentialed requests (credentials: 'include') in the browser when using session cookies.
  • Suspend public access temporarily blocks anonymous reads without disabling the capability for editors and service keys.