HomeBrowseUpload
← Back to registry
// Skill profile

Basecamp

name: basecamp

by byungkyu · published 2026-03-22

邮件处理日历管理加密货币
Total installs
0
Stars
★ 0
Last updated
2026-03
// Install command
$ claw add gh:byungkyu/byungkyu-basecamp
View on GitHub
// Full documentation

---

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](https://maton.ai)

2. Go to [maton.ai/settings](https://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

    2. 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

  • [Basecamp 4 API Documentation](https://github.com/basecamp/bc3-api)
  • [Authentication Guide](https://github.com/basecamp/bc3-api/blob/master/sections/authentication.md)
  • [API Reference](https://github.com/basecamp/bc3-api#endpoints)
  • [Maton Community](https://discord.com/invite/dBfFAcefs2)
  • [Maton Support](mailto:support@maton.ai)
  • // Comments
    Sign in with GitHub to leave a comment.
    // Related skills

    More tools from the same signal band