{"record":{"id":"97885d5511c92790","repo":"paperclipai/paperclip","slug":"webhook-ingestion-is-not-enabled","errorCode":null,"errorMessage":"Webhook ingestion is not enabled","messagePattern":"Webhook ingestion is not enabled","errorType":"http","errorClass":null,"httpStatus":501,"severity":"error","filePath":"server/src/routes/plugins.ts","lineNumber":2694,"sourceCode":"   * 2. The plugin declares the `webhooks.receive` capability\n   * 3. The `endpointKey` matches a declared webhook in the manifest\n   *\n   * The delivery is recorded in the `plugin_webhook_deliveries` table and\n   * dispatched to the worker via the `handleWebhook` RPC method.\n   *\n   * **Note:** This route does NOT require board authentication — webhook\n   * endpoints must be publicly accessible for external callers. Signature\n   * verification is the plugin's responsibility.\n   *\n   * Response: `{ deliveryId: string, status: string }`\n   * Errors:\n   * - 404 if plugin not found or endpointKey not declared\n   * - 400 if plugin is not in ready state or lacks webhooks.receive capability\n   * - 502 if the worker is unavailable or the RPC call fails\n   */\n  router.post(\"/plugins/:pluginId/webhooks/:endpointKey\", async (req, res) => {\n    if (!webhookDeps) {\n      res.status(501).json({ error: \"Webhook ingestion is not enabled\" });\n      return;\n    }\n\n    const { pluginId, endpointKey } = req.params;\n\n    // Step 1: Resolve the plugin\n    const plugin = await resolvePlugin(registry, pluginId);\n    if (!plugin) {\n      res.status(404).json({ error: \"Plugin not found\" });\n      return;\n    }\n\n    // Step 2: Validate the plugin is in 'ready' state\n    if (plugin.status !== \"ready\") {\n      res.status(400).json({\n        error: `Plugin is not ready (current status: ${plugin.status})`,\n      });\n      return;","sourceCodeStart":2676,"sourceCodeEnd":2712,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/server/src/routes/plugins.ts#L2676-L2712","documentation":"501/503-style guard on the public plugin webhook ingestion route. Fires when webhook ingestion is disabled at the instance/app level, so external webhook deliveries cannot be recorded or dispatched even though the route is intentionally unauthenticated.","triggerScenarios":"Thrown at server/src/routes/plugins.ts:2672 when the library encounters an invalid state.","commonSituations":"Returned when an inbound webhook is received but webhook ingestion is disabled for the company or plugin instance.","solutions":["Enable webhook ingestion for the company (webhooksEnabled / plugin webhook setting) before calling the webhook endpoint.","Confirm the webhook route is being called against the intended company and plugin instance."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}