diff --git a/docs/features/webhook.mdx b/docs/features/webhook.mdx index 5c083117..477025ba 100644 --- a/docs/features/webhook.mdx +++ b/docs/features/webhook.mdx @@ -13,7 +13,7 @@ Webhooks allow you to receive real-time notifications when memory events occur i ### Get Webhooks -Retrieve all webhooks configured for your project. By default, it uses the project_id from your client configuration, but you can optionally specify a different project: +Retrieve all webhooks configured for your project: @@ -22,10 +22,7 @@ from mem0 import MemoryClient client = MemoryClient(api_key="your-api-key") -# Get webhooks for the default project -webhooks = client.get_webhooks() - -# Or specify a different project +# Get webhooks for a specific project webhooks = client.get_webhooks(project_id="proj_123") print(webhooks) ``` @@ -34,10 +31,7 @@ print(webhooks) const { MemoryClient } = require('mem0ai'); const client = new MemoryClient('your-api-key'); -// Get webhooks for the default project -const webhooks = await client.getWebhooks(); - -// Or specify a different project +// Get webhooks for a specific project const webhooks = await client.getWebhooks("proj_123"); console.log(webhooks); ``` @@ -49,6 +43,7 @@ console.log(webhooks); 'url': 'https://mem0.ai', 'name': 'mem0', 'owner': 'john', + 'event_types': ['memory_add'], 'project': 'default-project', 'is_active': True, 'created_at': '2025-02-18T22:59:56.804993-08:00', @@ -67,33 +62,23 @@ Create a new webhook for your project. The webhook will only receive events from ```python Python -# Create a webhook in the default project -webhook = client.create_webhook( - url="https://your-app.com/webhook", - name="Memory Logger" -) - -# Or create in a specific project +# Create webhook in a specific project webhook = client.create_webhook( url="https://your-app.com/webhook", name="Memory Logger", project_id="proj_123" + event_types=["memory:add"] ) print(webhook) ``` ```javascript JavaScript -// Create a webhook in the default project -const webhook = await client.createWebhook({ - url: "https://your-app.com/webhook", - name: "Memory Logger" -}); - -// Or create in a specific project +// Create webhook in a specific project const webhook = await client.createWebhook({ url: "https://your-app.com/webhook", name: "Memory Logger", - projectId: "proj_123" + projectId: "proj_123", + eventTypes: ["memory:add"] }); console.log(webhook); ``` @@ -103,6 +88,7 @@ console.log(webhook); 'webhook_id': "wh_123", 'name': 'Memory Logger', 'url': 'https://your-app.com/webhook', + 'event_types': ['memory_add'], 'project': 'default-project', 'is_active': True, 'created_at': '2025-02-18T22:59:56.804993-08:00', @@ -119,28 +105,18 @@ Modify an existing webhook's configuration. Remember that webhooks can only be u ```python Python -# Update webhook in default project -updated_webhook = client.update_webhook( - name="Updated Logger", - url="https://your-app.com/new-webhook" -) - -# Or update in a specific project +# Update webhook for a specific project updated_webhook = client.update_webhook( name="Updated Logger", url="https://your-app.com/new-webhook" + project_id="proj_123", + webhook_id="wh_123" ) print(updated_webhook) ``` ```javascript JavaScript -// Update webhook in default project -const updatedWebhook = await client.updateWebhook("wh_123", { - name: "Updated Logger", - url: "https://your-app.com/new-webhook" -}); - -// Or update in a specific project +// Update webhook for a specific project const updatedWebhook = await client.updateWebhook("wh_123", { name: "Updated Logger", url: "https://your-app.com/new-webhook", @@ -164,19 +140,13 @@ Remove a webhook configuration from a project: ```python Python -# Delete webhook from default project -response = client.delete_webhook(webhook_id="wh_123") - -# Or delete from a specific project +# Delete webhook from a specific project response = client.delete_webhook(webhook_id="wh_123", project_id="proj_123") print(response) ``` ```javascript JavaScript -// Delete webhook from default project -const response = await client.deleteWebhook("wh_123"); - -// Or delete from a specific project +// Delete webhook from a specific project const response = await client.deleteWebhook("wh_123", "proj_123"); console.log(response); ``` @@ -189,6 +159,14 @@ console.log(response); +## Event Types + +Mem0 supports the following event types for webhooks: + +- `memory:add`: Triggered when a new memory is added. +- `memory:update`: Triggered when an existing memory is updated. +- `memory:delete`: Triggered when a memory is deleted. + ## Webhook Payload When a memory event occurs in your project, Mem0 sends a POST request to your webhook URL with the following payload structure: diff --git a/mem0/client/main.py b/mem0/client/main.py index 312e58e2..f67f6f5b 100644 --- a/mem0/client/main.py +++ b/mem0/client/main.py @@ -525,7 +525,7 @@ class MemoryClient: raise NotImplementedError("Chat is not implemented yet") @api_error_handler - def get_webhooks(self, project_id: Optional[str] = None) -> Dict[str, Any]: + def get_webhooks(self, project_id: str) -> Dict[str, Any]: """Get webhooks configuration for the project. Args: @@ -539,23 +539,19 @@ class MemoryClient: ValueError: If project_id is not set. """ - project_id = project_id or self.project_id - - if not project_id: - raise ValueError("project_id must be set to access webhooks") - response = self.client.get(f"api/v1/webhooks/{project_id}/webhook/") response.raise_for_status() capture_client_event("client.get_webhook", self) return response.json() @api_error_handler - def create_webhook(self, url: str, name: str, project_id: Optional[str] = None) -> Dict[str, Any]: + def create_webhook(self, url: str, name: str, project_id: str, event_types: List[str]) -> Dict[str, Any]: """Create a webhook for the current project. Args: url: The URL to send the webhook to. name: The name of the webhook. + event_types: List of event types to trigger the webhook for. Returns: Dictionary containing the created webhook details. @@ -564,12 +560,8 @@ class MemoryClient: APIError: If the API request fails. ValueError: If project_id is not set. """ - project_id = project_id or self.project_id - if not project_id: - raise ValueError("project_id must be set to create webhook") - - payload = {"url": url, "name": name} + payload = {"url": url, "name": name, "event_types": event_types} response = self.client.post(f"api/v1/webhooks/{project_id}/webhook/", json=payload) response.raise_for_status() capture_client_event("client.create_webhook", self) @@ -577,15 +569,16 @@ class MemoryClient: @api_error_handler def update_webhook( - self, webhook_id: int, name: Optional[str] = None, url: Optional[str] = None, project_id: Optional[str] = None + self, webhook_id: int, project_id: str, name: Optional[str] = None, url: Optional[str] = None, event_types: Optional[List[str]] = None ) -> Dict[str, Any]: """Update a webhook configuration. Args: webhook_id: ID of the webhook to update + project_id: The ID of the project to update the webhook for. name: Optional new name for the webhook url: Optional new URL for the webhook - project_id: The ID of the project to update the webhook for. + event_types: Optional list of event types to trigger the webhook for. Returns: Dictionary containing the updated webhook details. @@ -594,19 +587,15 @@ class MemoryClient: APIError: If the API request fails. ValueError: If project_id is not set. """ - project_id = project_id or self.project_id - if not project_id: - raise ValueError("project_id must be set to update webhook") - - payload = {k: v for k, v in {"name": name, "url": url}.items() if v is not None} + payload = {k: v for k, v in {"name": name, "url": url, "event_types": event_types}.items() if v is not None} response = self.client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload) response.raise_for_status() capture_client_event("client.update_webhook", self, {"webhook_id": webhook_id}) return response.json() @api_error_handler - def delete_webhook(self, webhook_id: int, project_id: Optional[str] = None) -> Dict[str, str]: + def delete_webhook(self, webhook_id: int, project_id: str) -> Dict[str, str]: """Delete a webhook configuration. Args: @@ -620,10 +609,6 @@ class MemoryClient: APIError: If the API request fails. ValueError: If project_id is not set. """ - project_id = project_id or self.project_id - - if not project_id: - raise ValueError("project_id must be set to delete webhook") response = self.client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/") response.raise_for_status() @@ -975,11 +960,7 @@ class AsyncMemoryClient: raise NotImplementedError("Chat is not implemented yet") @api_error_handler - async def get_webhooks(self, project_id: Optional[str] = None) -> Dict[str, Any]: - project_id = project_id or self.sync_client.project_id - - if not project_id: - raise ValueError("project_id must be set to access webhooks") + async def get_webhooks(self, project_id: str) -> Dict[str, Any]: response = await self.async_client.get( f"api/v1/webhooks/{project_id}/webhook/", @@ -989,14 +970,11 @@ class AsyncMemoryClient: return response.json() @api_error_handler - async def create_webhook(self, url: str, name: str, project_id: Optional[str] = None) -> Dict[str, Any]: - project_id = project_id or self.sync_client.project_id - - if not project_id: - raise ValueError("project_id must be set to create webhook") + async def create_webhook(self, url: str, name: str, project_id: str, event_types: List[str]) -> Dict[str, Any]: + payload = {"url": url, "name": name, "event_types": event_types} response = await self.async_client.post( - f"api/v1/webhooks/{project_id}/webhook/", json={"url": url, "name": name} + f"api/v1/webhooks/{project_id}/webhook/", json=payload ) response.raise_for_status() capture_client_event("async_client.create_webhook", self.sync_client) @@ -1004,25 +982,17 @@ class AsyncMemoryClient: @api_error_handler async def update_webhook( - self, webhook_id: int, name: Optional[str] = None, url: Optional[str] = None, project_id: Optional[str] = None + self, webhook_id: int,project_id: str, name: Optional[str] = None, url: Optional[str] = None, event_types: Optional[List[str]] = None ) -> Dict[str, Any]: - project_id = project_id or self.sync_client.project_id - if not project_id: - raise ValueError("project_id must be set to update webhook") - - payload = {k: v for k, v in {"name": name, "url": url}.items() if v is not None} + payload = {k: v for k, v in {"name": name, "url": url, "event_types": event_types}.items() if v is not None} response = await self.async_client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload) response.raise_for_status() capture_client_event("async_client.update_webhook", self.sync_client, {"webhook_id": webhook_id}) return response.json() @api_error_handler - async def delete_webhook(self, webhook_id: int, project_id: Optional[str] = None) -> Dict[str, str]: - project_id = project_id or self.sync_client.project_id - - if not project_id: - raise ValueError("project_id must be set to delete webhook") + async def delete_webhook(self, webhook_id: int, project_id: str) -> Dict[str, str]: response = await self.async_client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/") response.raise_for_status()