Project_id mandatory for Webhooks (#2232)

Co-authored-by: Deshraj Yadav <deshrajdry@gmail.com>
This commit is contained in:
Dev Khant
2025-02-20 23:57:29 +05:30
committed by GitHub
parent 9734b2db7e
commit acaf47ed54
2 changed files with 40 additions and 92 deletions

View File

@@ -13,7 +13,7 @@ Webhooks allow you to receive real-time notifications when memory events occur i
### Get Webhooks ### 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:
<CodeGroup> <CodeGroup>
@@ -22,10 +22,7 @@ from mem0 import MemoryClient
client = MemoryClient(api_key="your-api-key") client = MemoryClient(api_key="your-api-key")
# Get webhooks for the default project # Get webhooks for a specific project
webhooks = client.get_webhooks()
# Or specify a different project
webhooks = client.get_webhooks(project_id="proj_123") webhooks = client.get_webhooks(project_id="proj_123")
print(webhooks) print(webhooks)
``` ```
@@ -34,10 +31,7 @@ print(webhooks)
const { MemoryClient } = require('mem0ai'); const { MemoryClient } = require('mem0ai');
const client = new MemoryClient('your-api-key'); const client = new MemoryClient('your-api-key');
// Get webhooks for the default project // Get webhooks for a specific project
const webhooks = await client.getWebhooks();
// Or specify a different project
const webhooks = await client.getWebhooks("proj_123"); const webhooks = await client.getWebhooks("proj_123");
console.log(webhooks); console.log(webhooks);
``` ```
@@ -49,6 +43,7 @@ console.log(webhooks);
'url': 'https://mem0.ai', 'url': 'https://mem0.ai',
'name': 'mem0', 'name': 'mem0',
'owner': 'john', 'owner': 'john',
'event_types': ['memory_add'],
'project': 'default-project', 'project': 'default-project',
'is_active': True, 'is_active': True,
'created_at': '2025-02-18T22:59:56.804993-08:00', '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
<CodeGroup> <CodeGroup>
```python Python ```python Python
# Create a webhook in the default project # Create webhook in a specific project
webhook = client.create_webhook(
url="https://your-app.com/webhook",
name="Memory Logger"
)
# Or create in a specific project
webhook = client.create_webhook( webhook = client.create_webhook(
url="https://your-app.com/webhook", url="https://your-app.com/webhook",
name="Memory Logger", name="Memory Logger",
project_id="proj_123" project_id="proj_123"
event_types=["memory:add"]
) )
print(webhook) print(webhook)
``` ```
```javascript JavaScript ```javascript JavaScript
// Create a webhook in the default project // Create webhook in a specific project
const webhook = await client.createWebhook({
url: "https://your-app.com/webhook",
name: "Memory Logger"
});
// Or create in a specific project
const webhook = await client.createWebhook({ const webhook = await client.createWebhook({
url: "https://your-app.com/webhook", url: "https://your-app.com/webhook",
name: "Memory Logger", name: "Memory Logger",
projectId: "proj_123" projectId: "proj_123",
eventTypes: ["memory:add"]
}); });
console.log(webhook); console.log(webhook);
``` ```
@@ -103,6 +88,7 @@ console.log(webhook);
'webhook_id': "wh_123", 'webhook_id': "wh_123",
'name': 'Memory Logger', 'name': 'Memory Logger',
'url': 'https://your-app.com/webhook', 'url': 'https://your-app.com/webhook',
'event_types': ['memory_add'],
'project': 'default-project', 'project': 'default-project',
'is_active': True, 'is_active': True,
'created_at': '2025-02-18T22:59:56.804993-08:00', '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
<CodeGroup> <CodeGroup>
```python Python ```python Python
# Update webhook in default project # Update webhook for a specific project
updated_webhook = client.update_webhook(
name="Updated Logger",
url="https://your-app.com/new-webhook"
)
# Or update in a specific project
updated_webhook = client.update_webhook( updated_webhook = client.update_webhook(
name="Updated Logger", name="Updated Logger",
url="https://your-app.com/new-webhook" url="https://your-app.com/new-webhook"
project_id="proj_123",
webhook_id="wh_123"
) )
print(updated_webhook) print(updated_webhook)
``` ```
```javascript JavaScript ```javascript JavaScript
// Update webhook in default project // Update webhook for a specific project
const updatedWebhook = await client.updateWebhook("wh_123", {
name: "Updated Logger",
url: "https://your-app.com/new-webhook"
});
// Or update in a specific project
const updatedWebhook = await client.updateWebhook("wh_123", { const updatedWebhook = await client.updateWebhook("wh_123", {
name: "Updated Logger", name: "Updated Logger",
url: "https://your-app.com/new-webhook", url: "https://your-app.com/new-webhook",
@@ -164,19 +140,13 @@ Remove a webhook configuration from a project:
<CodeGroup> <CodeGroup>
```python Python ```python Python
# Delete webhook from default project # Delete webhook from a specific project
response = client.delete_webhook(webhook_id="wh_123")
# Or delete from a specific project
response = client.delete_webhook(webhook_id="wh_123", project_id="proj_123") response = client.delete_webhook(webhook_id="wh_123", project_id="proj_123")
print(response) print(response)
``` ```
```javascript JavaScript ```javascript JavaScript
// Delete webhook from default project // Delete webhook from a specific project
const response = await client.deleteWebhook("wh_123");
// Or delete from a specific project
const response = await client.deleteWebhook("wh_123", "proj_123"); const response = await client.deleteWebhook("wh_123", "proj_123");
console.log(response); console.log(response);
``` ```
@@ -189,6 +159,14 @@ console.log(response);
</CodeGroup> </CodeGroup>
## 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 ## Webhook Payload
When a memory event occurs in your project, Mem0 sends a POST request to your webhook URL with the following payload structure: When a memory event occurs in your project, Mem0 sends a POST request to your webhook URL with the following payload structure:

View File

@@ -525,7 +525,7 @@ class MemoryClient:
raise NotImplementedError("Chat is not implemented yet") raise NotImplementedError("Chat is not implemented yet")
@api_error_handler @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. """Get webhooks configuration for the project.
Args: Args:
@@ -539,23 +539,19 @@ class MemoryClient:
ValueError: If project_id is not set. 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 = self.client.get(f"api/v1/webhooks/{project_id}/webhook/")
response.raise_for_status() response.raise_for_status()
capture_client_event("client.get_webhook", self) capture_client_event("client.get_webhook", self)
return response.json() return response.json()
@api_error_handler @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. """Create a webhook for the current project.
Args: Args:
url: The URL to send the webhook to. url: The URL to send the webhook to.
name: The name of the webhook. name: The name of the webhook.
event_types: List of event types to trigger the webhook for.
Returns: Returns:
Dictionary containing the created webhook details. Dictionary containing the created webhook details.
@@ -564,12 +560,8 @@ class MemoryClient:
APIError: If the API request fails. APIError: If the API request fails.
ValueError: If project_id is not set. ValueError: If project_id is not set.
""" """
project_id = project_id or self.project_id
if not project_id: payload = {"url": url, "name": name, "event_types": event_types}
raise ValueError("project_id must be set to create webhook")
payload = {"url": url, "name": name}
response = self.client.post(f"api/v1/webhooks/{project_id}/webhook/", json=payload) response = self.client.post(f"api/v1/webhooks/{project_id}/webhook/", json=payload)
response.raise_for_status() response.raise_for_status()
capture_client_event("client.create_webhook", self) capture_client_event("client.create_webhook", self)
@@ -577,15 +569,16 @@ class MemoryClient:
@api_error_handler @api_error_handler
def update_webhook( 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]: ) -> Dict[str, Any]:
"""Update a webhook configuration. """Update a webhook configuration.
Args: Args:
webhook_id: ID of the webhook to update 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 name: Optional new name for the webhook
url: Optional new URL 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: Returns:
Dictionary containing the updated webhook details. Dictionary containing the updated webhook details.
@@ -594,19 +587,15 @@ class MemoryClient:
APIError: If the API request fails. APIError: If the API request fails.
ValueError: If project_id is not set. ValueError: If project_id is not set.
""" """
project_id = project_id or self.project_id
if not project_id: payload = {k: v for k, v in {"name": name, "url": url, "event_types": event_types}.items() if v is not None}
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}
response = self.client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload) response = self.client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload)
response.raise_for_status() response.raise_for_status()
capture_client_event("client.update_webhook", self, {"webhook_id": webhook_id}) capture_client_event("client.update_webhook", self, {"webhook_id": webhook_id})
return response.json() return response.json()
@api_error_handler @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. """Delete a webhook configuration.
Args: Args:
@@ -620,10 +609,6 @@ class MemoryClient:
APIError: If the API request fails. APIError: If the API request fails.
ValueError: If project_id is not set. 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 = self.client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/")
response.raise_for_status() response.raise_for_status()
@@ -975,11 +960,7 @@ class AsyncMemoryClient:
raise NotImplementedError("Chat is not implemented yet") raise NotImplementedError("Chat is not implemented yet")
@api_error_handler @api_error_handler
async def get_webhooks(self, project_id: Optional[str] = None) -> Dict[str, Any]: async def get_webhooks(self, project_id: str) -> 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")
response = await self.async_client.get( response = await self.async_client.get(
f"api/v1/webhooks/{project_id}/webhook/", f"api/v1/webhooks/{project_id}/webhook/",
@@ -989,14 +970,11 @@ class AsyncMemoryClient:
return response.json() return response.json()
@api_error_handler @api_error_handler
async def create_webhook(self, url: str, name: str, project_id: Optional[str] = None) -> Dict[str, Any]: async def create_webhook(self, url: str, name: str, project_id: str, event_types: List[str]) -> 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")
payload = {"url": url, "name": name, "event_types": event_types}
response = await self.async_client.post( 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() response.raise_for_status()
capture_client_event("async_client.create_webhook", self.sync_client) capture_client_event("async_client.create_webhook", self.sync_client)
@@ -1004,25 +982,17 @@ class AsyncMemoryClient:
@api_error_handler @api_error_handler
async def update_webhook( 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]: ) -> Dict[str, Any]:
project_id = project_id or self.sync_client.project_id
if not project_id: payload = {k: v for k, v in {"name": name, "url": url, "event_types": event_types}.items() if v is not None}
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}
response = await self.async_client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload) response = await self.async_client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload)
response.raise_for_status() response.raise_for_status()
capture_client_event("async_client.update_webhook", self.sync_client, {"webhook_id": webhook_id}) capture_client_event("async_client.update_webhook", self.sync_client, {"webhook_id": webhook_id})
return response.json() return response.json()
@api_error_handler @api_error_handler
async def delete_webhook(self, webhook_id: int, project_id: Optional[str] = None) -> Dict[str, str]: async def delete_webhook(self, webhook_id: int, project_id: str) -> 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")
response = await self.async_client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/") response = await self.async_client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/")
response.raise_for_status() response.raise_for_status()