REST API reference

This page documents the current server routes as they exist today. It intentionally favors the exact path and method names over simplified marketing labels.

i

Base URL and auth

The API server defaults to http://localhost:2009. Most machine clients use Authorization: Bearer arun_*. Browser login uses the Auth0-backed session routes under /auth, and shared links use X-Share-Token.

Common workflows

POST/v1/connect/sessionsNo auth

Start the browser approval flow for a runtime. The response includes a session ID and the approval URL your CLI opens in the browser.

FieldTypeNotes
client_kindrequiredstringclaude_code, codex, mcp, generic, openclaw, or setup.
completion_moderequiredstringloopback or poll.
display_namerequiredstringHuman-readable runtime name.
code_challengerequiredstringPKCE S256 code challenge.

Example Request

bash
curl -X POST http://localhost:2009/v1/connect/sessions \
  -H "Content-Type: application/json" \
  -d '{
    "client_kind": "claude_code",
    "completion_mode": "poll",
    "display_name": "Claude Code",
    "code_challenge": "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM"
  }'

Example Response

json
{
  "id": "01KM...",
  "status": "pending",
  "approval_url": "http://localhost:2009/connect/01KM...",
  "poll_interval_ms": 1000
}
POST/v1/connect/sessions/:id/redeemNo auth

Redeem an approved connect session and receive the scoped API key plus namespace details.

FieldTypeNotes
code_verifierrequiredstringPKCE code verifier matching the original challenge.

Example Request

bash
curl -X POST http://localhost:2009/v1/connect/sessions/01KM.../redeem \
  -H "Content-Type: application/json" \
  -d '{
    "code_verifier": "your-original-random-pkce-secret"
  }'

Example Response

json
{
  "api_base_url": "http://localhost:2009",
  "api_key": "arun_agt_...",
  "principal": {
    "id": "01KM...",
    "type": "agent"
  },
  "namespace": {
    "slug": "my-namespace"
  }
}
POST/v1/artifactsAuth required

Create a new artifact and version. This is the core publish operation behind the CLI and MCP server.

FieldTypeNotes
namespace_idrequiredstringTarget namespace ID.
titlerequiredstringArtifact title.
contentrequiredstringArtifact body.
content_typestringtext/plain, text/markdown, or application/json.

Example Request

bash
curl -X POST http://localhost:2009/v1/artifacts \
  -H "Authorization: Bearer arun_agt_..." \
  -H "Content-Type: application/json" \
  -d '{
    "namespace_id": "01KM...",
    "title": "Docs implementation plan",
    "content": "# Plan\n\nBuild a lean docs system.",
    "content_type": "text/markdown"
  }'

Example Response

json
{
  "id": "01KM...",
  "title": "Docs implementation plan",
  "current_version": 1,
  "content_type": "text/markdown"
}
PUT/v1/artifacts/:idAuth required

Create a new version of an existing artifact. The server preserves old versions and stores git metadata when present.

FieldTypeNotes
contentrequiredstringReplacement content.
titlestringOptional title update.
descriptionstringOptional description update.
messagestringVersion message.

Example Request

bash
curl -X PUT http://localhost:2009/v1/artifacts/01KM... \
  -H "Authorization: Bearer arun_agt_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content": "# Plan\n\nUpdated after review.",
    "message": "Incorporate review feedback"
  }'

Example Response

json
{
  "id": "01KM...",
  "current_version": 2,
  "version": {
    "version": 2,
    "content_hash": "3b2f..."
  }
}
POST/v1/grantsAuth required

Create a share token that grants read access to a namespace or one artifact.

FieldTypeNotes
namespace_idrequiredstringNamespace being shared.
artifact_idstringOptional artifact-specific scope.
permissionsstring[]Defaults to read-only behavior in normal share flows.
expires_atstringISO timestamp.

Example Request

bash
curl -X POST http://localhost:2009/v1/grants \
  -H "Authorization: Bearer arun_usr_..." \
  -H "Content-Type: application/json" \
  -d '{
    "namespace_id": "01KM...",
    "artifact_id": "01KM...",
    "permissions": ["read"]
  }'

Example Response

json
{
  "id": "01KM...",
  "token": "arun_share_...",
  "token_prefix": "arun_share_...",
  "expires_at": null
}
POST/v1/git/importAuth required

Fetch a file from GitHub, GitLab, or Bitbucket and import it as a new artifact with git provenance.

FieldTypeNotes
repo_urlrequiredstringRepository URL.
pathrequiredstringPath inside the repository.
namespace_idrequiredstringTarget namespace ID.
branchstringDefaults to main.

Example Request

bash
curl -X POST http://localhost:2009/v1/git/import \
  -H "Authorization: Bearer arun_agt_..." \
  -H "Content-Type: application/json" \
  -d '{
    "repo_url": "https://github.com/attach-dev/attach-platform",
    "path": "README.md",
    "branch": "main",
    "namespace_id": "01KM..."
  }'

Example Response

json
{
  "id": "01KM...",
  "current_version": 1,
  "provenance": {
    "source": "git_import",
    "gitRepoUrl": "https://github.com/attach-dev/attach-platform",
    "gitRef": "main",
    "gitPath": "README.md"
  }
}

Route inventory

Auth

GET /auth/login
GET /auth/callback
POST /auth/logout

Connect

POST /v1/connect/sessions
GET /v1/connect/sessions/:id
POST /v1/connect/sessions/:id/redeem
POST /v1/connect/sessions/:id/cancel
POST /connect/:id/approve

Principal and keys

GET /v1/me
POST /v1/principals
POST /v1/api-keys
GET /v1/api-keys
POST /v1/api-keys/:id/revoke

Namespaces and artifacts

POST /v1/namespaces
GET /v1/namespaces
GET /v1/namespaces/:slug
PATCH /v1/namespaces/:slug
GET /v1/namespaces/:slug/search
GET /v1/namespaces/:slug/artifacts
POST /v1/artifacts
GET /v1/artifacts/:id
GET /v1/artifacts/:id/content
PUT /v1/artifacts/:id
POST /v1/artifacts/:id/archive
POST /v1/artifacts/:id/unarchive
GET /v1/artifacts/:id/versions
GET /v1/artifacts/:id/diff

Sharing and git

POST /v1/grants
GET /v1/grants
POST /v1/grants/:id/revoke
POST /v1/git/import
POST /v1/git/sync/:id
GET /v1/git/export/:id

Instances, lineage, stats

GET /v1/instances
GET /v1/instances/:id
GET /v1/lineage
GET /v1/lineage/artifacts/:id
GET /v1/stats
GET /v1/stats/admin

Response shape notes

Error responses consistently use a compact shape with error and message. Search, list, and detail routes tend to use snake_case field names in JSON, even when the internal TypeScript types are camelCase.

json
{
  "error": "not_found",
  "message": "Artifact not found"
}