Repository navigation
feat: add webhook delivery retry - #39
Merged
Merged
Conversation
- New operation: POST /webhooks/{webhookId}/deliveries/{deliveryId}/retry
(team token, no request body). Returns 202 with a
RetryWebhookDeliveryResponse (message, delivery_id); 409 with an
ApiErrorBody when the delivery cannot be retried.
- WebhookDeliveryData and WebhookDeliveryListData gain an optional,
nullable next_retry_at.
- WebhookDeliveryData payload, response_body, response_headers and
error_message note that they are always included with a team API token.
- The webhook delivery and regenerate-secret operations list 401, 403 and
429 bodies as either ErrorMessage or ApiErrorBody.
Co-Authored-By: Claude <noreply@anthropic.com>
- webhooks.deliveries.retry(webhook_id, delivery_id, *, timeout=None) sends a delivery's original payload to the webhook again now and returns a RetryWebhookDeliveryResponse. It uses the team token and sends no body and no Idempotency-Key header. - A 409 (webhook disabled, delivery not retryable, retry in progress) raises ConflictError with the error code. - Document it in the README and test the request, the token, both path parameters, the 409 and the 403, 404 and 429 errors in either body shape, and next_retry_at on deliveries. Co-Authored-By: Claude <noreply@anthropic.com>
bjornftw
approved these changes
Oct 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Adds
client.webhooks.deliveries.retry(webhook_id, delivery_id). It sends a delivery's original payload to the webhook again now and returns aRetryWebhookDeliveryResponse. The retry counts as a delivery attempt; if it fails with a retryable error, automatic retries continue. It uses the team token and sends no request body and noIdempotency-Keyheader. Sync and async clients both have it.It sits next to
webhooks.deliveries.retrieve, like every other/webhooks/{webhookId}/deliveriesoperation in this SDK. A409raises the existingConflictError, with the API error code in.code(WEBHOOK_DISABLED,WEBHOOK_DELIVERY_NOT_RETRYABLEorWEBHOOK_DELIVERY_RETRY_IN_PROGRESS). No new error class.The types are regenerated from the latest API spec in their own commit.
Not a breaking change. Suggested version bump: minor.
API changes in the regenerated types
POST /webhooks/{webhookId}/deliveries/{deliveryId}/retryoperations.py, newRetryWebhookDeliveryResponse(message,delivery_id)202on success;404when the webhook or delivery is not found;409ApiErrorBodywhen it cannot be retried;429withRetry-After;401/403next_retry_atWebhookDeliveryData,WebhookDeliveryListDataNotRequired[str | None]: when the next automatic retry is due,Nonewhen none is scheduledWebhookDeliveryData.payload,response_body,response_headers,error_messageGET /webhooks/{webhookId}/deliveries,GET /webhooks/{webhookId}/deliveries/{deliveryId},POST /webhooks/{webhookId}/regenerate-secret401,403and429list eitherErrorMessage({message}) orApiErrorBody({error: {code, message, ...}}).429no longer points to the sharedTooManyRequestsresponse. The error parser already handled both shapes; the new tests cover both on the retry callUsage
Checks
python -m ruff check src tests scripts: all checks passedpython -m ruff format --check src tests scripts: 27 files already formattedpython -m mypy: no issues in 34 source filespython scripts/unasync.py --check:src/lettermint/_syncis up to datepython scripts/generate.py --check: generated files up to datepython -m pytest tests/: 264 passed on Python 3.10, 3.11, 3.12, 3.13 and 3.14python -m build, thenpython -m twine check --strict dist/*: both artifacts passedUPGRADE.mdandpy.typedin the wheel, client repr): passed.webhooks.deliveries.retryis present in the installed wheelNew tests (
tests/test_webhooks.py):POST, teamAuthorizationheader, empty body, noContent-TypeorIdempotency-Key202parsed asRetryWebhookDeliveryResponseLettermintConfigErrorbefore any request409WEBHOOK_DELIVERY_NOT_RETRYABLEraisesConflictErrorwith the code403,404and429in both body shapes, includingretry_afternext_retry_atondeliveries.retrieveanddeliveries.list, as a value and asNonetests/test_surface.pynow covers the new operation and thewebhooks.deliverieslayout.Not run locally
Nothing. The CI matrix and the build job were reproduced locally.
Suggested release tag
v3.2.0(minor).mainalso has the unreleasedmessages.resendand per-email batch idempotency keys sincev3.1.0.🤖 Generated with Claude Code