Repository navigation
feat: add messages resend - #39
Merged
Merged
Conversation
- Add the `POST /messages/{messageId}/resend` operation with the
optional `ResendMessageRequest` body (`recipients`)
- Add `resent_from_message_id` to `MessageData`
- Type batch items as `SendBatchMailItem`, which adds an optional
per-email `idempotency_key`
- Batch send 409 responses may now be an `ApiError`
Co-Authored-By: Claude <noreply@anthropic.com>
Add `messages.resend(messageId, body?, options?)` for
`POST /messages/{messageId}/resend`. It sends a sent message again as a
new message, to every original recipient or to the `recipients` given.
Like `process`, it accepts an `idempotencyKey` option; like `reschedule`
and `cancel`, it falls back to the sending token when no team token is
configured.
Co-Authored-By: Claude <noreply@anthropic.com>
`resent_from_message_id` stays nullable and is now optional, so code that constructs `MessageData` keeps compiling. Co-Authored-By: Claude <noreply@anthropic.com>
bjarn
added this pull request to stack #41
October 18, 2026 17:20
bjornftw
approved these changes
Oct 18, 2026
bjarn
added a commit
that referenced
this pull request
Oct 18, 2026
Stacked on #39 — merge that first. ## What changed Non-breaking; suggested bump: **minor**. - New exported type `BatchEmailMessage`: an `EmailMessage` with an optional per-email `idempotency_key`. `emails.sendBatch()` now accepts `(BatchEmailMessage | EmailBuilder)[]`. `EmailMessage[]` still works as before. - Each key goes in its own batch item as `idempotency_key`. It is separate from the request-level `idempotencyKey` option, which still sends the `Idempotency-Key` header. - If an email with the same key and content was accepted in the last 24 hours, the API returns the original result and does not send it again. A retried batch therefore sends only the emails that were not accepted yet. - Builders get a key by spreading their wire format: `{ ...builder.build(), idempotency_key }`. No builder setter was added, so `builder.send()` and `emails.send()` stay unchanged and `EmailMessage` (the single-send type) does not get the field. - The API validates the keys (1-255 characters, unique within a batch, `409 Conflict` when a key is reused with different content). The SDK adds no client-side checks. - Docblock and README: on a mid-batch failure, `error.details.accepted` lists the emails that were already accepted (`{ index, message_id }`). ## Usage ```ts await lettermint.emails.sendBatch( [ { ...invoice, idempotency_key: `invoice-${invoice.id}` }, { ...welcome.to('john@example.com').build(), idempotency_key: 'welcome-john' }, ], { idempotencyKey: 'batch-2026-10-18' } // optional, for the request as a whole ); ``` ## Checks Run locally on Node 26.5.0: - `npm run lint`: passed (33 files, no fixes) - `npm run type-check`: passed - `npm run generate:check`: generated files up to date (with the generator), and the header check passed without it - `npm run test:coverage`: 319 passed, 8 suites - `npm run build`: CJS, ESM and DTS builds succeeded - `npm run test:smoke`: ESM import, CJS require and type declarations ok ## Not run locally - The Node 20, 22 and 24 CI matrix. Only Node 26 was run locally. ## Suggested release tag `v3.2.0` if released together with #39, otherwise the next minor after it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
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
Non-breaking; suggested bump: minor.
src/generated/from the latest API spec.messages.resend(messageId, body?, options?)forPOST /messages/{messageId}/resend. It sends a sent message again as a new message with its own ID, to every original recipient or to therecipientsgiven. Likemessages.process, it takes anidempotencyKeyoption. Likerescheduleandcancel, it uses the team token and falls back to the sending token when no team token is set.resendis listed in the Team API table, with a short example and the note on the token fallback.API changes in the regenerated types
messages.resendendpointPOST /messages/{messageId}/resend. Optional bodyResendMessageRequest { recipients?: string[] }and optionalIdempotency-Keyheader. Answers202with aPendingSendMailResponse. Errors: 401, 403, 404, 409, 410 (content no longer retained), 422, 429, 500. Accepts the team or the sending token.MessageData.resent_from_message_idresent_from_message_id?: string | null. The ID of the message this message resent; absent ornullwhen the message is not a resend. Code that buildsMessageDataobjects keeps compiling.SendBatchMailItemSendMailRequestfield plus an optional per-emailidempotency_key(1-255 characters).SendBatchMailRequestis nowSendBatchMailItem[](wasSendMailRequest[]).POST /send/batch409ApiError(codeIDEMPOTENCY_CONFLICT).OperationTypesPendingSendMailResponseandResendMessageRequest.Usage
Checks
Run locally on Node 26.5.0:
npm run lint: passed (33 files, no fixes)npm run type-check: passednpm run generate:check: generated files up to date (with the generator), and the header check passed without itnpm run test:coverage: 316 passed, 8 suitesMessageDataliteral without the new field and anEmailMessage[]passed tosendBatch, type-checks against this branch (tsc -p tsconfig.test.json: no errors). The only failure is the v3.1.0 coverage test, which lists every operation and so missesresend, as expectednpm run build: CJS, ESM and DTS builds succeedednpm run test:smoke: ESM import, CJS require and type declarations okNot run locally
Suggested release tag
v3.2.0🤖 Generated with Claude Code