Feb 6, 2026
Latest updates and announcements
Webhook Subscriptions API & Connection Expiry Events
A new API for managing webhook configurations with event filtering, HMAC signature verification, and support for platform lifecycle events. This replaces the legacy project-level webhook settings with a more flexible, subscription-based model.
Summary
| Change | Type | Action Required |
|---|---|---|
| New Webhook Subscriptions API | New Feature | No |
composio.connected_account.expired event | New Feature | Opt-in |
| Legacy webhook endpoints | Deprecated | Migration recommended |
webhook_url, webhook_secret in Project | Deprecated | Use new API |
API Overview
See the API Reference for complete details.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /api/v3/webhook_subscriptions | Create a subscription |
GET | /api/v3/webhook_subscriptions | List all subscriptions |
GET | /api/v3/webhook_subscriptions/{id} | Get subscription details |
PATCH | /api/v3/webhook_subscriptions/{id} | Update subscription |
DELETE | /api/v3/webhook_subscriptions/{id} | Delete subscription |
POST | /api/v3/webhook_subscriptions/{id}/rotate_secret | Rotate signing secret |
GET | /api/v3/webhook_subscriptions/event_types | List available event types |
Key Capabilities
- Event filtering: Subscribe only to events you need
- HMAC-SHA256 signatures: Every webhook includes a cryptographic signature for verification
- Secret rotation: Rotate signing secrets on demand
Creating a Subscription
curl -X POST "https://backend.composio.dev/api/v3/webhook_subscriptions" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-server.com/webhooks/composio",
"enabled_events": ["composio.trigger.message"],
"version": "V3"
}'Response:
{
"id": "ws_your-subscription-id",
"webhook_url": "https://your-server.com/webhooks/composio",
"version": "V3",
"enabled_events": ["composio.trigger.message"],
"secret": "<your-webhook-secret>",
"created_at": "2026-02-06T12:00:00.000Z",
"updated_at": "2026-02-06T12:00:00.000Z"
}The secret is only returned once at creation time or when rotated. Store it securely for signature verification.
Notes
- 1 subscription per project: Currently limited to one webhook subscription per project. This will be expanded in future releases.
- HTTPS required: Webhook URLs must use HTTPS in production environments.
New Event: composio.connected_account.expired
A new platform event that notifies you when an OAuth2 connected account's authentication expires and cannot be automatically refreshed.
This event is only available in V3 format. We strongly recommend using V3 for all new integrations to access the latest features and follow standard webhook practices.
Use Cases
- Prompt users to re-authenticate before workflows fail
- Track connection health across your user base
- Automate re-connection flows
- Build proactive notification systems
Subscribing to Connection Expiry Events
curl -X POST "https://backend.composio.dev/api/v3/webhook_subscriptions" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-server.com/webhooks/composio",
"enabled_events": [
"composio.trigger.message",
"composio.connected_account.expired"
],
"version": "V3"
}'Payload Structure
The composio.connected_account.expired event follows the V3 envelope format:
{
"id": "evt_847cdfcd-d219-4f18-a6dd-91acd42ca94a",
"timestamp": "2026-02-06T12:00:00.000Z",
"type": "composio.connected_account.expired",
"metadata": {
"project_id": "pr_your-project-id",
"org_id": "ok_your-org-id"
},
"data": {
"toolkit": {
"slug": "gmail"
},
"auth_config": {
"id": "ac_your-auth-config-id",
"auth_scheme": "OAUTH2",
"is_composio_managed": true,
"is_disabled": false
},
"id": "ca_your-connected-account-id",
"status": "EXPIRED",
"created_at": "2025-12-01T10:00:00.000Z",
"updated_at": "2026-02-06T12:00:00.000Z",
"status_reason": "OAuth refresh token expired",
"is_disabled": false
}
}The data object matches the response from GET /api/v3/connected_accounts/{id}, making it easy to process with existing code and SDK types.
Verifying Webhook Signatures
All webhooks include an HMAC signature in the webhook-signature header. Use the SDK's built-in verification functions or see the Triggers documentation for implementation details.
Available Event Types
Query available events and their version compatibility:
curl "https://backend.composio.dev/api/v3/webhook_subscriptions/event_types" \
-H "x-api-key: YOUR_API_KEY"| Event Type | Description | Supported Versions |
|---|---|---|
composio.trigger.message | Trigger events from integrations | V1, V2, V3 |
composio.connected_account.expired | Connection authentication expired | V3 only |
Deprecations
Deprecated Endpoints
The following legacy endpoints are deprecated and will be removed in a future release:
| Deprecated Endpoint | Replacement |
|---|---|
GET /api/v3/org/project/webhook | GET /api/v3/webhook_subscriptions |
POST /api/v3/org/project/webhook/update | POST /api/v3/webhook_subscriptions |
DELETE /api/v3/org/project/webhook | DELETE /api/v3/webhook_subscriptions/{id} |
POST /api/v3/org/project/webhook/refresh | POST /api/v3/webhook_subscriptions/{id}/rotate_secret |
Deprecated Fields in Project Response
| Field | Status | Notes |
|---|---|---|
webhook_url | Deprecated | Use Webhook Subscriptions API |
webhook_secret | Deprecated | Use Webhook Subscriptions API |
event_webhook_url | Deprecated | Never implemented |
is_new_webhook | Deprecated | Use Webhook Subscriptions API |
Backward Compatibility
No immediate action required. Your existing webhook configurations will continue to work.
What We've Done For You
- Automatic migration: We've created a webhook subscription for all existing projects that had webhook URLs configured, with
composio.trigger.messageenabled by default - Same payload format: If you were using V1, V2, or V3 triggers, they continue with the same format
What Continues to Work
- Legacy webhook endpoints (deprecated but functional)
- Existing project webhook configurations
- All existing trigger payload formats (V1, V2, V3)
- Signature verification with your existing secret
Payload Version Comparison
| Version | Format | Recommendation |
|---|---|---|
| V1 | Legacy flat structure | For backward compatibility only |
| V2 | Nested with metadata | For existing integrations |
| V3 | Structured envelope with id, timestamp, type, metadata, data | Recommended for all new integrations |
75+ More Toolkits Get Typed Responses & Consistent Response Schema Wrapping
We've expanded typed response coverage to 75+ additional toolkits. In total, over 130 toolkits now return strongly typed response objects. Additionally, we've standardized response schema wrapping so that all action responses consistently nest their output under a top-level data field.
Breaking Change for latest Version
Two breaking changes ship in this release:
-
Newly typed toolkits — If your code depends on the old
response_datastructure for any of the 75+ newly typed toolkits listed below, you'll need to update your code to work with the new typed response schemas. -
Consistent response wrapping — Actions that previously had
dataat the root level of their response schema now wrap the entire response under adatafield. See the migration guide below.
Consistent Response Schema Wrapping
Previously, actions whose response schema already contained a data field at the root level would surface all fields (including data) alongside successful and error at the top level. Now, all action responses are uniformly wrapped: the full response object is nested inside a data field, with successful and error at the top level.
Affected: Toolkits with data in their response model (e.g., Pipedrive PIPEDRIVE_LIST_UPDATES_ABOUT_A_DEAL)
These actions had a data field in their original response schema. Previously, those fields were spread at the root level alongside successful and error. Now, they are nested under a top-level data field.
Before:
{
"data": { "deal_id": 1, "field_key": "stage_id", "old_value": "1", "new_value": "2" },
"successful": true,
"error": null
}After:
{
"data": {
"data": { "deal_id": 1, "field_key": "stage_id", "old_value": "1", "new_value": "2" }
},
"successful": true,
"error": null
}If your code accesses fields directly at the root level (e.g., result["data"]), update it to access them under result["data"]["data"] instead.
Not affected: Toolkits without data in their response model (e.g., GitHub GITHUB_GET_THE_LATEST_RELEASE)
These actions never had a data field in their original response schema, so their wrapping behavior is unchanged. The response fields are nested under data as before.
{
"data": {
"url": "https://api.github.com/repos/octocat/Hello-World/releases/1",
"tag_name": "v1.0.0",
"name": "v1.0.0",
"draft": false,
"prerelease": false,
"author": { "login": "octocat", "id": 1 }
},
"successful": true,
"error": null
}No migration needed for these toolkits.
75+ Newly Typed Response Toolkits
All outputs for these toolkits now return strongly typed objects with clear field documentation instead of generic response_data blobs. Combined with the 60+ toolkits typed in the previous release, over 130 toolkits now have typed responses.