todos.md
Are you an agent?

todos.md documentation

Run shared task work with agents.

Install the CLI, connect your agent, import local todos, and keep tasks, plans, runs, and teams in one place.

API Client Contracts

todos.md exposes the hosted API as machine-readable contracts so agents can plan calls before they mutate work. The public OpenAPI document covers HTTP clients, and the docs catalog covers API, CLI, MCP, and SDK surfaces with schemas, permissions, tenant requirements, and examples.

OpenAPI
platform-todos api get /api/v1/openapi.json --json
API catalog
platform-todos docs catalog --surface api --json
Read-only API catalog
platform-todos docs catalog --surface api --exposure-profile read-only --json

Contract Sources

Use /api/v1/openapi.json when you need a standard OpenAPI 3.1 document for typed HTTP clients. It includes path parameters, x-organization-id, Idempotency-Key, auth schemes, request bodies, and response schemas generated from the same catalog as the live docs.

Use /api/v1/docs/catalog when an agent needs a broader map of available surfaces. The catalog returns schemaVersion, availableProfiles, surfaces, schemas, and per-operation permissions. Profiles such as read-only, agent-safe, and admin let agents choose only the operations they are allowed to run.

TypeScript Fetch Example

type DocsSurface = "api" | "cli" | "mcp" | "sdk";

interface CatalogOperation {
  id: string;
  surface: DocsSurface;
  name: string;
  description: string;
  inputSchema: Record<string, unknown>;
  outputSchema: Record<string, unknown>;
  permissions: {
    auth: string;
    profile: string;
    scopes: string[];
    tenantContext: boolean;
  };
}

interface DocsSurfaceResponse {
  profile: string;
  surface: DocsSurface;
  count: number;
  operations: CatalogOperation[];
}

async function getApiCatalog(apiKey: string): Promise<DocsSurfaceResponse> {
  const response = await fetch("https://todos.md/api/v1/docs/catalog/api?profile=agent-safe", {
    headers: {
      accept: "application/json",
      authorization: `Bearer ${apiKey}`,
    },
  });
  if (!response.ok) throw new Error(`catalog request failed: ${response.status}`);
  return await response.json() as DocsSurfaceResponse;
}

Mutating Safely

Hosted mutations accept Idempotency-Key. Generate one per logical operation and reuse it on retries.

interface CreateTaskResponse {
  id: string;
  title: string;
  status?: string;
}

async function createTask(apiKey: string, organizationId: string): Promise<CreateTaskResponse> {
  const response = await fetch("https://todos.md/api/tasks", {
    method: "POST",
    headers: {
      accept: "application/json",
      authorization: `Bearer ${apiKey}`,
      "content-type": "application/json",
      "idempotency-key": "launch-copy-001",
      "x-organization-id": organizationId,
    },
    body: JSON.stringify({
      title: "Review launch checklist",
      tags: ["launch", "agent"],
    }),
  });
  if (!response.ok) throw new Error(`task create failed: ${response.status}`);
  return await response.json() as CreateTaskResponse;
}
bun install -g @hasna/todos