A provider secret is the signing secret webhook.co uses to verify that an inbound webhook really came from your provider. You register one per endpoint per provider; from then on every matching event is checked and its verification state recorded. Secrets are sealed at rest, never returned by any read, and revoking one stops verification from honoring it immediately.
Adding and revoking need an API key with endpoints:write; listing needs endpoints:read.
Add a secret
Give it the provider slug (one of 142 — see the provider directory) and the secret value. Optionally attach a label to tell rotations apart. The CLI never takes the secret as an argument — it reads it from a hidden prompt or piped stdin, so it never lands in your shell history or the process list.
wbhk endpoints add-provider-secret <endpoint-id> --provider stripe --label "prod signing"
# paste the secret at the hidden prompt, or pipe it non-interactively:
printf %s "$STRIPE_SIGNING_SECRET" | \
wbhk endpoints add-provider-secret <endpoint-id> --provider stripe --label "prod signing"
curl -X POST https://api.webhook.co/v1/endpoints/<endpoint-id>/provider-secrets \
-H "Authorization: Bearer $WEBHOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"provider": "stripe", "secret": "whsec_your_signing_secret", "label": "prod signing"}'
await webhook.providerSecrets.add({
endpointId,
provider: "stripe",
secret: process.env.STRIPE_SIGNING_SECRET!,
label: "prod signing",
});
client.provider_secrets.add(
endpoint_id=endpoint_id,
provider="stripe",
secret=os.environ["STRIPE_SIGNING_SECRET"],
label="prod signing",
)
Most providers sign with a single signing secret, which is the default. A couple need a second, differently-typed value — set kind to say which:
signing_secret — the payload-signing secret the verify path uses. The default; omit kind for it.
verify_token — a token echoed back to answer a GET verification handshake (for example a Meta hub.verify_token). It coexists with the signing secret under the same provider.
braintree_public_key — Braintree’s integration public key, needed to answer Braintree’s challenge handshake. Registered over the API or SDKs.
An added secret is validated at the boundary against the same decoder the verify path uses, so a value that could never match is rejected up front rather than sitting there failing silently.
List secrets
Listing returns metadata only — id, provider, label, status, and created-at. The sealed bytes and the plaintext are never in the response.
wbhk endpoints list-provider-secrets <endpoint-id>
curl "https://api.webhook.co/v1/endpoints/<endpoint-id>/provider-secrets" \
-H "Authorization: Bearer $WEBHOOK_API_KEY"
const secrets = await webhook.providerSecrets.list(endpointId);
for (const s of secrets) console.log(s.id, s.provider, s.status, s.label);
Each secret’s status is one of:
| Status | Meaning |
|---|
active | Honored by the verify path. |
retiring | Still honored — the state a superseded secret sits in during a rotation. |
revoked | No longer honored; kept as history. |
Revoke a secret
Revoking evicts the secret from the honored set and clears the ingest cache immediately, so verification stops trusting it right away. Pass the endpoint id and the secret id from the list.
wbhk endpoints revoke-provider-secret <endpoint-id> <secret-id>
curl -X DELETE \
"https://api.webhook.co/v1/endpoints/<endpoint-id>/provider-secrets/<secret-id>" \
-H "Authorization: Bearer $WEBHOOK_API_KEY"
await webhook.providerSecrets.revoke({ endpointId, secretId });
Revocation takes effect immediately — events signed only with the revoked secret start failing
verification at once. During a rotation, add the new secret before you revoke the old one.
Rotate without downtime
Providers roll signing secrets periodically. To rotate with no gap:
- Add the provider’s new secret. Both secrets are now honored — one
active, the older one retiring — so events signed with either verify.
- Wait for the provider to fully cut over to the new secret.
- Revoke the old one.
No event fails verification in the window, because there’s always at least one honored secret that matches.
Once a secret is registered, events arrive with a real verification state instead of unattempted. See verify inbound signatures for what each state means.