Basecamp · Schema

Basecamp Webhook Payload

Represents the JSON payload delivered by Basecamp to a registered webhook endpoint when a subscribed event occurs within a project. Every payload includes a unique event ID, the event kind, a timestamp, the full recording object that triggered the event, the person who triggered it, and optional event-specific details.

CollaborationProject ManagementRESTSaaSTeam Communication

Properties

Name Type Description
id integer Unique identifier for this webhook event delivery
kind string Event type descriptor identifying the resource type and action, formatted as {resource}_{action} (e.g., message_created, todo_completed, comment_updated)
created_at string ISO 8601 UTC timestamp when the triggering event occurred in Basecamp
recording object Full JSON representation of the Basecamp resource that triggered the event
creator object The Basecamp user whose action triggered the event
details object Event-specific contextual metadata. For copy and move events includes a copy object with the duplicated item reference. Contents vary by event kind.
View JSON Schema on GitHub

JSON Schema

basecamp-webhook-payload-schema.json Raw ↑
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/basecamp/bc3-api/schemas/basecamp/webhook-payload.json",
  "title": "Basecamp Webhook Payload",
  "description": "Represents the JSON payload delivered by Basecamp to a registered webhook endpoint when a subscribed event occurs within a project. Every payload includes a unique event ID, the event kind, a timestamp, the full recording object that triggered the event, the person who triggered it, and optional event-specific details.",
  "type": "object",
  "required": ["id", "kind", "created_at", "recording", "creator"],
  "properties": {
    "id": {
      "type": "integer",
      "description": "Unique identifier for this webhook event delivery"
    },
    "kind": {
      "type": "string",
      "description": "Event type descriptor identifying the resource type and action, formatted as {resource}_{action} (e.g., message_created, todo_completed, comment_updated)",
      "enum": [
        "message_created",
        "message_updated",
        "message_archived",
        "message_trashed",
        "message_subscribers_changed",
        "message_publicized",
        "todo_created",
        "todo_updated",
        "todo_completed",
        "todo_uncompleted",
        "todo_archived",
        "todo_trashed",
        "todo_subscribers_changed",
        "todolist_created",
        "todolist_updated",
        "todolist_archived",
        "todolist_trashed",
        "document_created",
        "document_updated",
        "document_archived",
        "document_trashed",
        "comment_created",
        "comment_updated",
        "comment_trashed",
        "card_created",
        "card_updated",
        "card_archived",
        "card_trashed",
        "schedule_entry_created",
        "schedule_entry_updated",
        "schedule_entry_archived",
        "schedule_entry_trashed",
        "upload_created",
        "upload_updated",
        "upload_archived",
        "upload_trashed",
        "question_answer_created",
        "question_answer_updated",
        "question_paused",
        "question_resumed",
        "inbox_forward_created",
        "client_forward_created",
        "client_correspondence_created"
      ]
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "description": "ISO 8601 UTC timestamp when the triggering event occurred in Basecamp"
    },
    "recording": {
      "$ref": "#/$defs/Recording",
      "description": "Full JSON representation of the Basecamp resource that triggered the event"
    },
    "creator": {
      "$ref": "#/$defs/Person",
      "description": "The Basecamp user whose action triggered the event"
    },
    "details": {
      "type": "object",
      "description": "Event-specific contextual metadata. For copy and move events includes a copy object with the duplicated item reference. Contents vary by event kind.",
      "additionalProperties": true,
      "properties": {
        "copy": {
          "$ref": "#/$defs/Recording",
          "description": "Reference to the original recording when this event was triggered by a copy or move operation"
        }
      }
    }
  },
  "$defs": {
    "Person": {
      "type": "object",
      "description": "A Basecamp user profile reference included in webhook payloads",
      "required": ["id", "name"],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for the person"
        },
        "attachable_sgid": {
          "type": "string",
          "description": "Signed global ID used to reference this person as an attachment"
        },
        "name": {
          "type": "string",
          "description": "Full display name of the person"
        },
        "email_address": {
          "type": "string",
          "format": "email",
          "description": "Primary email address of the person"
        },
        "personable_type": {
          "type": "string",
          "description": "Personable type indicating user role",
          "enum": ["User", "Client"]
        },
        "title": {
          "type": "string",
          "description": "Job title of the person"
        },
        "bio": {
          "type": "string",
          "description": "Short biography text"
        },
        "location": {
          "type": "string",
          "description": "Location string"
        },
        "avatar_url": {
          "type": "string",
          "format": "uri",
          "description": "URL to the person's avatar image"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp when the person's account was created"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp when the person's profile was last updated"
        },
        "admin": {
          "type": "boolean",
          "description": "Whether the person is an account administrator"
        },
        "owner": {
          "type": "boolean",
          "description": "Whether the person is the account owner"
        },
        "client": {
          "type": "boolean",
          "description": "Whether the person is a client user"
        },
        "employee": {
          "type": "boolean",
          "description": "Whether the person is an internal employee"
        },
        "time_zone": {
          "type": "string",
          "description": "IANA time zone name for the person's local time zone"
        }
      }
    },
    "Bucket": {
      "type": "object",
      "description": "Reference to the Basecamp project containing the recording",
      "required": ["id", "name", "type"],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Project ID"
        },
        "name": {
          "type": "string",
          "description": "Project name"
        },
        "type": {
          "type": "string",
          "description": "Always 'Project' for project buckets",
          "const": "Project"
        }
      }
    },
    "Recording": {
      "type": "object",
      "description": "A Basecamp content resource such as a message, to-do, document, comment, or card. The exact fields present depend on the resource type indicated by the type field.",
      "required": ["id", "type"],
      "properties": {
        "id": {
          "type": "integer",
          "description": "Unique identifier for this recording"
        },
        "status": {
          "type": "string",
          "description": "Lifecycle status of the recording",
          "enum": ["active", "archived", "trashed"]
        },
        "visible_to_clients": {
          "type": "boolean",
          "description": "Whether the recording is visible to client users"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp when the recording was created"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp when the recording was last updated"
        },
        "title": {
          "type": "string",
          "description": "Title or summary of the recording"
        },
        "inherits_status": {
          "type": "boolean",
          "description": "Whether this recording inherits its status from a parent recording"
        },
        "type": {
          "type": "string",
          "description": "Recording type identifying the kind of Basecamp content",
          "enum": [
            "Message",
            "Todo",
            "Todolist",
            "Document",
            "Comment",
            "Kanban::Card",
            "Schedule::Entry",
            "Upload",
            "Vault",
            "Question::Answer",
            "Client::Forward",
            "Client::Correspondence",
            "Inbox::Forward"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "API URL to retrieve this recording"
        },
        "app_url": {
          "type": "string",
          "format": "uri",
          "description": "Web URL to open this recording in the Basecamp application"
        },
        "bookmark_url": {
          "type": "string",
          "format": "uri",
          "description": "API URL to bookmark this recording"
        },
        "bucket": {
          "$ref": "#/$defs/Bucket"
        },
        "creator": {
          "$ref": "#/$defs/Person"
        },
        "content": {
          "type": "string",
          "description": "HTML-formatted body content for messages, documents, and comments"
        },
        "subject": {
          "type": "string",
          "description": "Subject line for message recordings"
        },
        "completed": {
          "type": "boolean",
          "description": "Whether the to-do has been completed (Todo type only)"
        },
        "due_on": {
          "type": ["string", "null"],
          "format": "date",
          "description": "Due date in ISO 8601 date format (Todo type only)"
        },
        "starts_on": {
          "type": ["string", "null"],
          "format": "date",
          "description": "Start date in ISO 8601 date format (Todo type only)"
        },
        "assignees": {
          "type": "array",
          "description": "People assigned to this to-do (Todo type only)",
          "items": {
            "$ref": "#/$defs/Person"
          }
        },
        "starts_at": {
          "type": "string",
          "format": "date-time",
          "description": "Start time for schedule entries (Schedule::Entry type only)"
        },
        "ends_at": {
          "type": "string",
          "format": "date-time",
          "description": "End time for schedule entries (Schedule::Entry type only)"
        },
        "all_day": {
          "type": "boolean",
          "description": "Whether the schedule entry spans the entire day (Schedule::Entry type only)"
        },
        "filename": {
          "type": "string",
          "description": "Original filename of the uploaded file (Upload type only)"
        },
        "content_type": {
          "type": "string",
          "description": "MIME type of the uploaded file (Upload type only)"
        },
        "byte_size": {
          "type": "integer",
          "description": "File size in bytes (Upload type only)"
        },
        "download_url": {
          "type": "string",
          "format": "uri",
          "description": "Direct download URL for the uploaded file (Upload type only)"
        },
        "comments_count": {
          "type": "integer",
          "description": "Number of comments on this recording"
        },
        "boosts_count": {
          "type": "integer",
          "description": "Number of boosts (reactions) on this recording"
        },
        "position": {
          "type": "integer",
          "description": "Display order position within the parent container"
        },
        "parent": {
          "$ref": "#/$defs/Recording",
          "description": "Reference to the parent recording (e.g., the message board containing a message, or the to-do list containing a to-do)"
        }
      }
    }
  }
}