Dec 30, 2025
Latest updates and announcements
Binary Data Support for Proxy Execute
The /api/v3/tools/execute/proxy endpoint now supports binary data for both file uploads and downloads.
File Uploads (binary_body)
To upload a file via the proxy, use the binary_body field in your request payload. This supports two approaches: specifying either a URL pointing to the file or providing the base64-encoded content directly.
Upload File via URL
curl --location 'https://backend.composio.dev/api/v3/tools/execute/proxy' \
--header 'accept: application/json' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"endpoint": "/upload-endpoint",
"method": "POST",
"connected_account_id": "<CONNECTED_ACCOUNT_ID>",
"binary_body": {
"url": "{URL_TO_THE_FILE}"
}
}'Upload File via Base64 Content
Supported up to 4MB file size.
curl --location 'https://backend.composio.dev/api/v3/tools/execute/proxy' \
--header 'accept: application/json' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"endpoint": "/upload-endpoint",
"method": "POST",
"connected_account_id": "<CONNECTED_ACCOUNT_ID>",
"binary_body": {
"base64": "JVBERi0xLjQKJ...<base64_data>...",
"content_type": "application/pdf"
}
}'File Downloads (binary_data)
When the proxied request returns a binary response (for example, a PDF or image), the proxy automatically uploads the file to temporary storage, and you receive a signed URL in the binary_data field. This enables you to download large files securely.
File Download Request
curl --location 'https://backend.composio.dev/api/v3/tools/execute/proxy' \
--header 'accept: application/json' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"endpoint": "{YOUR_ENDPOINT}",
"method": "GET",
"connected_account_id": "{YOUR_CONNECTED_ACCOUNT_ID}"
}'File Download Response
{
"data": {},
"binary_data": {
"url": "url to the file",
"content_type": "content type of the file",
"size": "size of the file",
"expires_at": "expires at of the file"
},
"status": "status code of the response",
"headers": "headers of the response"
}Summary
| Feature | Field | Description |
|---|---|---|
| File Upload via URL | binary_body.url | Provide a URL pointing to the file to upload |
| File Upload via Base64 | binary_body.base64 + binary_body.content_type | Provide base64-encoded content (up to 4MB) |
| File Download | binary_data in response | Receive a signed URL to download binary responses |
We'd love your feedback on the new proxy execute capabilities. If anything feels unclear or you have suggestions for improvement, please reach out.
Webhook Payload V3 - Lookahead Announcement
We're introducing Webhook Payload V3 - a redesigned webhook structure that follows industry standards and provides better developer experience. This update affects how you receive trigger events via webhooks and Pusher.
What's Changing?
New Webhook Structure
We're adopting the Standard Webhooks specification for better consistency and reliability.
Headers
A new header will identify the webhook version:
x-composio-webhook-version: V3Payload Structure
The payload structure is being reorganized to separate Composio metadata from trigger data:
Before (V2):
{
"log_id": "log_TpxVOLXYnwXZ",
"timestamp": "2025-12-23T13:06:07.695Z",
"type": "gmail_new_gmail_message",
"data": {
"connection_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"connection_nano_id": "ca_xYz9AbCdEfGh",
"trigger_nano_id": "ti_JZFoTyYKbzhB",
"trigger_id": "7f8e9d0c-1b2a-3c4d-5e6f-7a8b9c0d1e2f",
"user_id": "usr-demo-12a3b4c5...",
// ... actual trigger data mixed with metadata
}
}After (V3):
{
"id": "msg_a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"timestamp": "2025-12-23T13:06:07.695Z",
"type": "composio.trigger.message",
"metadata": {
"log_id": "log_TpxVOLXYnwXZ",
"trigger_slug": "GMAIL_NEW_GMAIL_MESSAGE",
"auth_config_id": "ac_aCYTppZ5RsRc",
"connected_account_id": "ca_cATYssZ5RrSc",
"trigger_id": "ti_JZFoTyYKbzhB",
"user_id": "pg-test-86c9fc84..."
},
"data": {
// Clean trigger data without Composio metadata
}
}Key Improvements
- Metadata Separation: Composio-specific fields (connection IDs, trigger IDs, user IDs) are now in a dedicated
metadataobject - Clean Data: The
datafield now contains only the actual trigger payload without infrastructure metadata - Standardized Type Field: The
typefield now follows a consistent format (composio.trigger.message) instead of trigger-specific names likegmail_new_gmail_message - Trigger Slug in Metadata: The trigger slug (e.g.,
GMAIL_NEW_GMAIL_MESSAGE) is now available inmetadata.trigger_slugfor easy identification - Standards Compliance: Follows Standard Webhooks specification for better interoperability
- Consistent Structure: Same payload structure for both webhooks and Pusher channels
Migration Guide
Updating Your Webhook Handlers
If you're accessing Composio metadata fields, update your code:
# Before (V2)
trigger_type = payload["type"] # "gmail_new_gmail_message"
connection_id = payload["data"]["connection_id"]
trigger_id = payload["data"]["trigger_id"]
message_text = payload["data"]["message_text"]
# After (V3)
trigger_type = payload["type"] # "composio.trigger.message"
trigger_slug = payload["metadata"]["trigger_slug"] # "GMAIL_NEW_GMAIL_MESSAGE"
connection_id = payload["metadata"]["connected_account_id"]
trigger_id = payload["metadata"]["trigger_id"]
message_text = payload["data"]["message_text"]// Before (V2)
const triggerSlug = payload.type; // "gmail_new_gmail_message"
const connectionId = payload.data.connection_id;
const triggerId = payload.data.trigger_id;
const messageText = payload.data.message_text;
// After (V3)
const webhookType = payload.type; // "composio.trigger.message"
const triggerSlug = payload.metadata.trigger_slug; // "GMAIL_NEW_GMAIL_MESSAGE"
const connectionId = payload.metadata.connected_account_id;
const triggerId = payload.metadata.trigger_id;
const messageText = payload.data.message_text;Checking Webhook Version
You can detect the webhook version from headers:
webhook_version = headers.get("x-composio-webhook-version", "V2")
if webhook_version == "V3":
# Use new structure
metadata = payload["metadata"]
else:
# Use old structure
metadata = payload["data"]Rollout Timeline
- December 2025: V3 released, opt-in via project settings
- February 15, 2026: All new organizations will default to V3
- Existing organizations: Continue using V2 by default, can opt-in to V3 anytime
How to Opt-In
- Go to your project settings in the Composio dashboard
- Navigate to the Webhooks section
- Select "Webhook Payload Version: V3"
- Update your webhook handlers to use the new structure
- Test thoroughly before enabling in production
Organizations created before February 15, 2026 will remain on V2 by default. You can switch to V3 at your convenience.
Organizations created on or after February 15, 2026 will use V3 by default.
Benefits
- Better DX: Clear separation between metadata and actual trigger data
- Standards Compliance: Follows industry-standard webhook specifications
- Consistency: Same structure across webhooks and Pusher channels
- Future-Proof: Built on established standards for long-term compatibility
Need Help?
If you have questions about migrating to V3 or need assistance:
- Join our Discord community
- Check our documentation
- Contact support at support@composio.dev