feat: add suppressions endpoints#246
Open
felipefreitag wants to merge 1 commit into
Open
Conversation
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
Adds suppression-list support:
add,list,get,remove, plus a nestedBatchwithadd/remove— each with an_asynctwin (6 sync + 6 async).Follows the
resend/domains/claims/layout for a nested sub-resource, reusesPaginationHelperforlist,Literalfor theoriginenum, andurllib.parse.quote(..., safe='')for the id-or-email path segment.Two TypedDicts rather than one:
SuppressionListItem(five fields) for list entries andSuppressionforget(those five plusobject) — following the existingEvent/EventListItemprecedent inresend/events/_event.py, which is the same situation.Batch.removebuilds its body through a single_build_remove_bodyhelper that both validates the XOR and stripsNonevalues, so validation and serialization cannot disagree about whatNonemeans — matching the# Filter out None valuesconvention already inPaginationHelper.Contract verification
Verified in order of authority: the API server implementation (
apps/public-api/src/routes/suppressions/in the monorepo), thenresend-openapiresend.yaml, then the docs — and finally end-to-end against the live API with a real team key (read-only operations).One deliberate divergence, flagged so it does not look like a bug in review: list entries do not carry the
objectfield; only the single-getresponse does.list.tsselects exactly{id, email, origin, source_id, created_at}and adds nothing, whileget.tsreturns{object: "suppression", ...}. Confirmed on live wire output.Two upstream artifacts disagree with the server here and are being tracked separately, so please do not use them as the reference when reviewing:
list-suppressionsdocs example shows a per-entryobjectthat the API never sendsresend-nodeSuppressionListEntrydeclares the same nonexistent field, and is shipped inresend@6.18.0The OpenAPI spec is correct on this point and agrees with the implementation.
Other behaviour confirmed at the server and reflected in docs/tests, not reimplemented client-side:
batch/removeacceptsemailsXORids; the unset key must be omitted, since the server validation accepts undefined but rejects an explicitnullbatch/addupserts — so batch responses can contain fewer entries than were sent; callers must not pair results to inputs by indexbatch/removereturns only rows actually deleted (misses are absent, no error), whereas singleremovereturns 404 on a misssource_idis nullable and isnullformanual-origin suppressionsRelease timing
These endpoints are in beta and gated behind a server-side feature flag: a team without access receives 404 on every suppression endpoint. Merging is safe, but worth a deliberate decision on whether this ships in the next release or waits for wider flag rollout, since otherwise a documented SDK method returns 404 for most users.
Verification
Python 3.9.6, inside CI's 3.8-3.11 matrix. 58 of those tests cover suppressions, including null
source_id, theidsbatch-remove variant, explicit-Noneomission (sync and async), server-side dedupe returning fewer entries than sent, and the all-miss empty-datacase.Summary by cubic
Adds suppression list support to the
resendPython SDK. Includes add, list, get, remove, and batch add/remove with both sync and async methods.New Features
Suppressions.add,list,get,remove, plusSuppressions.Batch.addandremove(async variants included).Suppression(single),SuppressionListItem(list), andSuppressionOriginenum.PaginationHelper.Migration
emailsorids(not both) and omit the unset key (do not send null).objectfield; onlygetresponses do.Written for commit 2155f03. Summary will update on new commits.