Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

46Elks Laravel Package

laravel-notification-channels/46elks

Send SMS notifications from your Laravel app with 46elks, the Swedish messaging provider. This channel plugs 46elks into Laravel's notification system, letting you deliver text messages to users through a familiar notification class backed by the 46elks API.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is a native Laravel notification channel, not a standalone SDK. It plugs into the Notification contract via via() and a to46elks() mapper method, so SMS becomes one more channel alongside mail, database, and chat rather than a new messaging subsystem. Internally the footprint is minimal: a service provider, a config block, a channel class that performs a single authenticated HTTP POST to https://api.46elks.com/a1/sms, and a fluent message DTO. That is the correct architecture for the stated use case (one-way transactional SMS) and the wrong one for anything resembling campaigns, batching, or aggregation — none of which it claims to support.

Integration feasibility. Low effort, with one long-lead dependency. Engineering work is roughly a composer require, a credentials block, a routeNotificationFor46elks() method on the notifiable, and a to46elks() method on existing notifications. The long-lead item is not code: 46elks alphanumeric sender IDs require dashboard approval, and the API user is a separate credential from the account login. Start that provisioning before the first sprint, not during it. On-demand notifications (Notification::route('46elks', $phone)->notify(...)) cover the pre-model case — signup OTPs, where no notifiable record exists yet.

Technical risk.

  • Supply chain. Two stars, zero dependents, community-maintained, no SLA, no commercial backing. Acceptable only because the exit cost is genuinely low — the documented fallback is ~20 lines of Http::withBasicAuth(...)->asForm()->post(...).
  • Semver is not a reliable signal. v1.10.12 widened the framework constraint to Laravel 12 as a patch release. Behavioral compatibility was unaffected, but the precedent matters: a floating constraint can pull a framework-support change nobody validated. Pin exactly and review constraint diffs in dependency PRs by hand.
  • Silent failure surface. notify() does not throw when an SMS fails. The notification is "delivered" as far as Laravel is concerned. Without try/catch, NotificationFailed listeners, or structured logging, credential, balance, and sender-approval failures all look identical to success.
  • No delivery receipts. The API returns a message id and nothing more. Confirming handset receipt requires a DLR callback registered in the 46elks dashboard plus a receiver route you build, allowlist, and treat as untrusted input. That is separate scope and should be costed as such.
  • Scope gaps that become tickets. E.164 normalization, per-tenant credentials, rate-limit backoff, batching, and credit monitoring are all absent. Each is small; collectively they are the difference between a demo and a production channel.

Key questions for the team.

  1. Is 46elks already committed on coverage, pricing, and compliance for our target markets, or is the provider still open? If open, evaluate a provider-agnostic abstraction first — this package locks in a vendor through a 2-star dependency.
  2. Which use cases go live first: internal ops alerts (low blast radius) or end-user OTP/transactional (high blast radius, compliance-relevant, failure-sensitive)? They warrant different acceptance criteria and different sequencing.
  3. What is our idempotency stance per notification? SMS retries are second billable, user-visible messages. OTPs need $tries = 1 plus ShouldBeUnique; status pings tolerate retries.
  4. Do we need delivery confirmation in v1, or can we ship on API acceptance and add DLR later?
  5. Who owns the 46elks account operationally — balance monitoring, sender-ID approvals per market, incident escalation?

Integration Approach

Stack fit. Laravel 12 is explicitly supported as of v1.10.12; earlier releases track Laravel ≤11. The package assumes a standard notification-driven application — existing mail/database channels, queue workers already running, config/services.php or a published package config. If those hold, integration is additive and touches no existing send path. If the application does not already use queued notifications, add that prerequisite to the plan rather than absorbing it silently into the SMS estimate.

Migration path.

  1. composer require laravel-notification-channels/46elks:^1.10.12 — pinned, not floated.
  2. Publish the package config if it ships one; otherwise add a '46elks' block to config/services.php sourced from env (username, password, from).
  3. Confirm package auto-discovery is intact. If the service provider is manually managed, register it — otherwise via() returns a channel class the notifier cannot instantiate, and the failure is silent.
  4. Add routeNotificationFor46elks() returning E.164, and to46elks() on the notification classes being extended.
  5. For pre-model flows, introduce a thin service wrapper (PhoneVerification::send($phone)) so the channel name appears in exactly one place and a provider swap is a one-file change.

Compatibility notes. Phone numbers must be E.164 (+46701234567) — the channel does not defensively reformat, so garbage in produces a delivery failure with a thin error message. Message bodies are GSM-7; 160 characters per segment, dropping to 70 with any non-GSM character (emoji, curly quotes, some accents) and billing per segment. An alphanumeric sender approved in Sweden may be dropped or substituted in other countries — verify per market before committing SMS to a new region.

Sequencing. Four phases, ordered by blast radius:

  • Phase 1 — internal ops alert to an owned handset. Validates credentials, sender approval, number formatting, and actual delivery with zero user exposure. Send it from tinker before touching a user-facing flow.
  • Phase 2 — first end-user transactional flow (order status or equivalent), queued, with failure logging and a retry policy chosen explicitly.
  • Phase 3 — OTP, which is the highest-scrutiny path: strict single-attempt semantics, ShouldBeUnique, a "didn't get the code?" escape hatch, and staging gated so no real SMS leaves non-production.
  • Phase 4 — optional. DLR callback receiver, multi-sender/per-tenant resolution, or provider abstraction, each scoped as its own line item.

Local and staging safety. Either Notification::fake() in a local service provider or a feature flag that returns ['mail'] instead of the SMS channel. A staging OTP reaching a real handset costs money and confuses whoever owns the number.

Operational Impact

Maintenance. Community-maintained with no SLA and a very small contributor base. The mitigation is architectural, not contractual: keep to46elks() a pure mapper so the channel is replaceable in one file, and keep the 20-line direct-HTTP fallback documented and known to more than one engineer. Do not fork the package for metrics or custom retry logic — wrap notify() in an internal SmsNotifier service instead.

Support. Expect no upstream support channel. Defects surface as our own tickets and are triaged by our team. Two recurring categories deserve runbook entries: (a) SMS failures that are actually billing failures — add a low-balance alert on the 46elks account and check balance before debugging queue workers; (b) credential resolution returning null because config:cache ran at image build before env injection — run it at boot and assert non-empty credentials at startup. In-product, provide a self-serve "didn't get the code?" path so credential and balance issues do not all convert into support tickets.

Scaling. Throughput is provider-bound and linear in message count; there is no batching, aggregation, or bulk semantics. Cost scales per segment, so message length is a cost and deliverability lever — keep OTP and status messages under one GSM-7 segment and sanitize smart quotes out of interpolated user strings. Queue workers carry the load; anything slow inside to46elks() (DB queries, HTTP calls, conditionals on app state) becomes queue latency for every other job on that worker, so resolve everything in the constructor or via(). Multi-tenant or multi-brand sender strategies should resolve from a config map keyed by tenant, never hardcoded in notification classes.

Failure modes and detection.

Failure Symptom Detection
Wrong credentials / cached config Auth error, no send Startup assertion on config; error logging
Unapproved sender ID API error, no send Error logging; sender verified in dashboard pre-launch
Non-E.164 number Silent non-delivery Normalize at input boundary; test the accessor
Account out of credit Send failures that look like code bugs Low-balance alert on 46elks account
Duplicate send on retry Second billable, user-visible message $tries = 1 + ShouldBeUnique on OTP-class notifications
Queue exhaustion Delayed or dropped notifications NotificationFailed listener; queue depth monitoring

Instrument at both layers: Notification::fake() for unit assertions on channel selection, and Http::fake(['api.46elks.com/*' => ...]) for integration tests that catch payload-shape regressions when the package version bumps.

Ramp-up. Low. The package is a handful of files; a Laravel engineer can read the source and have the complete public API in fifteen minutes — which is also the most reliable way to learn what the README leaves implicit (config key names, whether from is required, error behavior). Plan for one engineer-day to first production send, plus non-engineering lead time for sender-ID approval and any market-by-market verification. The larger ramp-up cost sits outside the package: deciding retry semantics per notification, establishing a phone-normalization convention, and agreeing who owns the 46elks account operationally.

Bottom line. This is a defensible tactical dependency for one-way transactional SMS in a Laravel app where 46elks is already the committed provider. It is not appropriate where SMS is a revenue-critical path without a written fallback, where delivery confirmation is required at launch, or where the provider decision is still open. The gating item for a go/no-go is provider fit and account provisioning, not the package itself.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource