Send durable, idempotent transactional emails from Convex using useSend, an open-source Resend alternative with batching, rate limiting, and webhook support.
npm install @pulgueta/usesend-convexuseSend Convex Component integrates the useSend transactional email service (an open-source Resend alternative) into Convex applications with durable, exactly-once email delivery. It uses Convex workpools for retry logic, automatic batching to the useSend batch endpoint, and idempotency key management to prevent duplicate sends. Webhook support enables real-time delivery status callbacks, and a typed REST client exposes the full useSend API for contacts, domains, campaigns, and analytics.
Install @pulgueta/usesend-convex, register the component in convex/convex.config.ts, then call usesend.sendEmail(ctx, { from, to, subject, html }) inside any Convex mutation or action. The component handles queueing, batching, and retries automatically so emails are eventually delivered without manual retry logic.
Mount an HTTP route in convex/http.ts pointing to usesend.handleUseSendEventWebhook(ctx, req), then register your useSend webhook URL in the useSend dashboard. Set USESEND_WEBHOOK_SECRET in your Convex environment and provide an onEmailEvent callback to the UseSend constructor to receive bounce, delivery, and spam complaint events as Convex mutations.
The @pulgueta/usesend-convex component integrates useSend, an open-source alternative to Resend, Sendgrid, Mailgun, and Postmark, directly into Convex projects. It exposes the same durable sending pipeline and full REST API coverage as commercial email providers but works with both useSend's hosted service and self-hosted instances.
Import sendReactEmail from @pulgueta/usesend-convex/react-email, author your template as a React component using the react-email component library, and call sendReactEmail inside a Convex mutation. The integration renders the component to email-client-safe HTML and generates a plain-text fallback before passing it through the durable send pipeline.
The useSend Convex component manages useSend idempotency keys internally for every email it sends. Combined with Convex workpools for durable execution, this guarantees exactly-once delivery even when mutations are retried due to transient failures or network outages.
Yes. Pass the baseUrl option to the UseSend constructor pointing at your self-hosted instance: new UseSend(components.usesend, { baseUrl: 'https://your-usesend-instance.com' }). The component defaults to https://app.usesend.com but will use any compatible endpoint.
usesend.sendEmail works inside Convex mutations and actions. The full REST API client at usesend.api, which covers contacts, domains, campaigns, and analytics, performs HTTP calls and must run inside a Convex action rather than a mutation.
The useSend Convex component retains finalized emails (delivered, cancelled, bounced) indefinitely by default. You are responsible for cleanup. Schedule cleanupOldEmails and cleanupAbandonedEmails via a Convex cron job using ctx.scheduler.runAfter to remove records older than a threshold you define, such as one week.
Yes. Pass a scheduledAt field with an ISO 8601 timestamp to usesend.sendEmail to have useSend deliver the email at a later time. Scheduled emails can be rescheduled or cancelled through the REST API client at usesend.api.emails.updateSchedule and usesend.api.emails.cancel using the email's usesendId.