prontuno/prontuno-laravel
Prontuno for Laravel is a lightweight package that brings Prontuno functionality into your Laravel applications. It offers straightforward Composer installation, simple configuration, and familiar Laravel conventions, making it easy to integrate and use in new or existing projects.
Mail:: as normal, so feature teams don't relearn an SDK per feature. That keeps roadmap estimates for email-touching features close to estimates for non-email features.withSendingKey() (per-domain mailer) and usingApiKey() (single-key client, returns a new client) make per-tenant sending a first-class pattern rather than an afterthought. This informs decisions about whether one deployment serves many brands or many deployments serve one brand each.WebhookEvent constants unblock delivery events (bounces, complaints, opens/clicks if exposed) as triggers for lifecycle messaging, suppression sync, and customer-facing delivery status—without polling.prontuno.webhook:billing named-secret pattern suggests separating billing events from general traffic).Message-ID, retries on 408/429/5xx with Retry-After, and no double-send on retry directly reduce duplicate-charge and duplicate-email incidents. Retryable flags and suggested actions on ApiException shape how much error-handling code product teams must own versus inherit.X-Prontuno-Email-ID on sent messages, request IDs on errors, and fresh signed download links for sent attachments make "where did this email go?" a support-deflectable question rather than an engineering escalation.Http::fake() in tests) and mirrors Laravel's own mail/exception primitives, the switching cost is mostly the transport swap plus webhook and suppression re-plumbing—worth stating explicitly in any make-vs-buy memo.prontuno/prontuno-php client means the email decision shouldn't be scoped as "Laravel only."Consider it when most of the following hold:
Mailable, notification, or Mail::raw() should flow through unchanged via MAIL_MAILER=prontuno; teams shouldn't need a bespoke sending API in feature code.key, plus withSendingKey()/usingApiKey(), are the deciding features if you serve multiple brands or tenants.Http::fake() compatibility means QA and CI can cover sending paths without hitting a live provider—worth weighting if email regressions have burned you.ConfigurationException failures before any request leaves the process.Look elsewhere or wait when:
prontuno/prontuno-php or another SDK instead.Message-ID and email sends retry only when you pass an idempotency key—that's a behavioral contract your code must honor.For executives (one paragraph): We can stop treating transactional email as an in-house platform problem. prontuno/prontuno-laravel is the official, MIT-licensed Laravel integration for the Prontuno API: it plugs into Laravel's native mail system, so sending email, managing suppression lists, rotating webhook secrets, and handling delivery events become configuration rather than engineering projects. It reduces duplicate-send and duplicate-charge risk through idempotency-keyed retries, cuts support load with per-message IDs and actionable error metadata, and supports multi-brand and multi-tenant sending without extra architecture. The trade-off: it's a v0.1.0 first release requiring PHP 8.3+ and Laravel 12/13, so it's an early-adopter commitment with some pre-1.0 churn risk—appropriate for teams willing to pin versions and absorb minor upgrades, and worth a time-boxed pilot before it becomes load-bearing.
For engineering leads: Adoption is deliberately low-friction. Composer install; service provider and Prontuno facade auto-discover; publish config with php artisan vendor:publish --tag=prontuno-config; set MAIL_MAILER=prontuno and you're sending through the standard Mail facade with from/to/cc/bcc/reply-to, text and HTML bodies, custom headers, and attachments including inline ones. Everything is .env-configurable (keys, base URL, timeouts, retries, webhook secrets and tolerance, PRONTUNO_APP_INFO for User-Agent attribution). Sending and management keys are separated, and calling a method whose key isn't configured throws ConfigurationException before any network request—fail-fast rather than silent misconfiguration. For multi-tenancy, withSendingKey() and usingApiKey() return new clients (immutable, no shared mutable state), and per-domain mailers take their own key. Retry behavior is opinionated and sensible: GET/DELETE retry on 408/429/5xx and connection failures, Retry-After honored up to 60s, timeouts per attempt, and a retried DELETE succeeds if the first attempt already removed the resource. Webhooks are verified HMAC over the raw request body with a 300s default tolerance via prontuno.webhook middleware or WebhookVerifier::fromRequest() in your own controller, returning a typed WebhookEvent. Pagination gives you list() for one page or lazy() as a LazyCollection across all pages with a page limit and repeated-cursor protection. Errors are typed—ApiException (status, code, request ID, retryable, suggested action, retry-after, field-level errors per batch item, raw body), ConnectionException extending Laravel's own, plus ConfigurationException and PaginationException. Tests can use Http::fake() throughout. Two things to enforce in code review: pass explicit idempotency keys on email sends if you want retries, and never verify webhook signatures against a re-encoded payload.
For product and support: This directly improves the customer-facing story around "I didn't get the email." Sent messages carry an X-Prontuno-Email-ID header, errors carry request IDs and suggested actions, and sent attachments are retrievable via fresh signed links—so support can diagnose without engineering. Suppression APIs mean unsubscribes and bounces get honored systematically rather than through manual list maintenance, which is a compliance and sender-reputation win. The caveats to communicate upward: it's a first release, the version pin matters, and a pilot with a clear success metric (send-to-delivery time, duplicate-send rate, support ticket volume on email issues) is a better commitment than an immediate org-wide mandate.
How can I help you explore Laravel packages today?