API reference

Public profile reads and explicit owner workflows.

Use the public profile API for published content and grounded questions. Use the owner API for account inspection, drafts, previews, and apply.

Public profile reads
/profiles/:slug/api/v1/*
Owner workflow API
/api/agent/v1/*
Owner CLI
explore

API v1 documentation

API v1

Base path: /profiles/:slug/api/v1

Related agent-friendly surfaces

These routes sit alongside the tenant-scoped public API and should be kept in sync with product behavior when onboarding or readiness semantics change:

  • Public agent manifest: GET /.well-known/agent.json
  • Human-readable agent guide: GET /agents
  • Authenticated agent context for the current signed-in account: GET /api/agent/context
  • Versioned inspect-first agent API: GET /api/agent/v1/*

Unlike the tenant-scoped public API below, the authenticated agent context is session-scoped to the current owner account and is not addressed by public profile slug.

This API mirrors the multitenant public profile app. Each request is scoped to a published profile slug.

Example base path:

/profiles/bravo-studio/api/v1

Authentication

  • The tenant-scoped public API under /profiles/:slug/api/v1 is public and does not require X-API-Key.
  • Invalid or missing key responses below apply to authenticated agent endpoints, not the tenant-scoped public content/chat routes.
  • Authenticated agent endpoints return 401 with:
{
  "error": {
    "code": "unauthorized",
    "message": "Unauthorized"
  }
}

Error Contract

Error responses use:

{
  "error": {
    "code": "<machine_code>",
    "message": "<human_message>",
    "details": {}
  }
}

Agent API v1 commonly returns these machine-readable codes:

  • api_key_missing
  • invalid_api_key
  • owner_context_required
  • account_scope_required
  • forbidden_account_scope
  • missing_parameter
  • account_not_found
  • draft_not_found
  • resource_not_found
  • draft_archived

Missing required agent parameters return 400 with:

{
  "error": {
    "code": "missing_parameter",
    "message": "Missing required parameter",
    "details": {
      "parameter": "draft[attributes]"
    }
  }
}

Endpoints

GET /profiles/:slug/api/v1/content/profile

Returns the published profile summary for that account.

When an avatar is published, avatar_url is an Explore-served Active Storage path backed by durable storage rather than a temporary external file URL.

Response:

{
  "data": {
    "name": "Bravo Studio",
    "tagline": "Design systems and shipping support",
    "bio": "Bravo Studio is another customer account fixture.",
    "location": "Remote",
    "avatar_url": "/rails/active_storage/blobs/proxy/:signed_id/bravo.png"
  }
}

GET /profiles/:slug/api/v1/content/case_studies

Returns published case studies for that account.

Response:

{
  "data": [
    {
      "title": "Platform modernization program",
      "summary": "Introduced release guardrails; improved delivery visibility; reduced ops overhead.",
      "outcome": "Reduced release risk for customer-facing changes.",
      "slug": "platform-modernization-program"
    }
  ]
}

GET /profiles/:slug/api/v1/content/posts

Returns published writing posts for that account.

Response:

{
  "data": [
    {
      "title": "Shipping practical software in small slices",
      "summary": "Notes on release discipline and pragmatic delivery.",
      "date": "2026-03-01",
      "slug": "shipping-practical-software-in-small-slices"
    }
  ]
}

GET /profiles/:slug/api/v1/content/experiences

Returns published experience entries for that account.

Response:

{
  "data": [
    {
      "company": "Bravo Studio",
      "role": "Head of Engineering",
      "location": "London",
      "start_date": "2022",
      "end_date": "",
      "current": true,
      "summary": "Scaled product delivery; led platform quality; managed release flow."
    }
  ]
}

POST /profiles/:slug/api/v1/chat/messages

Accepts a chat question and returns a grounded answer plus sources for that profile.

Request:

{
  "message": {
    "question": "What work has Bravo Studio done?"
  }
}

Response:

{
  "data": {
    "question": "What work has Bravo Studio done?",
    "answer": "Recent work includes platform modernization and self-serve operations rollout.",
    "error_code": null,
    "sources": [
      {
        "label": "Work",
        "path": "/profiles/bravo-studio/work",
        "href": "/profiles/bravo-studio/work"
      }
    ]
  }
}

Unsupported questions must return:

  • answer: "Not in the provided material."
  • sources: []
  • optional error_code for provider/runtime issues such as openai_rate_limited, openai_auth_failed, openai_timeout, or openai_request_failed

Notes

  • Versioning still follows /api/v1.
  • The API is now tenant-scoped by profile slug so it matches the public Explore experience.
  • Contracts are enforced by request tests in test/requests/api/v1.
  • Operational status remains outside this tenant surface at GET /api/content/status.
  • chat_status on the ops endpoints still reports backend/readiness/key-present/model for runtime checks.
  • error_tracking_status on the ops endpoints reports the configured provider, readiness, API-key presence, and runtime environment for internal checks.

Explore agent API v1

Base path: /api/agent/v1

This is a separate inspect-first surface for humans and coding agents. It is read-heavy by default, with explicit owner-only document apply and draft operations.

The shared Explore CLI and API contract is the main integration story here. Codex, Claude Code, OpenCode, and Cursor are supported today on top of that contract, tool-specific helpers stay thin and optional, and other shell-capable tools should also work with Explore's shared CLI flow, with fuller support rolling out very soon.

Authentication model

Public-safe endpoints:

  • GET /api/agent/v1/profile?slug=:slug
  • GET /api/agent/v1/content?slug=:slug

Owner-only endpoints:

  • GET /api/agent/v1/onboarding/status
  • GET /api/agent/v1/manifest/next_actions
  • GET /api/agent/v1/publish/preview
  • GET /api/agent/v1/profile/document
  • POST /api/agent/v1/profile/document/preview
  • PUT /api/agent/v1/profile/document
  • GET /api/agent/v1/drafts
  • GET /api/agent/v1/drafts/:id
  • POST /api/agent/v1/drafts/:id/apply
  • GET /api/agent/v1/drafts/:id/apply_preview
  • PATCH /api/agent/v1/drafts/:id
  • POST /api/agent/v1/drafts/:id/archive
  • POST /api/agent/v1/content/propose_update

Owner-only endpoints use either:

  • the current signed-in session account, or
  • an account-scoped owner token passed as X-API-Key, optionally plus account=<slug> or account_id=<id> scope when the client wants to be explicit

When slug is provided, the public-safe inspect endpoints above do not require an API key. Owner-only endpoints still require the current signed-in session or an account token.

Account tokens are scoped to a single Explore account and should be created from that account's signed-in workspace. Most CLI users should use explore login and browser approval first; the token value is mainly for advanced, scripted, or non-interactive owner access.

Response envelope

{
  "status": "ok",
  "resource": "profile.inspect",
  "generated_at": "2026-03-26T11:00:00Z",
  "account_id": 1,
  "account_slug": "acme-careers",
  "context": {
    "mode": "owner"
  }
}

Endpoints

#### GET /api/agent/v1/profile

Returns public profile data, completeness, weak spots, and next safe actions.

  • Public mode: pass slug=:slug to inspect a published profile without X-API-Key.
  • Owner mode: omit slug and use the current signed-in session, or pass an account token as X-API-Key plus optional account / account_id.

#### PATCH /api/agent/v1/drafts/:id

Updates an existing open draft without publishing it.

Request:

{
  "draft": {
    "title": "Refined project draft",
    "summary": "Sharper framing for the same idea.",
    "attributes": {
      "summary": "Sharper framing for the same idea."
    }
  }
}

Archived drafts are read-only and return:

{
  "error": {
    "code": "draft_archived",
    "message": "Archived drafts are read-only."
  }
}

#### GET /api/agent/v1/content

Returns a structured content inventory for projects, posts, experiences, testimonials, and public profile sections.

  • Public mode: pass slug=:slug to inspect published content without X-API-Key.
  • Owner mode: omit slug and use the current signed-in session, or pass an account token as X-API-Key plus optional account / account_id.

#### GET /api/agent/v1/onboarding/status

Returns the current onboarding/setup step, blockers, guidance, and useful internal/public URLs.

#### GET /api/agent/v1/manifest/next_actions

Returns the explicit next safe action and the currently allowed action set for the account.

#### GET /api/agent/v1/profile/document

Returns the canonical Explore profile document for the owner account as structured JSON. The CLI renders this into YAML for local editing. Successful responses also include document_fingerprint, a sha256: hash of the canonical document payload.

#### POST /api/agent/v1/profile/document/preview

Validates a proposed profile document and returns a non-mutating change preview against the current owner account state.

  • invalid documents return 422 with path-specific errors under error.details.errors plus field_path, section, and recommended_action
  • successful previews include document_fingerprint, changed sections, machine-readable diff details, compact summary counts, before/after snapshots, and allowed next actions
  • preview never updates canonical Explore data; explicit apply is still required

Collection sections use the most trustworthy diff available for that section:

  • add_item, remove_item, and update_item are used when Explore can match repeated items safely
  • replace_collection is a deliberate fallback when Explore cannot trust a semantic item match

#### PUT /api/agent/v1/profile/document

Validates and applies a profile document back into the canonical Explore account records.

  • invalid documents return 422 with path-specific errors under error.details.errors
  • clients may include expected_fingerprint to require that the submitted document still matches the last reviewed canonical payload
  • fingerprint mismatches return 409 with error.details.expected_fingerprint, actual_fingerprint, and recommended_action
  • successful apply responses include document_fingerprint, expected_fingerprint when provided, and fingerprint_verified

#### GET /api/agent/v1/publish/preview

Returns a safe share-readiness preview and explainable publish impact. It never publishes content.

#### POST /api/agent/v1/content/propose_update

Records an audit-friendly content proposal event. V1 stores the proposal for review and does not mutate or publish live content.

Use this when an agent wants to suggest an edit to an existing target, or to the profile-level target, without creating a draft artifact.

Do not use this to create a brand-new post, project, or experience. For new content, prefer:

1. POST /api/agent/v1/content/create_draft

2. GET /api/agent/v1/drafts/:id

3. GET /api/agent/v1/drafts/:id/apply_preview

4. POST /api/agent/v1/drafts/:id/apply

Example: propose an update to an existing post

{
  "proposal": {
    "target_type": "post",
    "target_id": 42,
    "summary": "Tighten the post summary and CTA.",
    "attributes": {
      "summary": "A sharper summary for the same published post.",
      "title": "Keeping CI Green in Agentic Workflows"
    }
  }
}

#### POST /api/agent/v1/content/create_draft

Creates a first-class draft artifact for future content. Drafts are owner-only, never published automatically, and can appear in owner-facing content.list / profile.inspect responses.

This is the preferred path for creating new content such as a new blog post, case study, project, or experience entry.

Recommended new-content workflow:

1. POST /api/agent/v1/content/create_draft

2. GET /api/agent/v1/drafts/:id

3. GET /api/agent/v1/drafts/:id/apply_preview

4. POST /api/agent/v1/drafts/:id/apply

Example: create a new post draft

{
  "draft": {
    "target_type": "post",
    "title": "Shipping Safer Agent Content Workflows",
    "summary": "Draft a new post about safer authoring flows for Explore agents.",
    "attributes": {
      "title": "Shipping Safer Agent Content Workflows",
      "summary": "Draft a new post about safer authoring flows for Explore agents."
    }
  }
}

#### GET /api/agent/v1/drafts

Lists owner-only drafts with stable metadata and allowed next actions.

#### GET /api/agent/v1/drafts/:id

Returns one owner-only draft for review.

#### POST /api/agent/v1/drafts/:id/apply

Applies a reviewed draft into Explore data and archives the draft.

  • Profile drafts update live account public profile fields.
  • Project, post, and experience drafts create new account-backed records.
  • This action is audited and does not perform broader publish orchestration.

#### GET /api/agent/v1/drafts/:id/apply_preview

Returns a read-only preview of what the draft would change if a future apply step were introduced.

  • Profile drafts compare against the current live profile fields.
  • Project, post, and experience drafts currently preview creation of a new item because V1 drafts do not yet carry a target record id.

#### POST /api/agent/v1/drafts/:id/archive

Marks one owner-only draft as archived so it no longer appears in open-draft pathways.