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 Demio Laravel Package

jeffersongoncalves/laravel-demio

Laravel Demio is a clean integration for the Demio webinar platform, providing a fluent wrapper around the Demio API to create and manage webinars, register participants, track attendance, and automate event workflows directly from your Laravel application.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require the package, then publish its config:

php artisan vendor:publish --tag=demio-config

Add credentials to .env (never commit them) and mirror them in config/demio.php:

DEMIO_API_KEY=...
DEMIO_API_SECRET=...
DEMIO_BASE_URL=https://my.demio.com/api/v1
DEMIO_TIMEOUT=10

Where to look first: config/demio.php for the four knobs, then the DemioClient class itself — at 1.0.0 there is no facade, no service provider documented behaviour beyond config merging, and no README-level docs for response shapes. Read the source of events(), eventDate(), and register() before wiring them into anything, because the return types (array vs. collection vs. response object) are the single biggest unknown you'll hit.

First use case: a connectivity/correctness smoke test from Tinker before building anything:

php artisan tinker
>>> app(\Vendor\Demio\DemioClient::class)->ping();

If ping() returns cleanly you've proven the key, secret, base URL, and outbound TLS all work. That's your fastest way to isolate "credentials wrong" from "code wrong" for the rest of the project. From there, the canonical first feature is: events() to populate a select list → event($id) for detail → eventDate($id, $dateId) for the specific session you want people to register against → register() for signups → participants() for the attendee report.

Implementation Patterns

Inject the client, don't new it. Resolve it from the container in constructors so it's swappable in tests. If the package doesn't register a singleton binding, add one in your own AppServiceProvider:

$this->app->singleton(DemioClient::class, fn () => new DemioClient(config('demio')));

Wrap it in a thin application service. This is the pattern that pays off most. Your controllers and jobs should never touch DemioClient directly — put a DemioService in front of it that owns caching, retries, and error translation:

class DemioService
{
    public function __construct(private DemioClient $client) {}

    public function upcomingEvents(): array
    {
        return Cache::remember('demio.events', now()->addMinutes(10), fn () => $this->client->events());
    }

    public function registerAttendee(int $dateId, array $attendee): array
    {
        return $this->client->register($dateId, $attendee);
    }
}

Cache the read-only lookups. Events and event dates change rarely; fetching them on every page render is the classic first mistake. events(), event(), and eventDate() are cache candidates. participants() is not — it's live data and is usually the most expensive call.

Push participants() into a queued job. Attendee lists for large webinars can be slow and can blow past your timeout. Fetch them in a job, store into your own table, and render from there. This also gives you a natural retry boundary.

Model the registration form yourself. register() takes attendee data; map your validated FormRequest payload into exactly the fields Demio expects and keep that mapping in one place. Demio is strict about what it receives, and a missing custom field will fail silently in your logs rather than throwing.

Handle DemioAuthenticationException distinctly. It's the only typed failure the package gives you, and it is almost always a deployment problem, not a user problem:

try {
    $service->upcomingEvents();
} catch (DemioAuthenticationException $e) {
    report($e);
    Log::critical('Demio credentials rejected — check DEMIO_API_KEY/SECRET');
    return collect();
}

Testing. If the client is built on Laravel's Http client, Http::fake() will intercept everything and let you assert outgoing URLs and payloads — verify this early by faking a 401 and confirming the exception fires. Otherwise, bind a stub DemioClient into the container in your test case.

Gotchas and Tips

  • Only 401 is mapped. 400s (validation), 404s (bad event ID), 429s (rate limit), and 500s are not documented as wrapped. Inspect what actually comes back on a failure before assuming you'll get an exception — you may get an error payload you're treating as success. Add your own status check in the service layer.
  • timeout units and magnitude. It's almost certainly seconds, but the default is not stated. ping() is a fine test at 5–10s; participants() for a large event may not be. Raise the timeout for that call specifically rather than globally.
  • No retry/backoff. Rate limits and transient 5xx are your responsibility. Http::retry() in a wrapper, or a queued job with $backoff, is the cheap fix.
  • base_url is your escape hatch. Point it at a proxy, a mock server, or a recording of real responses for integration tests. Don't hardcode Demio URLs anywhere in your code.
  • Pagination is undocumented. events() and participants() may return a truncated first page. Before trusting a participant export, compare a count against the Demio UI. If it's paginated, you'll need to loop the client yourself since there are no cursor helpers.
  • Container binding is not guaranteed. If app(DemioClient::class) fails to resolve, it needs constructor arguments that aren't auto-wirable from config — bind it yourself as shown above.
  • Config caching. After changing config/demio.php or the env vars in production, run php artisan config:cache (or config:clear). Stale config cache is the number one cause of "it works locally" auth failures.
  • No webhooks or events. Everything is pull-based. If you need registration-triggered behaviour (welcome email, CRM sync), you either poll participants() on a schedule or keep the trigger on your side at the point you call register().
  • Extension points. The client is a plain class, so subclassing and overriding methods is the simplest way to add retry or logging without forking. Alternatively decorate it behind an interface — better if you expect to swap or mock it later. Avoid editing the vendor directory.
  • Pin to ^1.0. This is a fresh initial release with a thin API surface; expect method signatures and response shapes to shift in minor releases. Read the changelog before every composer update.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings