---
title: "The Campaigns facade — Campaigns for Laravel | Roundly"
description: "Everything through one facade — create, prepare, start, cancel, find, all, a per-campaign handle, settings() and fake()."
url: https://roundly-consulting.com/open-source/docs/campaigns-for-laravel/facade
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Campaigns for Laravel](https://roundly-consulting.com/open-source/docs/campaigns-for-laravel.md)

# The Campaigns facade

The Campaigns facade over RoundlyConsulting\\Campaigns\\CampaignManager is the package’s public API and the recommended way in. It creates and sends campaigns, looks them up, and hands you a handle scoped to one campaign:

```php
use RoundlyConsulting\Campaigns\Facades\Campaigns;

$campaign = Campaigns::create('Spring sale', '<p>50% off</p>')->to($subscribers)->prepare();

Campaigns::start($campaign->uuid);        // only a prepared (Pending) campaign starts
Campaigns::find($campaign->uuid);         // ?Campaign — live progress while it sends
Campaigns::findOrFail($uuid);             // Campaign, or CampaignNotFound
Campaigns::all(offset: 0, limit: 25);     // Collection<int, Campaign>, in creation order
Campaigns::cancel($uuid);                 // Campaign — one that already ended is left as it is

Campaigns::campaign($uuid)->progress()->percentage();   // one campaign, through its handle
Campaigns::settings()->fromAddress();                   // the effective send defaults
```

## Every method

| Method | Returns | Purpose |
| --- | --- | --- |
| `create(string $subject, string $content)` | `PendingCampaign` | Fluent builder — from, to, onlyVerified, viaContactType, uuid, subject, content, prepare, dispatch. |
| `prepare(Campaign $campaign, iterable $recipients = [])` | `Campaign` | Store a campaign built from the value object with its recipients, and leave it Pending. A uuid that is taken throws CampaignAlreadyExists. |
| `start(Campaign\|string $campaign)` | `Campaign` | Start sending a Pending campaign; anything else throws InvalidCampaignTransition. |
| `cancel(Campaign\|string $campaign)` | `Campaign` | Cancel a campaign and its batch; one that already ended comes back unchanged. |
| `find(string $uuid)` | `?Campaign` | Look a campaign up, with live progress while it sends; null when unknown. |
| `findOrFail(string $uuid)` | `Campaign` | Look a campaign up or throw CampaignNotFound. |
| `all(int $offset = 0, int $limit = 10)` | `Collection<int, Campaign>` | A page of campaigns in creation order. |
| `campaign(Campaign\|string $campaign)` | `CampaignHandle` | One campaign — see the handle below. |
| `settings()` | `CampaignSettings` | The effective send defaults: fromName(), fromAddress(), notificationChannel(), sendingQueue(), onlyVerifiedRecipients(), defaultRecipientContactType(). |
| `fake()` | `CampaignsFake` | Swap in the recording fake — see Testing. |

## One campaign: the handle

Campaigns::campaign() takes a Campaign or a uuid and returns a CampaignHandle scoped to that campaign — an unknown uuid throws CampaignNotFound:

```php
use RoundlyConsulting\Campaigns\Facades\Campaigns;

$campaign = Campaigns::campaign($uuid);   // throws CampaignNotFound for an unknown uuid

$campaign->progress()->percentage();      // share delivered so far: 42.5
$campaign->progress()->failed;            // deliveries that failed
$campaign->progress()->remaining();       // recipients with no outcome yet
$campaign->recipients();                  // Collection<CampaignRecipient>, in the order added
$campaign->recipients(offset: 100, limit: 50);
$campaign->recipient($recipientUuid);     // one recipient of THIS campaign
$campaign->batch();                       // the Illuminate\Bus\Batch, or null
$campaign->start();
$campaign->cancel();                      // a campaign that already ended is left as it is
```

| Method | Returns | Purpose |
| --- | --- | --- |
| `uuid()` | `string` | The campaign’s uuid. |
| `get()` | `Campaign` | The campaign as stored now, with live progress. |
| `progress()` | `CampaignProgress` | Live progress — read from the recipients and the batch while Pending or Processing. |
| `recipients(int $offset = 0, ?int $limit = null)` | `Collection<int, CampaignRecipient>` | Recipients in the order they were added; a null limit returns them all. |
| `recipient(CampaignRecipient\|string $recipient)` | `CampaignRecipient` | One recipient of this campaign; RecipientNotFound otherwise. |
| `batch()` | `?Batch` | The Laravel job batch — null before prepare() and under the fake. |
| `start()` | `Campaign` | Same as Campaigns::start(). |
| `cancel()` | `Campaign` | Same as Campaigns::cancel(). |
| `markProcessed(CampaignRecipient $recipient)` | `CampaignRecipient` | Record a delivery and fire RecipientProcessed. |
| `markFailed(CampaignRecipient $recipient, string $error)` | `CampaignRecipient` | Record a failure with its message and fire RecipientFailed. |

The handle refuses recipients of other campaigns: recipient(), markProcessed() and markFailed() throw RecipientNotFound. markProcessed() and markFailed() are what delivery jobs call — see Custom delivery jobs.

Want the same API without static calls? See DI and actions.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/campaigns-for-laravel.md)
