{
  "schemaVersion": "1.0",
  "item": {
    "slug": "basecamp",
    "name": "Basecamp",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/byungkyu/basecamp",
    "canonicalUrl": "https://clawhub.ai/byungkyu/basecamp",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/basecamp",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=basecamp",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "LICENSE.txt"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-23T16:43:11.935Z",
      "expiresAt": "2026-04-30T16:43:11.935Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
        "contentDisposition": "attachment; filename=\"4claw-imageboard-1.0.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/basecamp"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/basecamp",
    "agentPageUrl": "https://openagent3.xyz/skills/basecamp/agent",
    "manifestUrl": "https://openagent3.xyz/skills/basecamp/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/basecamp/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Basecamp",
        "body": "Access the Basecamp 4 API with managed OAuth authentication. Manage projects, to-dos, messages, schedules, documents, and team collaboration."
      },
      {
        "title": "Quick Start",
        "body": "# List all projects\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://gateway.maton.ai/basecamp/projects.json')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF"
      },
      {
        "title": "Base URL",
        "body": "https://gateway.maton.ai/basecamp/{resource}.json\n\nThe gateway proxies requests to 3.basecampapi.com/{account_id}/ and automatically injects your OAuth token and account ID.\n\nImportant: All Basecamp API URLs must end with .json."
      },
      {
        "title": "Authentication",
        "body": "All requests require the Maton API key in the Authorization header:\n\nAuthorization: Bearer $MATON_API_KEY\n\nEnvironment Variable: Set your API key as MATON_API_KEY:\n\nexport MATON_API_KEY=\"YOUR_API_KEY\""
      },
      {
        "title": "Getting Your API Key",
        "body": "Sign in or create an account at maton.ai\nGo to maton.ai/settings\nCopy your API key"
      },
      {
        "title": "Connection Management",
        "body": "Manage your Basecamp OAuth connections at https://ctrl.maton.ai."
      },
      {
        "title": "List Connections",
        "body": "python <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://ctrl.maton.ai/connections?app=basecamp&status=ACTIVE')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF"
      },
      {
        "title": "Create Connection",
        "body": "python <<'EOF'\nimport urllib.request, os, json\ndata = json.dumps({'app': 'basecamp'}).encode()\nreq = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Content-Type', 'application/json')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF"
      },
      {
        "title": "Get Connection",
        "body": "python <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\nResponse:\n\n{\n  \"connection\": {\n    \"connection_id\": \"71e313c8-9100-48c6-8ea1-6323f6fafd04\",\n    \"status\": \"ACTIVE\",\n    \"creation_time\": \"2026-02-08T03:12:39.815086Z\",\n    \"last_updated_time\": \"2026-02-08T03:12:59.259878Z\",\n    \"url\": \"https://connect.maton.ai/?session_token=...\",\n    \"app\": \"basecamp\",\n    \"metadata\": {}\n  }\n}\n\nOpen the returned url in a browser to complete OAuth authorization."
      },
      {
        "title": "Delete Connection",
        "body": "python <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF"
      },
      {
        "title": "Specifying Connection",
        "body": "If you have multiple Basecamp connections, specify which one to use with the Maton-Connection header:\n\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://gateway.maton.ai/basecamp/projects.json')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Maton-Connection', '71e313c8-9100-48c6-8ea1-6323f6fafd04')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\nIf omitted, the gateway uses the default (oldest) active connection."
      },
      {
        "title": "User Info",
        "body": "Get Current User\n\nGET /basecamp/my/profile.json\n\nResponse:\n\n{\n  \"id\": 51197030,\n  \"name\": \"Chris Kim\",\n  \"email_address\": \"chris@example.com\",\n  \"admin\": true,\n  \"owner\": true,\n  \"time_zone\": \"America/Los_Angeles\",\n  \"avatar_url\": \"https://...\"\n}"
      },
      {
        "title": "People Operations",
        "body": "List People\n\nGET /basecamp/people.json\n\nResponse:\n\n[\n  {\n    \"id\": 51197030,\n    \"name\": \"Chris Kim\",\n    \"email_address\": \"chris@example.com\",\n    \"admin\": true,\n    \"owner\": true,\n    \"employee\": true,\n    \"time_zone\": \"America/Los_Angeles\"\n  }\n]\n\nGet Person\n\nGET /basecamp/people/{person_id}.json\n\nList Project Members\n\nGET /basecamp/projects/{project_id}/people.json"
      },
      {
        "title": "Project Operations",
        "body": "List Projects\n\nGET /basecamp/projects.json\n\nResponse:\n\n[\n  {\n    \"id\": 46005636,\n    \"status\": \"active\",\n    \"name\": \"Getting Started\",\n    \"description\": \"Quickly get up to speed with everything Basecamp\",\n    \"created_at\": \"2026-02-05T22:59:26.087Z\",\n    \"url\": \"https://3.basecampapi.com/6153810/projects/46005636.json\",\n    \"dock\": [...]\n  }\n]\n\nGet Project\n\nGET /basecamp/projects/{project_id}.json\n\nThe project response includes a dock array with available tools (message_board, todoset, vault, chat, schedule, etc.). Each dock item has:\n\nid: The tool's ID\nname: Tool type (e.g., \"todoset\", \"message_board\")\nenabled: Whether the tool is active\nurl: Direct URL to access the tool\n\nCreate Project\n\nPOST /basecamp/projects.json\nContent-Type: application/json\n\n{\n  \"name\": \"New Project\",\n  \"description\": \"Project description\"\n}\n\nUpdate Project\n\nPUT /basecamp/projects/{project_id}.json\nContent-Type: application/json\n\n{\n  \"name\": \"Updated Project Name\",\n  \"description\": \"Updated description\"\n}\n\nDelete (Trash) Project\n\nDELETE /basecamp/projects/{project_id}.json"
      },
      {
        "title": "To-Do Operations",
        "body": "Get Todoset\n\nFirst, get the todoset ID from the project's dock:\n\nGET /basecamp/buckets/{project_id}/todosets/{todoset_id}.json\n\nList Todolists\n\nGET /basecamp/buckets/{project_id}/todosets/{todoset_id}/todolists.json\n\nResponse:\n\n[\n  {\n    \"id\": 9550474442,\n    \"title\": \"Basecamp essentials\",\n    \"description\": \"\",\n    \"completed\": false,\n    \"completed_ratio\": \"0/5\",\n    \"url\": \"https://...\"\n  }\n]\n\nCreate Todolist\n\nPOST /basecamp/buckets/{project_id}/todosets/{todoset_id}/todolists.json\nContent-Type: application/json\n\n{\n  \"name\": \"New Todo List\",\n  \"description\": \"List description\"\n}\n\nGet Todolist\n\nGET /basecamp/buckets/{project_id}/todolists/{todolist_id}.json\n\nList Todos\n\nGET /basecamp/buckets/{project_id}/todolists/{todolist_id}/todos.json\n\nResponse:\n\n[\n  {\n    \"id\": 9550474446,\n    \"content\": \"Start here\",\n    \"description\": \"\",\n    \"completed\": false,\n    \"due_on\": null,\n    \"assignees\": []\n  }\n]\n\nCreate Todo\n\nPOST /basecamp/buckets/{project_id}/todolists/{todolist_id}/todos.json\nContent-Type: application/json\n\n{\n  \"content\": \"New todo item\",\n  \"description\": \"Todo description\",\n  \"due_on\": \"2026-02-15\",\n  \"assignee_ids\": [51197030]\n}\n\nResponse:\n\n{\n  \"id\": 9555973289,\n  \"content\": \"New todo item\",\n  \"completed\": false\n}\n\nUpdate Todo\n\nPUT /basecamp/buckets/{project_id}/todos/{todo_id}.json\nContent-Type: application/json\n\n{\n  \"content\": \"Updated todo\",\n  \"description\": \"Updated description\"\n}\n\nComplete Todo\n\nPOST /basecamp/buckets/{project_id}/todos/{todo_id}/completion.json\n\nReturns 204 on success.\n\nUncomplete Todo\n\nDELETE /basecamp/buckets/{project_id}/todos/{todo_id}/completion.json"
      },
      {
        "title": "Message Board Operations",
        "body": "Get Message Board\n\nGET /basecamp/buckets/{project_id}/message_boards/{message_board_id}.json\n\nList Messages\n\nGET /basecamp/buckets/{project_id}/message_boards/{message_board_id}/messages.json\n\nCreate Message\n\nPOST /basecamp/buckets/{project_id}/message_boards/{message_board_id}/messages.json\nContent-Type: application/json\n\n{\n  \"subject\": \"Message Subject\",\n  \"content\": \"<p>Message body with HTML</p>\",\n  \"category_id\": 123\n}\n\nGet Message\n\nGET /basecamp/buckets/{project_id}/messages/{message_id}.json\n\nUpdate Message\n\nPUT /basecamp/buckets/{project_id}/messages/{message_id}.json\nContent-Type: application/json\n\n{\n  \"subject\": \"Updated Subject\",\n  \"content\": \"<p>Updated content</p>\"\n}"
      },
      {
        "title": "Schedule Operations",
        "body": "Get Schedule\n\nGET /basecamp/buckets/{project_id}/schedules/{schedule_id}.json\n\nList Schedule Entries\n\nGET /basecamp/buckets/{project_id}/schedules/{schedule_id}/entries.json\n\nCreate Schedule Entry\n\nPOST /basecamp/buckets/{project_id}/schedules/{schedule_id}/entries.json\nContent-Type: application/json\n\n{\n  \"summary\": \"Team Meeting\",\n  \"description\": \"Weekly sync\",\n  \"starts_at\": \"2026-02-15T14:00:00Z\",\n  \"ends_at\": \"2026-02-15T15:00:00Z\",\n  \"all_day\": false,\n  \"participant_ids\": [51197030]\n}\n\nUpdate Schedule Entry\n\nPUT /basecamp/buckets/{project_id}/schedule_entries/{entry_id}.json\nContent-Type: application/json\n\n{\n  \"summary\": \"Updated Meeting\",\n  \"starts_at\": \"2026-02-15T15:00:00Z\",\n  \"ends_at\": \"2026-02-15T16:00:00Z\"\n}"
      },
      {
        "title": "Vault (Documents & Files) Operations",
        "body": "Get Vault\n\nGET /basecamp/buckets/{project_id}/vaults/{vault_id}.json\n\nList Documents in Vault\n\nGET /basecamp/buckets/{project_id}/vaults/{vault_id}/documents.json\n\nCreate Document\n\nPOST /basecamp/buckets/{project_id}/vaults/{vault_id}/documents.json\nContent-Type: application/json\n\n{\n  \"title\": \"Document Title\",\n  \"content\": \"<p>Document content with HTML</p>\"\n}\n\nList Uploads in Vault\n\nGET /basecamp/buckets/{project_id}/vaults/{vault_id}/uploads.json"
      },
      {
        "title": "Campfire (Chat) Operations",
        "body": "List All Campfires\n\nGET /basecamp/chats.json\n\nGet Campfire\n\nGET /basecamp/buckets/{project_id}/chats/{chat_id}.json\n\nList Campfire Lines (Messages)\n\nGET /basecamp/buckets/{project_id}/chats/{chat_id}/lines.json\n\nCreate Campfire Line\n\nPOST /basecamp/buckets/{project_id}/chats/{chat_id}/lines.json\nContent-Type: application/json\n\n{\n  \"content\": \"Hello from the API!\"\n}"
      },
      {
        "title": "Comments Operations",
        "body": "List Comments on Recording\n\nGET /basecamp/buckets/{project_id}/recordings/{recording_id}/comments.json\n\nCreate Comment\n\nPOST /basecamp/buckets/{project_id}/recordings/{recording_id}/comments.json\nContent-Type: application/json\n\n{\n  \"content\": \"<p>Comment text</p>\"\n}"
      },
      {
        "title": "Recording Status Operations",
        "body": "All content items (todos, messages, documents, etc.) are \"recordings\" that can be archived or trashed.\n\nTrash Recording\n\nPUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/trashed.json\n\nArchive Recording\n\nPUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/archived.json\n\nUnarchive Recording\n\nPUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/active.json"
      },
      {
        "title": "Templates Operations",
        "body": "List Templates\n\nGET /basecamp/templates.json\n\nCreate Project from Template\n\nPOST /basecamp/templates/{template_id}/project_constructions.json\nContent-Type: application/json\n\n{\n  \"name\": \"New Project from Template\",\n  \"description\": \"Description\"\n}"
      },
      {
        "title": "Pagination",
        "body": "Basecamp uses Link header pagination with rel=\"next\":\n\nResponse Headers:\n\nLink: <https://3.basecampapi.com/.../page=2>; rel=\"next\"\nX-Total-Count: 150\n\nFollow the Link header URL for the next page. When next is absent, you've reached the last page.\n\nImportant: Do not construct pagination URLs manually. Always use the URL provided in the Link header."
      },
      {
        "title": "Buckets and Projects",
        "body": "A \"bucket\" is a project's content container. The bucket ID is the same as the project ID in URLs:\n\n/buckets/{project_id}/todosets/{todoset_id}.json"
      },
      {
        "title": "Dock",
        "body": "Each project has a \"dock\" containing available tools. Always check that a tool is enabled: true before using it:\n\n{\n  \"dock\": [\n    {\"name\": \"todoset\", \"id\": 123, \"enabled\": true},\n    {\"name\": \"message_board\", \"id\": 456, \"enabled\": false}\n  ]\n}"
      },
      {
        "title": "Recordings",
        "body": "All content items (todos, messages, documents, comments, etc.) are \"recordings\" with:\n\nstatus: \"active\", \"archived\", or \"trashed\"\nparent: navigation to container\nUnique IDs that can be used across endpoints"
      },
      {
        "title": "JavaScript",
        "body": "const response = await fetch(\n  'https://gateway.maton.ai/basecamp/projects.json',\n  {\n    headers: {\n      'Authorization': `Bearer ${process.env.MATON_API_KEY}`\n    }\n  }\n);\nconst projects = await response.json();"
      },
      {
        "title": "Python",
        "body": "import os\nimport requests\n\nresponse = requests.get(\n    'https://gateway.maton.ai/basecamp/projects.json',\n    headers={'Authorization': f'Bearer {os.environ[\"MATON_API_KEY\"]}'}\n)\nprojects = response.json()"
      },
      {
        "title": "Notes",
        "body": "All API paths must end with .json\nThe gateway automatically injects the account ID\nUses Basecamp 4 API (bc3-api)\nTimestamps are in ISO 8601 format\nHTML content uses <div>, <p>, <strong>, <em>, <a>, <ul>, <ol>, <li> tags\nRate limit: ~50 requests per 10 seconds per IP\nIMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments"
      },
      {
        "title": "Error Handling",
        "body": "StatusMeaning400Missing Basecamp connection or bad request401Invalid or missing Maton API key404Resource not found, deleted, or no access429Rate limited (check Retry-After header)507Account limit reached (e.g., project limit)5xxServer error (retry with exponential backoff)"
      },
      {
        "title": "Troubleshooting: API Key Issues",
        "body": "Check that the MATON_API_KEY environment variable is set:\n\necho $MATON_API_KEY\n\nVerify the API key is valid by listing connections:\n\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://ctrl.maton.ai/connections')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF"
      },
      {
        "title": "Troubleshooting: Invalid App Name",
        "body": "Ensure your URL path starts with basecamp. For example:\n\nCorrect: https://gateway.maton.ai/basecamp/projects.json\nIncorrect: https://gateway.maton.ai/projects.json"
      },
      {
        "title": "Resources",
        "body": "Basecamp 4 API Documentation\nAuthentication Guide\nAPI Reference\nMaton Community\nMaton Support"
      }
    ],
    "body": "Basecamp\n\nAccess the Basecamp 4 API with managed OAuth authentication. Manage projects, to-dos, messages, schedules, documents, and team collaboration.\n\nQuick Start\n# List all projects\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://gateway.maton.ai/basecamp/projects.json')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\nBase URL\nhttps://gateway.maton.ai/basecamp/{resource}.json\n\n\nThe gateway proxies requests to 3.basecampapi.com/{account_id}/ and automatically injects your OAuth token and account ID.\n\nImportant: All Basecamp API URLs must end with .json.\n\nAuthentication\n\nAll requests require the Maton API key in the Authorization header:\n\nAuthorization: Bearer $MATON_API_KEY\n\n\nEnvironment Variable: Set your API key as MATON_API_KEY:\n\nexport MATON_API_KEY=\"YOUR_API_KEY\"\n\nGetting Your API Key\nSign in or create an account at maton.ai\nGo to maton.ai/settings\nCopy your API key\nConnection Management\n\nManage your Basecamp OAuth connections at https://ctrl.maton.ai.\n\nList Connections\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://ctrl.maton.ai/connections?app=basecamp&status=ACTIVE')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\nCreate Connection\npython <<'EOF'\nimport urllib.request, os, json\ndata = json.dumps({'app': 'basecamp'}).encode()\nreq = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Content-Type', 'application/json')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\nGet Connection\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\n\nResponse:\n\n{\n  \"connection\": {\n    \"connection_id\": \"71e313c8-9100-48c6-8ea1-6323f6fafd04\",\n    \"status\": \"ACTIVE\",\n    \"creation_time\": \"2026-02-08T03:12:39.815086Z\",\n    \"last_updated_time\": \"2026-02-08T03:12:59.259878Z\",\n    \"url\": \"https://connect.maton.ai/?session_token=...\",\n    \"app\": \"basecamp\",\n    \"metadata\": {}\n  }\n}\n\n\nOpen the returned url in a browser to complete OAuth authorization.\n\nDelete Connection\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\nSpecifying Connection\n\nIf you have multiple Basecamp connections, specify which one to use with the Maton-Connection header:\n\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://gateway.maton.ai/basecamp/projects.json')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Maton-Connection', '71e313c8-9100-48c6-8ea1-6323f6fafd04')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\n\nIf omitted, the gateway uses the default (oldest) active connection.\n\nAPI Reference\nUser Info\nGet Current User\nGET /basecamp/my/profile.json\n\n\nResponse:\n\n{\n  \"id\": 51197030,\n  \"name\": \"Chris Kim\",\n  \"email_address\": \"chris@example.com\",\n  \"admin\": true,\n  \"owner\": true,\n  \"time_zone\": \"America/Los_Angeles\",\n  \"avatar_url\": \"https://...\"\n}\n\nPeople Operations\nList People\nGET /basecamp/people.json\n\n\nResponse:\n\n[\n  {\n    \"id\": 51197030,\n    \"name\": \"Chris Kim\",\n    \"email_address\": \"chris@example.com\",\n    \"admin\": true,\n    \"owner\": true,\n    \"employee\": true,\n    \"time_zone\": \"America/Los_Angeles\"\n  }\n]\n\nGet Person\nGET /basecamp/people/{person_id}.json\n\nList Project Members\nGET /basecamp/projects/{project_id}/people.json\n\nProject Operations\nList Projects\nGET /basecamp/projects.json\n\n\nResponse:\n\n[\n  {\n    \"id\": 46005636,\n    \"status\": \"active\",\n    \"name\": \"Getting Started\",\n    \"description\": \"Quickly get up to speed with everything Basecamp\",\n    \"created_at\": \"2026-02-05T22:59:26.087Z\",\n    \"url\": \"https://3.basecampapi.com/6153810/projects/46005636.json\",\n    \"dock\": [...]\n  }\n]\n\nGet Project\nGET /basecamp/projects/{project_id}.json\n\n\nThe project response includes a dock array with available tools (message_board, todoset, vault, chat, schedule, etc.). Each dock item has:\n\nid: The tool's ID\nname: Tool type (e.g., \"todoset\", \"message_board\")\nenabled: Whether the tool is active\nurl: Direct URL to access the tool\nCreate Project\nPOST /basecamp/projects.json\nContent-Type: application/json\n\n{\n  \"name\": \"New Project\",\n  \"description\": \"Project description\"\n}\n\nUpdate Project\nPUT /basecamp/projects/{project_id}.json\nContent-Type: application/json\n\n{\n  \"name\": \"Updated Project Name\",\n  \"description\": \"Updated description\"\n}\n\nDelete (Trash) Project\nDELETE /basecamp/projects/{project_id}.json\n\nTo-Do Operations\nGet Todoset\n\nFirst, get the todoset ID from the project's dock:\n\nGET /basecamp/buckets/{project_id}/todosets/{todoset_id}.json\n\nList Todolists\nGET /basecamp/buckets/{project_id}/todosets/{todoset_id}/todolists.json\n\n\nResponse:\n\n[\n  {\n    \"id\": 9550474442,\n    \"title\": \"Basecamp essentials\",\n    \"description\": \"\",\n    \"completed\": false,\n    \"completed_ratio\": \"0/5\",\n    \"url\": \"https://...\"\n  }\n]\n\nCreate Todolist\nPOST /basecamp/buckets/{project_id}/todosets/{todoset_id}/todolists.json\nContent-Type: application/json\n\n{\n  \"name\": \"New Todo List\",\n  \"description\": \"List description\"\n}\n\nGet Todolist\nGET /basecamp/buckets/{project_id}/todolists/{todolist_id}.json\n\nList Todos\nGET /basecamp/buckets/{project_id}/todolists/{todolist_id}/todos.json\n\n\nResponse:\n\n[\n  {\n    \"id\": 9550474446,\n    \"content\": \"Start here\",\n    \"description\": \"\",\n    \"completed\": false,\n    \"due_on\": null,\n    \"assignees\": []\n  }\n]\n\nCreate Todo\nPOST /basecamp/buckets/{project_id}/todolists/{todolist_id}/todos.json\nContent-Type: application/json\n\n{\n  \"content\": \"New todo item\",\n  \"description\": \"Todo description\",\n  \"due_on\": \"2026-02-15\",\n  \"assignee_ids\": [51197030]\n}\n\n\nResponse:\n\n{\n  \"id\": 9555973289,\n  \"content\": \"New todo item\",\n  \"completed\": false\n}\n\nUpdate Todo\nPUT /basecamp/buckets/{project_id}/todos/{todo_id}.json\nContent-Type: application/json\n\n{\n  \"content\": \"Updated todo\",\n  \"description\": \"Updated description\"\n}\n\nComplete Todo\nPOST /basecamp/buckets/{project_id}/todos/{todo_id}/completion.json\n\n\nReturns 204 on success.\n\nUncomplete Todo\nDELETE /basecamp/buckets/{project_id}/todos/{todo_id}/completion.json\n\nMessage Board Operations\nGet Message Board\nGET /basecamp/buckets/{project_id}/message_boards/{message_board_id}.json\n\nList Messages\nGET /basecamp/buckets/{project_id}/message_boards/{message_board_id}/messages.json\n\nCreate Message\nPOST /basecamp/buckets/{project_id}/message_boards/{message_board_id}/messages.json\nContent-Type: application/json\n\n{\n  \"subject\": \"Message Subject\",\n  \"content\": \"<p>Message body with HTML</p>\",\n  \"category_id\": 123\n}\n\nGet Message\nGET /basecamp/buckets/{project_id}/messages/{message_id}.json\n\nUpdate Message\nPUT /basecamp/buckets/{project_id}/messages/{message_id}.json\nContent-Type: application/json\n\n{\n  \"subject\": \"Updated Subject\",\n  \"content\": \"<p>Updated content</p>\"\n}\n\nSchedule Operations\nGet Schedule\nGET /basecamp/buckets/{project_id}/schedules/{schedule_id}.json\n\nList Schedule Entries\nGET /basecamp/buckets/{project_id}/schedules/{schedule_id}/entries.json\n\nCreate Schedule Entry\nPOST /basecamp/buckets/{project_id}/schedules/{schedule_id}/entries.json\nContent-Type: application/json\n\n{\n  \"summary\": \"Team Meeting\",\n  \"description\": \"Weekly sync\",\n  \"starts_at\": \"2026-02-15T14:00:00Z\",\n  \"ends_at\": \"2026-02-15T15:00:00Z\",\n  \"all_day\": false,\n  \"participant_ids\": [51197030]\n}\n\nUpdate Schedule Entry\nPUT /basecamp/buckets/{project_id}/schedule_entries/{entry_id}.json\nContent-Type: application/json\n\n{\n  \"summary\": \"Updated Meeting\",\n  \"starts_at\": \"2026-02-15T15:00:00Z\",\n  \"ends_at\": \"2026-02-15T16:00:00Z\"\n}\n\nVault (Documents & Files) Operations\nGet Vault\nGET /basecamp/buckets/{project_id}/vaults/{vault_id}.json\n\nList Documents in Vault\nGET /basecamp/buckets/{project_id}/vaults/{vault_id}/documents.json\n\nCreate Document\nPOST /basecamp/buckets/{project_id}/vaults/{vault_id}/documents.json\nContent-Type: application/json\n\n{\n  \"title\": \"Document Title\",\n  \"content\": \"<p>Document content with HTML</p>\"\n}\n\nList Uploads in Vault\nGET /basecamp/buckets/{project_id}/vaults/{vault_id}/uploads.json\n\nCampfire (Chat) Operations\nList All Campfires\nGET /basecamp/chats.json\n\nGet Campfire\nGET /basecamp/buckets/{project_id}/chats/{chat_id}.json\n\nList Campfire Lines (Messages)\nGET /basecamp/buckets/{project_id}/chats/{chat_id}/lines.json\n\nCreate Campfire Line\nPOST /basecamp/buckets/{project_id}/chats/{chat_id}/lines.json\nContent-Type: application/json\n\n{\n  \"content\": \"Hello from the API!\"\n}\n\nComments Operations\nList Comments on Recording\nGET /basecamp/buckets/{project_id}/recordings/{recording_id}/comments.json\n\nCreate Comment\nPOST /basecamp/buckets/{project_id}/recordings/{recording_id}/comments.json\nContent-Type: application/json\n\n{\n  \"content\": \"<p>Comment text</p>\"\n}\n\nRecording Status Operations\n\nAll content items (todos, messages, documents, etc.) are \"recordings\" that can be archived or trashed.\n\nTrash Recording\nPUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/trashed.json\n\nArchive Recording\nPUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/archived.json\n\nUnarchive Recording\nPUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/active.json\n\nTemplates Operations\nList Templates\nGET /basecamp/templates.json\n\nCreate Project from Template\nPOST /basecamp/templates/{template_id}/project_constructions.json\nContent-Type: application/json\n\n{\n  \"name\": \"New Project from Template\",\n  \"description\": \"Description\"\n}\n\nPagination\n\nBasecamp uses Link header pagination with rel=\"next\":\n\nResponse Headers:\n\nLink: <https://3.basecampapi.com/.../page=2>; rel=\"next\"\nX-Total-Count: 150\n\n\nFollow the Link header URL for the next page. When next is absent, you've reached the last page.\n\nImportant: Do not construct pagination URLs manually. Always use the URL provided in the Link header.\n\nKey Concepts\nBuckets and Projects\n\nA \"bucket\" is a project's content container. The bucket ID is the same as the project ID in URLs:\n\n/buckets/{project_id}/todosets/{todoset_id}.json\n\nDock\n\nEach project has a \"dock\" containing available tools. Always check that a tool is enabled: true before using it:\n\n{\n  \"dock\": [\n    {\"name\": \"todoset\", \"id\": 123, \"enabled\": true},\n    {\"name\": \"message_board\", \"id\": 456, \"enabled\": false}\n  ]\n}\n\nRecordings\n\nAll content items (todos, messages, documents, comments, etc.) are \"recordings\" with:\n\nstatus: \"active\", \"archived\", or \"trashed\"\nparent: navigation to container\nUnique IDs that can be used across endpoints\nCode Examples\nJavaScript\nconst response = await fetch(\n  'https://gateway.maton.ai/basecamp/projects.json',\n  {\n    headers: {\n      'Authorization': `Bearer ${process.env.MATON_API_KEY}`\n    }\n  }\n);\nconst projects = await response.json();\n\nPython\nimport os\nimport requests\n\nresponse = requests.get(\n    'https://gateway.maton.ai/basecamp/projects.json',\n    headers={'Authorization': f'Bearer {os.environ[\"MATON_API_KEY\"]}'}\n)\nprojects = response.json()\n\nNotes\nAll API paths must end with .json\nThe gateway automatically injects the account ID\nUses Basecamp 4 API (bc3-api)\nTimestamps are in ISO 8601 format\nHTML content uses <div>, <p>, <strong>, <em>, <a>, <ul>, <ol>, <li> tags\nRate limit: ~50 requests per 10 seconds per IP\nIMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments\nError Handling\nStatus\tMeaning\n400\tMissing Basecamp connection or bad request\n401\tInvalid or missing Maton API key\n404\tResource not found, deleted, or no access\n429\tRate limited (check Retry-After header)\n507\tAccount limit reached (e.g., project limit)\n5xx\tServer error (retry with exponential backoff)\nTroubleshooting: API Key Issues\nCheck that the MATON_API_KEY environment variable is set:\necho $MATON_API_KEY\n\nVerify the API key is valid by listing connections:\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://ctrl.maton.ai/connections')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n\nTroubleshooting: Invalid App Name\nEnsure your URL path starts with basecamp. For example:\nCorrect: https://gateway.maton.ai/basecamp/projects.json\nIncorrect: https://gateway.maton.ai/projects.json\nResources\nBasecamp 4 API Documentation\nAuthentication Guide\nAPI Reference\nMaton Community\nMaton Support"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/byungkyu/basecamp",
    "publisherUrl": "https://clawhub.ai/byungkyu/basecamp",
    "owner": "byungkyu",
    "version": "1.0.2",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/basecamp",
    "downloadUrl": "https://openagent3.xyz/downloads/basecamp",
    "agentUrl": "https://openagent3.xyz/skills/basecamp/agent",
    "manifestUrl": "https://openagent3.xyz/skills/basecamp/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/basecamp/agent.md"
  }
}