jeffersongoncalves/laravel-rewardful
Laravel package for integrating Rewardful affiliate and referral tracking into your app. Connect your SaaS to Rewardful, track referrals and commissions, and manage affiliate campaigns from Laravel with a simple, configurable API.
This is the initial 1.0.0 release of a Rewardful API client for Laravel, so the fastest path is to treat it as a thin, resource-oriented wrapper over the Rewardful REST API rather than a full affiliate-management system.
Minimal setup:
composer require <vendor>/laravel-rewardful
php artisan vendor:publish --tag="rewardful-config"
.env:
REWARDFUL_API_KEY=your-secret-key
REWARDFUL_API_URL=https://api.getrewardful.com/v1
use Rewardful\Facades\Rewardful;
$affiliates = Rewardful::affiliates()->all();
Where to look first:
config/rewardful.php for base URL, key, timeout, and any pagination defaults.src/Resources/ directory (or equivalent) — this is the map of the four supported domains: affiliates, referrals, commissions, affiliateLinks.First use case: resolving an affiliate or referral record when a customer signs up or a sale is recorded, then reading the resulting commissions for reporting. Start with a single read call (affiliates()->all() or affiliates()->find($id)) before wiring anything into checkout flows.
Inject the client, don't scatter the facade. Bind the client through the container in controllers, jobs, and listeners. Facades are convenient for tinker and one-off scripts, but constructor injection keeps the package swappable and testable:
public function __construct(private Rewardful $rewardful) {}
$affiliate = $this->rewardful->affiliates()->find($affiliateId);
Treat each resource as a paginated collection, not an array. List endpoints typically return a page of records plus metadata. Prefer the package's iterator or paginator helper if one exists; otherwise loop over pages explicitly and cap the loop. This matters most for commissions and referrals, which grow unbounded over time.
Sync, don't query live, on hot paths. The common production pattern is a scheduled job that pulls affiliates/commissions into local tables on an interval, with your application reading from the local copy:
// App\Jobs\SyncRewardfulCommissions
foreach ($this->rewardful->commissions()->all(['since' => $lastSyncedAt]) as $commission) {
Commission::updateOrCreate(['rewardful_id' => $commission->id], [...]);
}
Keep the raw rewardful_id as a unique key so reruns are idempotent. This also decouples your checkout flow from Rewardful's uptime and rate limits.
Use the resource objects, then map to your own DTOs. Don't leak package response objects into Blade views or API resources. Map into your own models/DTOs at the boundary. If the package ships DTOs, they are a reasonable stopping point for mapping but should not become your domain model.
Affiliate links are usually write-path, referrals/commissions are read-path. Creating an affiliate link tends to happen during onboarding (return the URL to the affiliate or store it against their profile); referrals and commissions are mostly read for dashboards, payout reports, and support tooling. Structure services along that split rather than one god-service over all four resources.
Wrap calls in your own service with retry/backoff. A small RewardfulService that wraps the package client gives you one place to add logging, timeouts, and retries (for 429/5xx) without touching call sites. Keep retries out of write paths unless the underlying endpoint is idempotent.
Testing: use Laravel's Http::fake() against the known API host, and assert the package sends the expected auth header and query parameters. Because this is a 1.0.0 release, pin the version in composer.json and add at least one integration-style test that exercises each of the four resources against a faked response shape.
.env/server config — never ship it to the front end. Double-check which key the package expects in the config before wiring it into a tracking snippet.commissions. Assert the total count after a sync and log when the fetched count equals the page size exactly — that's often a sign there's another page.^1.0 and review release notes before upgrading, especially around any pagination or DTO changes.How can I help you explore Laravel packages today?