Update a webhook
lob_webhooks_updateUpdate an existing webhook's URL, event subscriptions, or description. Lob automatically manages the disabled status.
Instructions
Update a webhook's URL, event subscriptions, or description. Note: the disabled flag on the response is Lob-managed (e.g. Lob auto-disables webhooks whose delivery URL consistently fails) and is not settable by callers.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Webhook ID (`ep_…`). | |
| url | No | ||
| event_types | No | ||
| description | No | ||
| metadata | No | Up to 20 string key/value pairs of arbitrary metadata to attach to the resource. | |
| extra | No | Additional Lob API parameters not enumerated above. Merged into the request body verbatim. See https://docs.lob.com for the full parameter list per resource. |
Implementation Reference
- src/tools/webhooks.ts:81-89 (handler)Handler for lob_webhooks_update: destructures id and extra from args, then sends a POST request to /webhooks/{id} with the remaining fields as body (merged with extra params).
handler: async (args) => { const { id, extra, ...rest } = args; return lob.request({ method: "POST", path: `/webhooks/${id}`, body: withExtra(rest, extra), }); }, }); - src/tools/webhooks.ts:73-80 (schema)Input schema for lob_webhooks_update: accepts id (required webhook ID matching whk_ or ep_ prefix), optional url, optional event_types array, optional description (max 255 chars), optional metadata, and optional extra escape hatch.
inputSchema: { id: WH_ID, url: z.string().url().optional(), event_types: z.array(z.string()).optional(), description: z.string().max(255).optional(), metadata: metadataSchema, extra: extraParamsSchema, }, - src/tools/webhooks.ts:66-89 (registration)Registration of lob_webhooks_update via registerTool helper inside the registerWebhookTools function. Uses mutate annotation preset.
registerTool(server, { name: "lob_webhooks_update", annotations: { title: "Update a webhook", ...ToolAnnotationPresets.mutate }, description: "Update a webhook's URL, event subscriptions, or description. Note: the `disabled` flag on the " + "response is Lob-managed (e.g. Lob auto-disables webhooks whose delivery URL consistently fails) " + "and is not settable by callers.", inputSchema: { id: WH_ID, url: z.string().url().optional(), event_types: z.array(z.string()).optional(), description: z.string().max(255).optional(), metadata: metadataSchema, extra: extraParamsSchema, }, handler: async (args) => { const { id, extra, ...rest } = args; return lob.request({ method: "POST", path: `/webhooks/${id}`, body: withExtra(rest, extra), }); }, }); - src/schemas/common.ts:161-166 (helper)Helper function withExtra used by the handler: merges extra parameters with typed fields, with typed fields taking precedence.
export function withExtra( payload: object, extra: Record<string, unknown> | undefined, ): Record<string, unknown> { return { ...(extra ?? {}), ...compact(payload) }; } - src/tools/helpers.ts:85-128 (helper)registerTool helper that wraps tool registration with consistent error handling and JSON content formatting.
export function registerTool<TShape extends ZodRawShape>( server: McpServer, def: ToolDefinition<TShape>, ): void { const a = def.annotations ?? {}; server.registerTool( def.name, { title: a.title ?? def.name, description: def.description, inputSchema: def.inputSchema, annotations: { ...a, // Lob is always external; default the hint accordingly. openWorldHint: a.openWorldHint ?? true, }, }, // The SDK's ToolCallback type is parameterised over the exact ZodRawShape and // resists the generic erasure here. The runtime contract (validated args in, // CallToolResult out) is correct, so we bridge the type boundary with `as never`. (async (args: unknown, serverCtx: unknown): Promise<CallToolResult> => { try { const result = await def.handler(args as never, serverCtx); return { content: [{ type: "text", text: stringifyResult(result) }] }; } catch (err) { return { isError: true, content: [{ type: "text", text: formatErrorForTool(err) }], }; } }) as never, ); } function stringifyResult(value: unknown): string { if (value === undefined || value === null) return "(no content)"; if (typeof value === "string") return value; try { return JSON.stringify(value, null, 2); } catch { // JSON.stringify throws on circular refs; safeStringify handles them via fallback. return safeStringify(value); } }