SIGN IN SIGN UP

refactor(api): share webhook signature verification (#3704)

- [x] I understand that this repository is auto-generated and my pull
request may not be merged

## Changes being requested

Move the identical webhook header/timestamp/HMAC verification core into
the
SDK-owned `lib/_webhooks.py` module. The public sync and async wrappers
retain
their signatures, client-secret fallback, mismatch errors, and their
existing
exception-chaining differences. Both `unwrap` methods are unchanged.

The helper keeps the same replay-window checks, secret decoding, signed
bytes,
signature order, and `hmac.compare_digest` calls. This is a
behavior-preserving
extraction, not a change to accepted signatures or verification policy.
Generation metadata, dependencies, workflows, and the API reference are
unchanged.

The verified custom-code report keeps 40 mixed files and changes only
the
webhook resource's patch: **+179/-3 → +89/-3**. The other 39
customizations are
unchanged.

## Additional context & links

Please get SDK CODEOWNER review for this verification-boundary change.

The existing 71 cases remain unchanged in

[`tests/lib/test_webhooks.py::TestWebhooks`](https://github.com/openai/openai-python/blob/ece4324da0b96f848b48bdef090a372ff0a1db26/tests/lib/test_webhooks.py#L32)
and

[`tests/lib/test_webhooks.py::TestAsyncWebhooks`](https://github.com/openai/openai-python/blob/ece4324da0b96f848b48bdef090a372ff0a1db26/tests/lib/test_webhooks.py#L170).
The new

[`tests/lib/test_webhook_signature.py`](https://github.com/openai/openai-python/blob/35d955800683b814490c7a583b91611c30df9a71/tests/lib/test_webhook_signature.py)
adds 87 cases for raw/prefixed/empty secrets, text/bytes payloads,
replay-window
boundaries, exact timestamp text, header order, malformed inputs, and
constant-time comparison order. In particular,

[`test_missing_secret_preserves_wrapper_exception_chaining`](https://github.com/openai/openai-python/blob/35d955800683b814490c7a583b91611c30df9a71/tests/lib/test_webhook_signature.py#L146)
and

[`test_mismatch_preserves_wrapper_exception_chaining`](https://github.com/openai/openai-python/blob/35d955800683b814490c7a583b91611c30df9a71/tests/lib/test_webhook_signature.py#L161)
pin the existing sync/async differences.

Validation: exact-source/AST preservation check; `./scripts/format`;
`./scripts/lint` (Ruff, Pyright, mypy, import); wheel and sdist builds
with the
new helper included; **158 tests passed under Pydantic v2 and 158 under
v1**.
A
Alex Chang committed
e14ac34376efa5260ef9ef82b939f451f6f9a66a
Parent: ece4324
Committed by GitHub <noreply@github.com> on 8/21/2026, 12:59:13 AM