Skip to main content
Glama

Cooper Email

Rotate a webhook secret

cooper_rotate_webhook_secret
Destructive

Use this when a webhook signing secret should change without breaking receivers that still check the old secret. Requires auth. Inputs: webhook_id (required). Mints a new secret (whsec_…), stores it as the current secret, and keeps the previous secret valid for 24 hours. Returns the webhook with the new secret in full once, previous_secret_expires_at (ISO-8601), and previous_secret_active true. The previous secret value is not returned. For those 24 hours each delivery sends x-cooper-signature as sha256=,sha256= and x-cooper-signature-v2 as v1=,v1=, current secret first. Verify by splitting on the comma and accepting the delivery when any segment matches. Rotating again replaces the previous secret and resets the 24 hour window. A hook with no secret just stores the new one. Needs webhook_write, the same permission as updating a webhook. Fails with 404 webhook_not_found or 403 permission_denied.

Input Schema

NameRequiredDescriptionDefault
webhook_idYesWebhook id (wh_…) whose signing secret should rotate

Output Schema

NameRequiredDescriptionDefault
idNoStable id of the returned object. Pass it to the matching get, update, or delete tool.
urlNoURL that receives POST deliveries.
eventsNoEvent types this object delivers.
secretNoSigning secret. Shown in full once on create or rotate, redacted otherwise.
enabledNoTrue when the object is active.
headersNoExtra delivery headers. Values are redacted.
inbox_idNoInbox id (inb_…) this object belongs to. Null when it applies to every inbox.
client_idNoCaller idempotency key stored with the object, or null.
inbox_idsNoInbox ids this object is limited to. Empty means every inbox on the account.
created_atNoISO-8601 time the object was created.
disabled_atNoISO-8601 time Cooper disabled the hook, or null.
disabled_reasonNoWhy the hook was disabled, or null.
consecutive_failuresNoFailed deliveries in a row.
previous_secret_activeNoTrue while deliveries are also signed with the previous secret.
previous_secret_expires_atNoISO-8601 time the previous secret stops signing, or null.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "additionalProperties": true,
      +  "description": "The webhook with the new secret in full once.",
      +  "properties": {
      +    "client_id": {
      +      "description": "Caller idempotency key stored with the object, or null."
      +    },
      +    "consecutive_failures": {
      +      "description": "Failed deliveries in a row."
      +    },
      +    "created_at": {
      +      "description": "ISO-8601 time the object was created."
      +    },
      +    "disabled_at": {
      +      "description": "ISO-8601 time Cooper disabled the hook, or null."
      +    },
      +    "disabled_reason": {
      +      "description": "Why the hook was disabled, or null."
      +    },
      +    "enabled": {
      +      "description": "True when the object is active."
      +    },
      +    "events": {
      +      "description": "Event types this object delivers."
      +    },
      +    "headers": {
      +      "description": "Extra delivery headers. Values are redacted."
      +    },
      +    "id": {
      +      "description": "Stable id of the returned object. Pass it to the matching get, update, or delete tool."
      +    },
      +    "inbox_id": {
      +      "description": "Inbox id (inb_…) this object belongs to. Null when it applies to every inbox."
      +    },
      +    "inbox_ids": {
      +      "description": "Inbox ids this object is limited to. Empty means every inbox on the account."
      +    },
      +    "previous_secret_active": {
      +      "description": "True while deliveries are also signed with the previous secret."
      +    },
      +    "previous_secret_expires_at": {
      +      "description": "ISO-8601 time the previous secret stops signing, or null."
      +    },
      +    "secret": {
      +      "description": "Signing secret. Shown in full once on create or rotate, redacted otherwise."
      +    },
      +    "url": {
      +      "description": "URL that receives POST deliveries."
      +    }
      +  },
      +  "type": "object"
      +}
  2. Added

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past the annotations: it discloses the 24-hour overlap window, that the new secret is returned in full exactly once, that the previous secret value is not returned, that re-rotating replaces the previous secret and resets the clock, and the required permission plus 404/403 failure modes. The destructiveHint=true annotation is substantiated by the concrete consequence of the call.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the when-to-use clause and the core effect, then the timing and response details. It is dense but nearly every sentence earns its place; the signature-format and verification guidance is arguably operational detail that stretches the definition slightly, though it is genuinely useful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still sums up the key fields (new secret, previous_secret_expires_at, previous_secret_active) so an agent knows what to surface. Permissions, error codes, idempotency-relevant rotation semantics, and header verification are all covered for a mutation tool of this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single webhook_id parameter is fully described in the schema, so the description only restates that it is required and echoes the wh_… prefix. Baseline 3 is appropriate when the schema carries the semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Rotate a webhook secret' / 'Mints a new secret (whsec_…)'), and the scope is narrow enough to distinguish it from cooper_update_webhook, cooper_register_webhook, and cooper_delete_webhook without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use condition: change the signing secret without breaking receivers that still check the old one. It also covers the rotate-again and no-existing-secret cases. It never names a sibling tool (e.g. update_webhook for non-rotating changes, register_webhook for initial setup) as the alternative, so the routing is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.