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

Laravel Rewardful Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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:

  1. Install the package and publish its config:
    composer require <vendor>/laravel-rewardful
    php artisan vendor:publish --tag="rewardful-config"
    
  2. Add your Rewardful API secret (and, if supported by the package, your public/API mode) to .env:
    REWARDFUL_API_KEY=your-secret-key
    REWARDFUL_API_URL=https://api.getrewardful.com/v1
    
  3. Confirm the service provider and facade are auto-discovered, then make a first read call to verify credentials:
    use Rewardful\Facades\Rewardful;
    
    $affiliates = Rewardful::affiliates()->all();
    

Where to look first:

  • config/rewardful.php for base URL, key, timeout, and any pagination defaults.
  • The package's src/Resources/ directory (or equivalent) — this is the map of the four supported domains: affiliates, referrals, commissions, affiliateLinks.
  • The README's method signatures for each resource; with a 1.0.0 release, the resource methods are the real API surface, not the config.

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.

Implementation Patterns

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.

Gotchas and Tips

  • Secret vs. public key. Rewardful distinguishes between keys used server-side and any public identifier used in browser snippets. Only the secret key belongs in .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.
  • Test/live mode confusion. If the package supports a mode flag, make sure it's driven from config and not hardcoded; accidentally pointing staging at live affiliate data is the classic failure here. Verify the base URL resolves to the environment you expect by logging the outgoing request once.
  • Pagination is the usual bug source. Silent truncation at the default page size is easy to miss on 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.
  • Rate limits and 429s. Don't retry in a tight loop. Use exponential backoff and keep scheduled sync windows conservative; a backfill over a large commission history will hit limits quickly. Add jitter if you run multiple workers.
  • Timestamps and timezones. Commission and referral dates from the API may be UTC or include offsets. Normalize to UTC on ingest and convert only at the presentation layer; otherwise your "this month" payout reports will drift.
  • Money as integers or strings, not floats. Commission amounts should be stored in the currency's smallest unit or as a decimal string. Float arithmetic on payouts will eventually produce a one-cent discrepancy someone has to reconcile manually.
  • Error handling is on you. Expect the package to throw on non-2xx responses. Wrap calls in try/catch at service boundaries, convert to your own exception types, and make sure a Rewardful outage degrades gracefully (queued retry, cached data) rather than breaking checkout. Do not let a failed affiliate lookup block a customer's purchase.
  • Webhooks are not implied by this release. The 1.0.0 notes list four read/write resources only. If you need real-time commission events, plan to either poll or implement webhook handling yourself; confirm against the source before assuming any signature verification helper exists.
  • Extension points: the client's HTTP layer (Guzzle options, base URI, timeout) is usually the right place to customize — set timeouts via config rather than editing vendor code. If the package exposes a macroable client or a container binding, prefer rebinding the client over forking.
  • Pin and read the changelog. With a fresh 1.0.0, resource method names and response shapes are the most likely things to shift in 1.1. Lock to ^1.0 and review release notes before upgrading, especially around any pagination or DTO changes.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle