basecamp

star 8

Basecamp API integration with managed OAuth. Manage projects, to-dos, messages, schedules, documents, and team collaboration. Use this skill when users want to create and manage projects, to-do lists, schedule events, or collaborate with teams in Basecamp. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key.

modbender By modbender schedule Updated 3/6/2026

name: basecamp

description: |

Basecamp API integration with managed OAuth. Manage projects, to-dos, messages, schedules, documents, and team collaboration.

Use this skill when users want to create and manage projects, to-do lists, schedule events, or collaborate with teams in Basecamp.

For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).

Requires network access and valid Maton API key.

metadata:

author: maton

version: "1.0"

clawdbot:

emoji: 🧠

requires:

  env:

    - MATON_API_KEY

Basecamp

Access the Basecamp 4 API with managed OAuth authentication. Manage projects, to-dos, messages, schedules, documents, and team collaboration.

Quick Start


# List all projects

python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://gateway.maton.ai/basecamp/projects.json')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Base URL


https://gateway.maton.ai/basecamp/{resource}.json

The gateway proxies requests to 3.basecampapi.com/{account_id}/ and automatically injects your OAuth token and account ID.

Important: All Basecamp API URLs must end with .json.

Authentication

All requests require the Maton API key in the Authorization header:


Authorization: Bearer $MATON_API_KEY

Environment Variable: Set your API key as MATON_API_KEY:


export MATON_API_KEY="YOUR_API_KEY"

Getting Your API Key

  1. Sign in or create an account at maton.ai

  2. Go to maton.ai/settings

  3. Copy your API key

Connection Management

Manage your Basecamp OAuth connections at https://ctrl.maton.ai.

List Connections


python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://ctrl.maton.ai/connections?app=basecamp&status=ACTIVE')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Create Connection


python <<'EOF'

import urllib.request, os, json

data = json.dumps({'app': 'basecamp'}).encode()

req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

req.add_header('Content-Type', 'application/json')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Get Connection


python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Response:


{

  "connection": {

    "connection_id": "71e313c8-9100-48c6-8ea1-6323f6fafd04",

    "status": "ACTIVE",

    "creation_time": "2026-02-08T03:12:39.815086Z",

    "last_updated_time": "2026-02-08T03:12:59.259878Z",

    "url": "https://connect.maton.ai/?session_token=...",

    "app": "basecamp",

    "metadata": {}

  }

}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection


python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Specifying Connection

If you have multiple Basecamp connections, specify which one to use with the Maton-Connection header:


python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://gateway.maton.ai/basecamp/projects.json')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

req.add_header('Maton-Connection', '71e313c8-9100-48c6-8ea1-6323f6fafd04')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

If omitted, the gateway uses the default (oldest) active connection.

API Reference

User Info

Get Current User


GET /basecamp/my/profile.json

Response:


{

  "id": 51197030,

  "name": "Chris Kim",

  "email_address": "chris@example.com",

  "admin": true,

  "owner": true,

  "time_zone": "America/Los_Angeles",

  "avatar_url": "https://..."

}

People Operations

List People


GET /basecamp/people.json

Response:


[

  {

    "id": 51197030,

    "name": "Chris Kim",

    "email_address": "chris@example.com",

    "admin": true,

    "owner": true,

    "employee": true,

    "time_zone": "America/Los_Angeles"

  }

]

Get Person


GET /basecamp/people/{person_id}.json

List Project Members


GET /basecamp/projects/{project_id}/people.json

Project Operations

List Projects


GET /basecamp/projects.json

Response:


[

  {

    "id": 46005636,

    "status": "active",

    "name": "Getting Started",

    "description": "Quickly get up to speed with everything Basecamp",

    "created_at": "2026-02-05T22:59:26.087Z",

    "url": "https://3.basecampapi.com/6153810/projects/46005636.json",

    "dock": [...]

  }

]

Get Project


GET /basecamp/projects/{project_id}.json

The project response includes a dock array with available tools (message_board, todoset, vault, chat, schedule, etc.). Each dock item has:

  • id: The tool's ID

  • name: Tool type (e.g., "todoset", "message_board")

  • enabled: Whether the tool is active

  • url: Direct URL to access the tool

Create Project


POST /basecamp/projects.json

Content-Type: application/json



{

  "name": "New Project",

  "description": "Project description"

}

Update Project


PUT /basecamp/projects/{project_id}.json

Content-Type: application/json



{

  "name": "Updated Project Name",

  "description": "Updated description"

}

Delete (Trash) Project


DELETE /basecamp/projects/{project_id}.json

To-Do Operations

Get Todoset

First, get the todoset ID from the project's dock:


GET /basecamp/buckets/{project_id}/todosets/{todoset_id}.json

List Todolists


GET /basecamp/buckets/{project_id}/todosets/{todoset_id}/todolists.json

Response:


[

  {

    "id": 9550474442,

    "title": "Basecamp essentials",

    "description": "",

    "completed": false,

    "completed_ratio": "0/5",

    "url": "https://..."

  }

]

Create Todolist


POST /basecamp/buckets/{project_id}/todosets/{todoset_id}/todolists.json

Content-Type: application/json



{

  "name": "New Todo List",

  "description": "List description"

}

Get Todolist


GET /basecamp/buckets/{project_id}/todolists/{todolist_id}.json

List Todos


GET /basecamp/buckets/{project_id}/todolists/{todolist_id}/todos.json

Response:


[

  {

    "id": 9550474446,

    "content": "Start here",

    "description": "",

    "completed": false,

    "due_on": null,

    "assignees": []

  }

]

Create Todo


POST /basecamp/buckets/{project_id}/todolists/{todolist_id}/todos.json

Content-Type: application/json



{

  "content": "New todo item",

  "description": "Todo description",

  "due_on": "2026-02-15",

  "assignee_ids": [51197030]

}

Response:


{

  "id": 9555973289,

  "content": "New todo item",

  "completed": false

}

Update Todo


PUT /basecamp/buckets/{project_id}/todos/{todo_id}.json

Content-Type: application/json



{

  "content": "Updated todo",

  "description": "Updated description"

}

Complete Todo


POST /basecamp/buckets/{project_id}/todos/{todo_id}/completion.json

Returns 204 on success.

Uncomplete Todo


DELETE /basecamp/buckets/{project_id}/todos/{todo_id}/completion.json

Message Board Operations

Get Message Board


GET /basecamp/buckets/{project_id}/message_boards/{message_board_id}.json

List Messages


GET /basecamp/buckets/{project_id}/message_boards/{message_board_id}/messages.json

Create Message


POST /basecamp/buckets/{project_id}/message_boards/{message_board_id}/messages.json

Content-Type: application/json



{

  "subject": "Message Subject",

  "content": "<p>Message body with HTML</p>",

  "category_id": 123

}

Get Message


GET /basecamp/buckets/{project_id}/messages/{message_id}.json

Update Message


PUT /basecamp/buckets/{project_id}/messages/{message_id}.json

Content-Type: application/json



{

  "subject": "Updated Subject",

  "content": "<p>Updated content</p>"

}

Schedule Operations

Get Schedule


GET /basecamp/buckets/{project_id}/schedules/{schedule_id}.json

List Schedule Entries


GET /basecamp/buckets/{project_id}/schedules/{schedule_id}/entries.json

Create Schedule Entry


POST /basecamp/buckets/{project_id}/schedules/{schedule_id}/entries.json

Content-Type: application/json



{

  "summary": "Team Meeting",

  "description": "Weekly sync",

  "starts_at": "2026-02-15T14:00:00Z",

  "ends_at": "2026-02-15T15:00:00Z",

  "all_day": false,

  "participant_ids": [51197030]

}

Update Schedule Entry


PUT /basecamp/buckets/{project_id}/schedule_entries/{entry_id}.json

Content-Type: application/json



{

  "summary": "Updated Meeting",

  "starts_at": "2026-02-15T15:00:00Z",

  "ends_at": "2026-02-15T16:00:00Z"

}

Vault (Documents & Files) Operations

Get Vault


GET /basecamp/buckets/{project_id}/vaults/{vault_id}.json

List Documents in Vault


GET /basecamp/buckets/{project_id}/vaults/{vault_id}/documents.json

Create Document


POST /basecamp/buckets/{project_id}/vaults/{vault_id}/documents.json

Content-Type: application/json



{

  "title": "Document Title",

  "content": "<p>Document content with HTML</p>"

}

List Uploads in Vault


GET /basecamp/buckets/{project_id}/vaults/{vault_id}/uploads.json

Campfire (Chat) Operations

List All Campfires


GET /basecamp/chats.json

Get Campfire


GET /basecamp/buckets/{project_id}/chats/{chat_id}.json

List Campfire Lines (Messages)


GET /basecamp/buckets/{project_id}/chats/{chat_id}/lines.json

Create Campfire Line


POST /basecamp/buckets/{project_id}/chats/{chat_id}/lines.json

Content-Type: application/json



{

  "content": "Hello from the API!"

}

Comments Operations

List Comments on Recording


GET /basecamp/buckets/{project_id}/recordings/{recording_id}/comments.json

Create Comment


POST /basecamp/buckets/{project_id}/recordings/{recording_id}/comments.json

Content-Type: application/json



{

  "content": "<p>Comment text</p>"

}

Recording Status Operations

All content items (todos, messages, documents, etc.) are "recordings" that can be archived or trashed.

Trash Recording


PUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/trashed.json

Archive Recording


PUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/archived.json

Unarchive Recording


PUT /basecamp/buckets/{project_id}/recordings/{recording_id}/status/active.json

Templates Operations

List Templates


GET /basecamp/templates.json

Create Project from Template


POST /basecamp/templates/{template_id}/project_constructions.json

Content-Type: application/json



{

  "name": "New Project from Template",

  "description": "Description"

}

Pagination

Basecamp uses Link header pagination with rel="next":

Response Headers:


Link: <https://3.basecampapi.com/.../page=2>; rel="next"

X-Total-Count: 150

Follow the Link header URL for the next page. When next is absent, you've reached the last page.

Important: Do not construct pagination URLs manually. Always use the URL provided in the Link header.

Key Concepts

Buckets and Projects

A "bucket" is a project's content container. The bucket ID is the same as the project ID in URLs:


/buckets/{project_id}/todosets/{todoset_id}.json

Dock

Each project has a "dock" containing available tools. Always check that a tool is enabled: true before using it:


{

  "dock": [

    {"name": "todoset", "id": 123, "enabled": true},

    {"name": "message_board", "id": 456, "enabled": false}

  ]

}

Recordings

All content items (todos, messages, documents, comments, etc.) are "recordings" with:

  • status: "active", "archived", or "trashed"

  • parent: navigation to container

  • Unique IDs that can be used across endpoints

Code Examples

JavaScript


const response = await fetch(

  'https://gateway.maton.ai/basecamp/projects.json',

  {

    headers: {

      'Authorization': `Bearer ${process.env.MATON_API_KEY}`

    }

  }

);

const projects = await response.json();

Python


import os

import requests



response = requests.get(

    'https://gateway.maton.ai/basecamp/projects.json',

    headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}

)

projects = response.json()

Notes

  • All API paths must end with .json

  • The gateway automatically injects the account ID

  • Uses Basecamp 4 API (bc3-api)

  • Timestamps are in ISO 8601 format

  • HTML content uses <div>, <p>, <strong>, <em>, <a>, <ul>, <ol>, <li> tags

  • Rate limit: ~50 requests per 10 seconds per IP

  • IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments

Error Handling

| Status | Meaning |

|--------|---------|

| 400 | Missing Basecamp connection or bad request |

| 401 | Invalid or missing Maton API key |

| 404 | Resource not found, deleted, or no access |

| 429 | Rate limited (check Retry-After header) |

| 507 | Account limit reached (e.g., project limit) |

| 5xx | Server error (retry with exponential backoff) |

Troubleshooting: API Key Issues

  1. Check that the MATON_API_KEY environment variable is set:

echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:

python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://ctrl.maton.ai/connections')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with basecamp. For example:
  • Correct: https://gateway.maton.ai/basecamp/projects.json

  • Incorrect: https://gateway.maton.ai/projects.json

Resources

Install via CLI
npx skills add https://github.com/modbender/skill-library-mcp --skill basecamp
Repository Details
star Stars 8
call_split Forks 2
navigation Branch main
article Path SKILL.md
More from Creator