Esc

    This reference documents a fictional project management API. It exists to show how dense reference material reads: many sections, many fields, and code in several languages.

    Overview

    All requests go to https://api.example.com/v1. Requests and responses use JSON. Timestamps are ISO 8601 strings in UTC.

    v1 is the current version. Breaking changes ship under a new version prefix.

    Authentication

    Authenticate with a bearer token in the Authorization header. Create tokens in your account settings.

    curl
    curl https://api.example.com/v1/projects \
      -H "Authorization: Bearer $TOKEN"
    TypeScript
    const response = await fetch('https://api.example.com/v1/projects', {
      headers: { Authorization: `Bearer ${token}` },
    });
    Python
    import requests
    
    response = requests.get(
        "https://api.example.com/v1/projects",
        headers={"Authorization": f"Bearer {token}"},
    )

    Errors

    Errors return a non-2xx status and a JSON body with a machine-readable code.

    {
      "error": {
        "code": "project_not_found",
        "message": "No project with id prj_123 exists."
      }
    }
    Status Meaning
    400 The request body or query is invalid
    401 The token is missing or expired
    403 The token lacks permission for this resource
    404 The resource does not exist
    429 Too many requests, see rate limits

    Pagination

    List endpoints return at most limit items and a next cursor. Pass the cursor to get the next page.

    limitintegerdefault: 20

    Items per page, between 1 and 100.

    cursorstring

    The next value from the previous response.

    Rate limits

    Each token may make 600 requests per minute. Responses include the remaining budget.

    X-RateLimit-Limitheader

    Requests allowed per window.

    X-RateLimit-Remainingheader

    Requests left in the current window.

    X-RateLimit-Resetheader

    Unix time when the window resets.

    Projects

    A project groups tasks and members.

    The project object

    idstring

    Unique identifier, prefixed with prj_.

    namestring

    Display name, up to 80 characters.

    descriptionstring | null

    Optional Markdown description.

    status'active' | 'archived'

    Archived projects are read-only.

    created_atstring

    Creation time.

    List projects

    GET /projects

    curl https://api.example.com/v1/projects?limit=2 \
      -H "Authorization: Bearer $TOKEN"
    {
      "data": [
        { "id": "prj_1", "name": "Website", "status": "active" },
        { "id": "prj_2", "name": "Mobile app", "status": "active" }
      ],
      "next": "cur_9f2"
    }

    Create a project

    POST /projects

    namestringrequired

    Display name.

    descriptionstring

    Optional Markdown description.
    curl https://api.example.com/v1/projects \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{ "name": "Docs" }'

    Archive a project

    POST /projects/:id/archive

    Archiving is reversible. Archived projects keep their tasks but reject writes.

    Tasks

    A task belongs to exactly one project.

    The task object

    idstring

    Unique identifier, prefixed with tsk_.

    project_idstring

    Owning project.

    titlestring

    Short summary.

    assignee_idstring | null

    Member responsible for the task.

    due_atstring | null

    Due date.

    state'todo' | 'doing' | 'done'default: 'todo'

    Workflow state.

    List tasks

    GET /projects/:id/tasks

    state'todo' | 'doing' | 'done'

    Filter by state.

    assignee_idstring

    Filter by assignee.

    Update a task

    PATCH /tasks/:id

    Send only the fields you want to change.

    await fetch(`https://api.example.com/v1/tasks/${id}`, {
      method: 'PATCH',
      headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
      body: JSON.stringify({ state: 'done' }),
    });

    Delete a task

    DELETE /tasks/:id

    Deletion is permanent.

    Members

    Members are people with access to a project.

    The member object

    idstring

    Unique identifier, prefixed with mem_.

    emailstring

    Login email.

    role'owner' | 'editor' | 'viewer'

    Permission level.

    Invite a member

    POST /projects/:id/members

    emailstringrequired

    Invitee’s email.

    role'editor' | 'viewer'default: 'viewer'

    Initial role.

    Webhooks

    Webhooks send a POST request to your URL when something changes.

    Events

    Event Sent when
    project.created A project is created
    project.archived A project is archived
    task.created A task is created
    task.updated Any task field changes
    member.invited A member is invited

    Verifying signatures

    Every delivery includes an X-Signature header: an HMAC-SHA256 of the raw body with your webhook secret.

    verify.ts
    import { createHmac, timingSafeEqual } from 'node:crypto';
    
    export function verifySignature(body: string, signature: string, secret: string) {
      const expected = createHmac('sha256', secret).update(body).digest('hex');
      const a = Buffer.from(expected);
      const b = Buffer.from(signature);
      return a.length === b.length && timingSafeEqual(a, b);
    }
    
    export async function handleWebhook(request: Request, secret: string) {
      const body = await request.text();
      const signature = request.headers.get('X-Signature') ?? '';
    
      if (!verifySignature(body, signature, secret)) {
        return new Response('Invalid signature', { status: 401 });
      }
    
      const event = JSON.parse(body);
      console.log(`Received ${event.type}`);
      return new Response(null, { status: 204 });
    }

    Retries

    Failed deliveries are retried with exponential backoff for up to 24 hours. Respond with any 2xx status to acknowledge.

    Changelog

    2026-09-01

    • Added due_at to tasks.
    • limit now accepts up to 100.

    2026-06-15

    • Added webhooks.
    • Deprecated the owner query parameter on /projects. Deprecated

    2026-03-02

    • Initial release.