{"record":{"id":"65feb0086718bc8f","repo":"mem0ai/mem0","slug":"projectid-must-be-set-to-create-a-webhook","errorCode":null,"errorMessage":"projectId must be set to create a webhook","messagePattern":"projectId must be set to create a webhook","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/client/mem0.ts","lineNumber":692,"sourceCode":"    if (!data?.projectId) await this._awaitIdentity();\n    const project_id = data?.projectId || this.projectId;\n    if (!project_id) {\n      throw new Error(\"projectId must be set to access webhooks\");\n    }\n    const response = await this._fetchWithErrorHandling(\n      `${this.host}/api/v1/webhooks/projects/${project_id}/`,\n      {\n        headers: this.headers,\n      },\n    );\n    return response;\n  }\n\n  async createWebhook(webhook: WebhookCreatePayload): Promise<Webhook> {\n    this._captureEvent(\"create_webhook\", []);\n    await this._awaitIdentity();\n    if (!this.projectId) {\n      throw new Error(\"projectId must be set to create a webhook\");\n    }\n    const body = {\n      name: webhook.name,\n      url: webhook.url,\n      event_types: webhook.eventTypes,\n    };\n    const response = await this._fetchWithErrorHandling(\n      `${this.host}/api/v1/webhooks/projects/${this.projectId}/`,\n      {\n        method: \"POST\",\n        headers: this.headers,\n        body: JSON.stringify(body),\n      },\n    );\n    return response;\n  }\n\n  async updateWebhook(","sourceCodeStart":674,"sourceCodeEnd":710,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/client/mem0.ts#L674-L710","documentation":"Thrown by MemoryClient.createWebhook() when the client's internally resolved projectId is null after awaiting identity. Unlike getWebhooks, createWebhook has no per-call projectId override — it relies entirely on the identity resolved from the API key. The webhook registration URL /api/v1/webhooks/projects/{projectId}/ cannot be built without it.","triggerScenarios":"Calling client.createWebhook({ name, url, eventTypes }) with an API key whose identity carries no project, or when the identity ping could not complete (offline, blocked, or malformed response). Any createWebhook call immediately after client construction where the ping resolved to a null projectId.","commonSituations":"Personal API key not attached to any project; network egress blocked so the identity ping fails silently before the throw; using a test key against the wrong host (e.g. EU host with a US key).","solutions":["Use an API key that belongs to the target project (Mem0 dashboard -> Project -> API keys), then construct a fresh MemoryClient with it","Confirm projectId resolution with the working sibling call: const hooks = await client.getWebhooks(); — if it also fails, the identity itself lacks a project","Check that the client can reach the identity/ping endpoint (proxy or firewall rules) and that host is correct in ClientOptions"],"exampleFix":"// before\nconst client = new MemoryClient({ apiKey: OLD_PERSONAL_KEY });\nawait client.createWebhook({ name: 'n', url: 'https://ex.com/h', eventTypes: ['memory.created'] });\n\n// after\nconst client = new MemoryClient({ apiKey: PROJECT_SCOPED_KEY });\nawait client.createWebhook({ name: 'n', url: 'https://ex.com/h', eventTypes: ['memory.created'] });","handlingStrategy":"validation","validationCode":"// createWebhook has no per-call override; verify identity first via a cheap call\nconst projects = await client.getOrgsProjects();\nif (!projects?.length) {\n  throw new Error('API key is not project-scoped; cannot create webhooks');\n}\nawait client.createWebhook({ name, url, eventTypes });","typeGuard":null,"tryCatchPattern":"try {\n  await client.createWebhook(webhook);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('projectId must be set')) {\n    // configuration error — retrying will not help; surface to operator\n    throw new Error('Regenerate the Mem0 API key from inside the target project');\n  }\n  throw e;\n}","preventionTips":["Create API keys from within the target project's dashboard page so they are project-scoped","Add a startup health check that calls getWebhooks() (or getOrgsProjects()) before registering webhooks","Keep createWebhook calls out of retry middleware — this error is deterministic, not transient"],"tags":["webhooks","hosted-api","validation","project-id","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}