Repository navigation
fix: send the documented field set and honour every base URL override - #40
Merged
franciscbalint merged 1 commit intoOct 25, 2026
Merged
Conversation
An audit against the 74 documented operations turned up a group of places where the client and the API disagree. None of them are cosmetic: each one either sends something the endpoint does not document, refuses something the endpoint accepts, or quietly drops a value the caller passed. - validateBatch handed its JSON body to fetch as a plain string, so createRequest never set Content-Type and fetch labelled the JSON text/plain;charset=UTF-8. The API tolerates it today, which is exactly why it is worth fixing before it stops doing so. It now goes out as jsonBody. - findEmailByDomain / findEmailByCompanyName rejected a missing first_name although /guessformat documents it as optional for the find-email use: without a name the API answers with the domain's or company's format. The name is now left out of the query rather than refused. The domain-search helpers and the deprecated guessFormat are untouched. - The bulk email finder needs a name to work from, so sendEmailFinderFile and sendEmailFinderFileStream now require first_name_column or full_name_column instead of only domain_column. 0 and false stay the "leave this column out" sentinel, so neither counts as given. - exportS3file rejected a missing export_bucket although it is optional and its sibling exportSFTPfile already treats export_path that way. Without it the bucket from the account's settings is used. - validateS3file and scoreS3file had bespoke bodies that sent seven undocumented fields (email_address_column, the name/gender/IP columns, allow_phase_2 and a singular remove_duplicate) and made return_url optional. The live API requires return_url -- POST /validateS3file without it answers 400 "Provided return URL is not permitted: None" -- so both now go through _bulkRootFileJob with their six siblings and send exactly file_name, has_header_row, remove_duplicates and return_url. - init validated and stored emailFinderBaseURL and domainSearchBaseURL but nothing ever read them: ops 20-27 hardcoded the bulk root, so two advertised overrides silently did nothing. Both are now passed to createRequest as baseURL with a path relative to them, the way the list evaluator and the Inbox Placement Tester already work. The defaults are unchanged, so a client that does not set them sends the same URLs. - validateSFTPfile passed a third argument to a two-parameter helper, where it was silently dropped, and its jsdoc still promised an optional file_name that the helper has required for some time. - Warmup addSendingAccount only added engagement_rule_id inside the self_managed branch, so a caller who sent one for a zb_managed account had it dropped without a word. It is rejected now, as email_content and managed_sending already are for self_managed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
franciscbalint
deleted the
fix/documented-field-sets-and-base-url-overrides
branch
October 25, 2026 21:19
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.
Fixes found auditing the SDK against the 74 documented ZeroBounce operations. Each item is a real disagreement between the client and the API, not a tidy-up: the client either sends a field the endpoint does not document, refuses a call the endpoint accepts, or drops a value the caller passed.
No version bump — 3.0.0 is already published, so the entries go under
## [Unreleased].Fixed
validateBatchsends JSON as JSON. The body was handed tofetchas a pre-stringified string, socreateRequestnever setContent-Typeandfetchlabelled the payloadtext/plain;charset=UTF-8. The live API tolerates it today; that is the reason to fix it now rather than later. It goes out asjsonBody.validateSFTPfilepassed a third argument (false) to_bulkRootFileJob, which takes two parameters, so it was silently dropped. Removed, and its jsdoc no longer promises an optionalfile_namethat the helper has required for some time.addSendingAccountdroppedengagementRuleIdforzb_managed. The field was only added to the body inside theself_managedbranch, so a caller who sent one for a managed account got no error and no field. It is rejected explicitly now, asemail_contentandmanaged_sendingalready are forself_managed.Changed
emailFinderBaseURLanddomainSearchBaseURLnow work.initvalidated and stored both, but nothing ever read them — ops 20–27 hardcoded the bulk root, so two advertised overrides did nothing at all. Both are now passed tocreateRequestasbaseURLwith a path relative to them, the same way the list evaluator and the Inbox Placement Tester already work. The defaults are unchanged, so a client that does not set them sends exactly the same URLs as before.findEmail*accept a missingfirst_name./guessformatdocuments it as optional for the find-email use: without a name the API answers with the domain's or company's email format. It is left out of the query rather than refused.domain/company_nameis still required, and_findEmailFormat, the domain-search helpers and the deprecatedguessFormatare untouched.exportS3fileaccepts a missingexport_bucket, matching its siblingexportSFTPfile's handling ofexport_path. Without it the output bucket from your ZeroBounce settings is used.sendEmailFinderFileandsendEmailFinderFileStreamnow requirefirst_name_columnorfull_name_columnas well asdomain_column.0andfalseremain the "leave this column out" sentinel, so neither counts as given.validateS3fileandscoreS3filesend exactly the documented set. Both had bespoke implementations that sent seven undocumented fields (email_address_column,first_name_column,last_name_column,gender_column,ip_address_column,allow_phase_2, and a singularremove_duplicate) and madereturn_urloptional. The live API requires it —POST /validateS3filewithout it answers400 {"error_message":"Provided return URL is not permitted: None"}— so both now route through the existing_bulkRootFileJobhelper with their six siblings and sendfile_name,has_header_row,remove_duplicatesandreturn_url, nothing more.allowPhase2stays available onsendFile/sendFileStream, where it is documented.Tests
Jest with mocked HTTP for every changed method, asserting the method, the full URL, the parameters and where the key travels, and the parsed response including error bodies:
validateBatchsendsContent-Type: application/json, the key in the body and not the query, andtimeoutas the string the live API wants.findEmail*with and withoutfirst_name, asserting the exact query string both ways.0/falsesentinel, and that no request goes out when it is unmet.https://check on both overrides and the unchanged default host.exportS3filewith and withoutexport_bucket.400rejection body surfaced as a short message with its status code.addSendingAccountrejectingengagementRuleIdforzb_managedbefore sending anything.zeroBounceSDK.d.tsis updated to match (the two S3 option types now extendBulkRootFileJobOptions, whosefile_nameandreturn_urlare required;first_nameis optional on the finder options; the two base URL overrides are declared), andtests/ts-consumer.tsexercises the new shapes.npm run dts-checkandnpm run test:coveragepass as well.🤖 Generated with Claude Code