Skip to content

Basecamp Integration Guide ​

spectryn supports Basecamp 3 for syncing markdown specifications. This guide covers OAuth setup, account and project configuration, and the Todo vs Message mapping strategy.

Overview ​

The Basecamp adapter supports:

  • ✅ Projects (epics), Todos and Messages (stories), and Todo items (subtasks)
  • ✅ Status mapping via todo completion state
  • ✅ Priority and story points (stored in notes)
  • ✅ Comments sync
  • ✅ Campfire (chat) integration
  • ✅ Webhooks for real-time sync
  • ✅ Message boards as alternative to todos

Quick Start ​

bash
# Install spectryn
pip install spectryn

# Sync markdown to Basecamp
spectryn --markdown EPIC.md --tracker basecamp --execute

Configuration ​

Config File (YAML) ​

Create .spectryn.yaml:

yaml
# Basecamp connection settings
basecamp:
  access_token: your-basecamp-access-token
  account_id: "123456"  # Basecamp account ID
  project_id: "789012"  # Basecamp project ID
  api_url: https://3.basecampapi.com  # Optional: defaults to Basecamp 3 API
  use_messages_for_stories: false  # Optional: use Messages instead of Todos

# Sync settings
sync:
  execute: false  # Set to true for live mode
  verbose: true

Config File (TOML) ​

Create .spectryn.toml:

toml
[basecamp]
access_token = "your-basecamp-access-token"
account_id = "123456"
project_id = "789012"
api_url = "https://3.basecampapi.com"
use_messages_for_stories = false

[sync]
execute = false
verbose = true

Environment Variables ​

bash
# Required
export BASECAMP_ACCESS_TOKEN=your-basecamp-access-token
export BASECAMP_ACCOUNT_ID=123456
export BASECAMP_PROJECT_ID=789012

# Optional
export BASECAMP_API_URL=https://3.basecampapi.com
export BASECAMP_USE_MESSAGES_FOR_STORIES=false

CLI Arguments ​

bash
spectryn \
  --markdown EPIC.md \
  --tracker basecamp \
  --basecamp-access-token your-token \
  --basecamp-account-id 123456 \
  --basecamp-project-id 789012 \
  --execute

OAuth Setup ​

Basecamp 3 uses OAuth 2.0 for authentication. You'll need to create an OAuth application and obtain an access token.

Step 1: Create OAuth Application ​

  1. Log in to Basecamp

  2. Navigate to Integrations

    • Click on your account name (top right)
    • Go to Settings → Integrations → OAuth Applications
    • Or visit: https://launchpad.37signals.com/integrations
  3. Create New Application

    • Click "New application" or "Create a new application"
    • Fill in the application details:
      • Name: spectryn-sync (or your preferred name)
      • Description: CLI tool for syncing markdown specifications to Basecamp
      • Redirect URI: urn:ietf:wg:oauth:2.0:oob (for CLI applications)
      • Scopes: Select the permissions you need:
        • ✅ Read - Read todos, messages, comments
        • ✅ Write - Create and update todos, messages, comments
        • ✅ Admin - Full access (if you need to manage projects)
  4. Save Application

    • Click "Save" or "Create application"
    • You'll receive a Client ID and Client Secret

Step 2: Obtain Access Token ​

There are two ways to get an access token:

  1. Go to Account Settings

    • Navigate to your account settings
    • Go to "My info" → "API tokens" or visit: https://3.basecampapi.com/YOUR_ACCOUNT_ID/people/me.json
  2. Generate Token

    • Click "Create a new token"
    • Give it a name: spectryn-sync
    • Select scopes (same as OAuth scopes)
    • Copy the token immediately (shown only once)

Option B: OAuth 2.0 Flow (For Applications) ​

If you're building an application that needs OAuth:

  1. Authorize Application

    https://launchpad.37signals.com/authorization/new?
      type=web_server&
      client_id=YOUR_CLIENT_ID&
      redirect_uri=urn:ietf:wg:oauth:2.0:oob&
      response_type=code
  2. Get Authorization Code

    • User authorizes the application
    • Copy the authorization code from the redirect
  3. Exchange for Access Token

    bash
    curl -X POST https://launchpad.37signals.com/authorization/token \
      -H "Content-Type: application/json" \
      -d '{
        "type": "web_server",
        "client_id": "YOUR_CLIENT_ID",
        "client_secret": "YOUR_CLIENT_SECRET",
        "redirect_uri": "urn:ietf:wg:oauth:2.0:oob",
        "code": "AUTHORIZATION_CODE"
      }'
  4. Use Access Token

    • The response contains an access_token
    • Use this token for API requests

Step 3: Configure spectryn ​

Set the access token as an environment variable:

bash
export BASECAMP_ACCESS_TOKEN=your-access-token-here

Or in your config file:

yaml
basecamp:
  access_token: your-access-token-here

Token Permissions ​

ScopeRequired For
ReadViewing todos, messages, comments
WriteCreating/updating todos, messages, comments
AdminManaging projects, webhooks, Campfire

Security

  • Never commit tokens to version control
  • Use environment variables or .env files (add to .gitignore)
  • Rotate tokens regularly
  • Use tokens with minimal required permissions
  • Personal access tokens don't expire, but OAuth tokens may

Account and Project Configuration ​

Finding Your Account ID ​

The account ID is the numeric identifier for your Basecamp account.

  1. Method 1: From API Response

    bash
    curl -H "Authorization: Bearer YOUR_TOKEN" \
      https://3.basecampapi.com/people/me.json

    Look for accounts array - each account has an id field.

  2. Method 2: From Basecamp URL

    • When viewing a project, check the URL
    • Format: https://3.basecampapi.com/{ACCOUNT_ID}/projects/{PROJECT_ID}
    • The first number is your account ID
  3. Method 3: From Basecamp Web Interface

    • Go to your account settings
    • The account ID may be visible in the URL or API settings

Finding Your Project ID ​

The project ID is the numeric identifier for a specific Basecamp project.

  1. Method 1: From Project URL

    • Open your Basecamp project in a web browser
    • Check the URL: https://3.basecampapi.com/{ACCOUNT_ID}/projects/{PROJECT_ID}
    • The project ID is the number after /projects/
  2. Method 2: List Projects via API

    bash
    curl -H "Authorization: Bearer YOUR_TOKEN" \
      https://3.basecampapi.com/{ACCOUNT_ID}/projects.json

    Each project in the response has an id field.

  3. Method 3: From Basecamp Web Interface

    • Go to your project
    • Check the browser's developer tools → Network tab
    • Look for API requests - the project ID appears in URLs

Configuration Example ​

yaml
basecamp:
  access_token: ${BASECAMP_ACCESS_TOKEN}
  account_id: "123456"      # Your Basecamp account ID
  project_id: "789012"      # Your Basecamp project ID
  api_url: https://3.basecampapi.com
bash
# Set environment variables
export BASECAMP_ACCESS_TOKEN=your-token
export BASECAMP_ACCOUNT_ID=123456
export BASECAMP_PROJECT_ID=789012

Todo vs Message Mapping ​

Basecamp 3 offers two ways to represent stories: Todos and Messages. The adapter supports both, and you can choose which one fits your workflow.

Todos (Default) ​

Use Todos when:

  • ✅ You need task tracking with completion status
  • ✅ You want assignees and due dates
  • ✅ You need subtasks (todo items)
  • ✅ You're managing a backlog or sprint

Characteristics:

  • Can be marked as completed/not completed
  • Support assignees and due dates
  • Organized in Todo Sets (lists)
  • Can have subtasks (todo items within a todo)

Example:

markdown
### STORY-001: Implement Login Feature
**Status:** In Progress
**Story Points:** 5
**Assignee:** john@example.com
**Due Date:** 2024-12-31

Creates a todo in Basecamp that can be:

  • Assigned to team members
  • Marked as completed
  • Given a due date
  • Broken down into subtasks

Messages ​

Use Messages when:

  • ✅ You want discussion-focused content
  • ✅ You need announcements or updates
  • ✅ You're documenting decisions or proposals
  • ✅ Completion status isn't important

Characteristics:

  • Posted to Message Boards
  • Organized by categories
  • Better for discussions and documentation
  • No completion status (always "Planned")

Example:

markdown
### STORY-001: Design System Proposal
**Status:** Planned
**Story Points:** 3

Creates a message in Basecamp that:

  • Appears in the project's message board
  • Can be categorized
  • Supports rich text content
  • Encourages discussion via comments

Configuration ​

Choose your mapping strategy:

yaml
# Use Todos (default)
basecamp:
  use_messages_for_stories: false

# Use Messages
basecamp:
  use_messages_for_stories: true

Mapping Summary ​

spectryn ConceptBasecamp (Todos)Basecamp (Messages)
EpicProject or Todo SetProject or Message Board Category
StoryTodoMessage
SubtaskTodo Item (within todo)Not supported
StatusCompleted/Not CompletedAlways "Planned"
PriorityStored in notesStored in content
Story PointsStored in notesStored in content
AssigneeSupportedNot supported
Due DateSupportedNot supported

When to Use Each ​

Choose Todos if:

  • You're managing a development backlog
  • You need to track completion status
  • Assignees and due dates are important
  • You have subtasks to track

Choose Messages if:

  • You're documenting decisions or proposals
  • Discussion is more important than completion
  • You want announcement-style updates
  • You don't need task tracking

Switching Between Modes ​

You can switch between modes, but note:

  • Existing todos won't become messages (and vice versa)
  • You may need to manually migrate content
  • Consider your team's workflow before switching

Status Mapping ​

Basecamp todos use a simple completion model. The adapter maps standard statuses:

spectryn StatusBasecamp Todo Status
Done, Completed, Closed, Resolved✅ Completed
Planned, To Do, Backlog⬜ Not Completed
In Progress, In Review⬜ Not Completed (status in notes)
Blocked, On Hold⬜ Not Completed (status in notes)

Note: Messages don't have completion status - they're always "Planned".

Priority and Story Points ​

Basecamp doesn't natively support priority or story points. The adapter stores these values in the notes field (for todos) or content field (for messages).

Format ​

The adapter stores metadata in this format:

markdown
**Priority:** High
**Story Points:** 5

Your description here...

Extraction ​

When reading from Basecamp, the adapter extracts:

  • Story points from patterns like: Story Points: 5, SP: 5, Points: 5
  • Priority from patterns like: Priority: High

Updating ​

When updating story points or priority:

  • The adapter preserves existing notes/content
  • Removes old priority/story points entries
  • Adds new entries in the standard format

Advanced Features ​

Campfire (Chat) Integration ​

Basecamp includes Campfire for real-time chat. The adapter supports:

python
# Get all Campfires
campfires = adapter.get_campfires()

# Send a message
adapter.send_campfire_message(
    chat_id="chat123",
    content="Story STORY-001 has been completed!"
)

# Get chat history
messages = adapter.get_campfire_messages(
    chat_id="chat123",
    since="2024-01-01T00:00:00Z",
    limit=50
)

Use cases:

  • Automated notifications when stories are synced
  • Status updates for team members
  • Integration with CI/CD pipelines

Webhooks ​

Set up webhooks to receive real-time updates:

python
# Create webhook
webhook = adapter.create_webhook(
    url="https://your-server.com/webhook",
    events=["todo.created", "todo.updated", "message.created"],
    description="Spectra sync webhook"
)

# List webhooks
webhooks = adapter.list_webhooks()

# Delete webhook
adapter.delete_webhook(webhook_id="webhook123")

Supported Events:

  • todo.created, todo.updated, todo.completed, todo.uncompleted
  • message.created, message.updated
  • comment.created, comment.updated
  • todo_list.created, todo_list.updated

Comments ​

Comments are synced bidirectionally:

  • Comments added in Basecamp appear in markdown
  • Comments in markdown are added to Basecamp todos/messages

Rate Limiting ​

Basecamp API has a rate limit of 40 requests per 10 seconds. The adapter:

  • Automatically throttles requests
  • Implements exponential backoff on rate limit errors
  • Respects Retry-After headers

Examples ​

Basic Sync ​

bash
# Dry run (preview changes)
spectryn --markdown EPIC.md --tracker basecamp

# Execute sync
spectryn --markdown EPIC.md --tracker basecamp --execute

With Custom Configuration ​

yaml
# .spectryn.yaml
basecamp:
  access_token: ${BASECAMP_ACCESS_TOKEN}
  account_id: "123456"
  project_id: "789012"
  use_messages_for_stories: false  # Use todos

sync:
  execute: true
  update_source_file: true  # Write tracker info back to markdown

Markdown Example ​

markdown
# Epic: User Authentication

## Stories

### STORY-001: Login Page
**Story Points:** 5
**Priority:** High
**Status:** In Progress

**As a** user
**I want** to log in with email and password
**So that** I can access my account

#### Acceptance Criteria
- [ ] Email and password fields are present
- [ ] Form validation works
- [ ] Error messages display correctly

#### Subtasks
- [ ] Design login form (STORY-001-T1)
- [ ] Implement authentication API (STORY-001-T2)
- [ ] Add error handling (STORY-001-T3)

Troubleshooting ​

Common Issues ​

"Authentication failed" ​

  • Verify your access token is correct
  • Check that the token hasn't expired (OAuth tokens)
  • Ensure the token has the necessary scopes (Read, Write, Admin)
  • Verify the token format (should start with a long string, no special prefix)

"Account not found" ​

  • Verify the account ID is correct (numeric string)
  • Check that you have access to the account
  • Ensure the account ID matches the token's account

"Project not found" ​

  • Verify the project ID is correct (numeric string)
  • Check that the project exists in the specified account
  • Ensure you have access to the project
  • Verify the project ID is from Basecamp 3 (not Basecamp 2)

"Todo list not found" ​

  • Ensure the project has at least one Todo Set
  • Create a Todo Set in Basecamp if none exist
  • Check that you're using the correct project ID

"Cannot create subtask for message" ​

  • Subtasks are only supported for todos, not messages
  • Switch to todo mode: use_messages_for_stories: false
  • Or create the parent as a todo instead of a message

Debug Mode ​

Enable verbose logging:

bash
spectryn --markdown EPIC.md --tracker basecamp --verbose

Or set in config:

yaml
sync:
  verbose: true

Testing Connection ​

Test your configuration:

python
from spectryn.adapters.basecamp import BasecampAdapter

adapter = BasecampAdapter(
    access_token="your-token",
    account_id="123456",
    project_id="789012",
    dry_run=True
)

# Test connection
if adapter.test_connection():
    print("✓ Connection successful")
    user = adapter.get_current_user()
    print(f"✓ Logged in as: {user.get('name')}")
else:
    print("✗ Connection failed")

API Reference ​

Endpoints Used ​

  • GET /people/me.json - Get current user
  • GET /projects/{id}.json - Get project
  • GET /projects/{id}/todosets.json - Get todo lists
  • GET /projects/{id}/todosets/{id}/todos.json - Get todos
  • GET /projects/{id}/todos/{id}.json - Get todo
  • POST /projects/{id}/todosets/{id}/todos.json - Create todo
  • PUT /projects/{id}/todos/{id}.json - Update todo
  • GET /projects/{id}/messages.json - Get messages
  • GET /projects/{id}/messages/{id}.json - Get message
  • POST /projects/{id}/messages.json - Create message
  • GET /projects/{id}/recordings/{id}/comments.json - Get comments
  • POST /projects/{id}/recordings/{id}/comments.json - Create comment
  • GET /projects/{id}/chats.json - Get Campfires
  • POST /projects/{id}/chats/{id}/lines.json - Send Campfire message
  • POST /projects/{id}/webhooks.json - Create webhook

Rate Limits ​

  • 40 requests per 10 seconds per account
  • Adapter automatically throttles to stay under limit
  • Retries with exponential backoff on 429 errors

Best Practices ​

  1. Use Dry Run First: Always test with --execute flag off first
  2. Choose the Right Mode: Decide between Todos and Messages based on your workflow
  3. Backup Your Data: Export your Basecamp project before bulk operations
  4. Incremental Syncs: Sync frequently to avoid large changes
  5. Consistent Naming: Use consistent story point and priority formats in notes
  6. Webhooks: Set up webhooks for real-time sync if needed
  7. Campfire Notifications: Use Campfire for team notifications about syncs

See Also ​

Released under the MIT License.