Notes & PKMDocumentedScanned

craft-do

Complete REST API integration for Craft.do - the beautiful note-taking and document.

Share:

Installation

npx clawhub@latest install craft-do

View the full skill documentation and source below.

Documentation

Craft.do Integration Skill

Complete REST API integration for Craft.do - the beautiful note-taking and document app.

Overview

This skill provides full programmatic access to Craft.do for:

  • Task automation: Create, update, manage tasks across inbox/daily notes/logbook

  • Document workflows: Programmatically create, read, organize documents

  • Folder management: Build nested folder hierarchies via API

  • Obsidian migration: One-time full vault migration with content preservation

  • Content manipulation: Add/edit markdown content via blocks API


Craft.do features:
  • Native markdown support

  • Task management (inbox, daily notes, logbook)

  • Collections (database tables)

  • Hierarchical folders and documents

  • Full REST API access


Setup

  • Get your API key from Craft.do settings

  • Store credentials securely:
  • export CRAFT_API_KEY="pdk_xxx"
    export CRAFT_ENDPOINT=""

    API Capabilities

    ✅ What Works

    List Folders

    curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/folders"

    Returns all locations: unsorted, daily_notes, trash, templates, and custom folders.

    List Documents

    curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/documents?folderId=FOLDER_ID"

    Create Folder (with optional parent for nesting)

    # Root-level folder
    curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "folders": [{
          "name": "Projects"
        }]
      }' \
      "$CRAFT_ENDPOINT/folders"
    
    # Nested folder (requires parent folder ID)
    curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "folders": [{
          "name": "Q1 2024",
          "parentFolderId": "PARENT_FOLDER_ID"
        }]
      }' \
      "$CRAFT_ENDPOINT/folders"

    Create Document

    curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "documents": [{
          "title": "Document Title"
        }],
        "destination": {
          "folderId": "FOLDER_ID"
        }
      }' \
      "$CRAFT_ENDPOINT/documents"

    Note: Documents are created without content initially. Use the /blocks endpoint to add content.

    Add Content to Document

    curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "blocks": [{
          "type": "text",
          "markdown": "# Document content\n\nFull markdown support!"
        }],
        "position": {
          "pageId": "DOCUMENT_ID",
          "position": "end"
        }
      }' \
      "$CRAFT_ENDPOINT/blocks"

    Read Document Content

    curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/blocks?id=DOCUMENT_ID"

    Returns full markdown content with all blocks.

    Create Task

    curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "tasks": [{
          "markdown": "Task description",
          "location": {"type": "inbox"},
          "status": "active"
        }]
      }' \
      "$CRAFT_ENDPOINT/tasks"

    Update Task (Mark Complete)

    curl -X PUT \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "tasksToUpdate": [{
          "id": "TASK_ID",
          "markdown": "- [x] Completed task"
        }]
      }' \
      "$CRAFT_ENDPOINT/tasks"

    List Tasks

    # Active tasks
    curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/tasks?scope=active"
    
    # All completed (logbook)
    curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/tasks?scope=logbook"
    
    # Upcoming
    curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/tasks?scope=upcoming"
    
    # Inbox only
    curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/tasks?scope=inbox"

    Move Documents

    curl -X PUT \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "documentIds": ["DOC_ID"],
        "destination": {"location": "unsorted"}
      }' \
      "$CRAFT_ENDPOINT/documents/move"

    Note: Can only move to unsorted, templates, or custom folder IDs. Cannot move directly to trash.

    ❌ Limitations

    • No Collections API - Collections (databases) not accessible via API
    • No task deletion - Can only create/update tasks, not delete
    • No document deletion - Cannot delete documents directly (only move)
    • No search endpoint - Search requires specific query format (needs more testing)
    • Limited filtering - Collections filtering/grouping only in UI, not via API

    Common Use Cases

    Sync Tasks from External System

    # Create task in Craft from Mission Control
    TASK_TITLE="Deploy new feature"
    curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{
        \"tasks\": [{
          \"markdown\": \"$TASK_TITLE\",
          \"location\": {\"type\": \"inbox\"},
          \"status\": \"active\"
        }]
      }" \
      "$CRAFT_ENDPOINT/tasks"

    Create Daily Note

    TODAY=$(date +%Y-%m-%d)
    curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{
        \"documents\": [{
          \"title\": \"Daily Note - $TODAY\",
          \"content\": [{\"textContent\": \"# $TODAY\\n\\n## Tasks\\n\\n## Notes\\n\"}],
          \"location\": \"daily_notes\"
        }]
      }" \
      "$CRAFT_ENDPOINT/documents"

    Archive Completed Work

    # Get all completed tasks
    curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/tasks?scope=logbook" | jq '.items[] | {id, markdown, completedAt}'

    Integration Patterns

    Mission Control → Craft Sync

    Problem: Mission Control has automation but ugly UI. Craft has beautiful UI but no automation.

    Solution: Use Mission Control as the source of truth, sync completed work to Craft for viewing.

    #!/bin/bash
    # sync-to-craft.sh - Sync completed tasks to Craft
    
    # Read completed tasks from Mission Control
    COMPLETED_TASKS=$(cat mission-control/tasks.json | jq -r '.[] | select(.status=="done") | .title')
    
    # Push each to Craft
    echo "$COMPLETED_TASKS" | while read -r task; do
      curl -X POST \
        -H "Authorization: Bearer $CRAFT_API_KEY" \
        -H "Content-Type: application/json" \
        -d "{
          \"tasks\": [{
            \"markdown\": \"- [x] $task\",
            \"location\": {\"type\": \"inbox\"}
          }]
        }" \
        "$CRAFT_ENDPOINT/tasks"
    done

    Markdown Support

    Craft fully supports markdown:

    • Headers: # H1, ## H2, etc.

    • Lists: - item, 1. item

    • Tasks: - [ ] todo, - [x] done

    • Links: [text](url)

    • Code: ` inline or ``block`

    • Emphasis: *italic*, **bold**


    All content is stored and returned as markdown, making it perfect for programmatic manipulation.

    Best Practices

  • Store API key securely - Never commit to code

  • Test in unsorted folder first - Easy to find/clean up

  • Use markdown format - Native to both systems

  • One-way sync only - Craft → read-only, Mission Control → write

  • Batch operations - API supports arrays for efficiency

  • Handle errors gracefully - API returns detailed validation errors
  • Error Handling

    Common errors:

    • VALIDATION_ERROR - Check required fields (markdown, location)

    • 403 - Invalid/expired API key

    • 404 - Document/task ID not found


    Example validation error:
    {
      "error": "Validation failed",
      "code": "VALIDATION_ERROR",
      "details": [{
        "path": ["tasks", 0, "markdown"],
        "message": "Invalid input: expected string"
      }]
    }

    Future Possibilities

    When Craft adds to their API:

    • Collections CRUD via API

    • Task deletion

    • Document deletion

    • Advanced search

    • Webhooks for real-time sync

    • Batch operations for large datasets


    Resources

    • [Craft API Docs]() (get your personal API endpoint from Craft settings)
    • [Craft Blog - Collections]()
    • [Craft YouTube]()

    Testing Checklist

    • List folders
    • List documents
    • Create document
    • Add content to document (via /blocks endpoint)
    • Read document content
    • Create task
    • Update task (mark complete)
    • List tasks (all scopes)
    • Move documents between locations
    • Full Obsidian → Craft migration with content
    • Search (needs format refinement)
    • Collections - NOT accessible via API
    • Delete tasks - NOT supported
    • Delete documents - NOT supported (only move)

    Example: Complete Workflow

    # 1. Create a project folder
    PROJECT_ID=$(curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name": "Q1 2024 Projects"}' \
      "$CRAFT_ENDPOINT/folders" | jq -r '.id')
    
    # 2. Create a project document
    DOC_ID=$(curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{
        \"documents\": [{
          \"title\": \"Project Alpha\",
          \"content\": [{\"textContent\": \"## Overview\\n\\nProject details here.\"}],
          \"location\": \"$PROJECT_ID\"
        }]
      }" \
      "$CRAFT_ENDPOINT/documents" | jq -r '.items[0].id')
    
    # 3. Create tasks for the project
    curl -X POST \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "tasks": [
          {"markdown": "Design wireframes", "location": {"type": "inbox"}},
          {"markdown": "Build prototype", "location": {"type": "inbox"}},
          {"markdown": "User testing", "location": {"type": "inbox"}}
        ]
      }' \
      "$CRAFT_ENDPOINT/tasks"
    
    # 4. Mark first task complete
    TASK_ID=$(curl -H "Authorization: Bearer $CRAFT_API_KEY" \
      "$CRAFT_ENDPOINT/tasks?scope=active" | jq -r '.items[0].id')
    
    curl -X PUT \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{
        \"tasksToUpdate\": [{
          \"id\": \"$TASK_ID\",
          \"markdown\": \"- [x] Design wireframes\"
        }]
      }" \
      "$CRAFT_ENDPOINT/tasks"

    Status: Tested and working (2026-01-31)
    Tested with: Craft API v1