# Automation without Flows

Source: https://docs.qiick.io/externa/automation-without-flows

Externa will **not** ship a visual Flow / no-code automation canvas. Operators automate with **Laravel** (listeners, jobs, schedule) and **outbound webhooks**. This page is the Directus-migrant map.

> **Related**
> [Extending](https://docs.qiick.io/externa/extending) · [Outbound webhooks](https://docs.qiick.io/externa/webhooks) · [Operations](https://docs.qiick.io/externa/operations) · [Queues & scheduler](https://docs.qiick.io/externa/operations) · [Scheduled publish](https://docs.qiick.io/externa/content-versioning) · [Rebuild / CDN purge](https://docs.qiick.io/externa/webhook-rebuild-purge)

## Choose a tool

| Need                                                         | Prefer                                     | Why                                                                          |
| ------------------------------------------------------------ | ------------------------------------------ | ---------------------------------------------------------------------------- |
| React inside the same app (side effects, sync another table) | **Eloquent model hook** or `Event::listen` | Same request / same deploy; full model access                                |
| Slow / unreliable / external HTTP                            | **Queued Job**                             | Retries, Horizon, isolation from the admin request                           |
| Cron / recurring                                             | **`routes/console.php` Schedule**          | Already runs `collections:process-schedules`, cleanups, sync                 |
| Agency / Make / n8n / static rebuild                         | **Outbound webhook**                       | Signed HTTP; no custom PHP on the CMS host                                   |
| “Publish at 09:00” / unpublish                               | **Built-in scheduled publish**             | `publish_at` / `unpublish_at` + `collections:process-schedules` — not a Flow |

**Non-goal:** a drag-and-drop Flow builder. Fork or wrap Externa if you need one.

## Out of the box

- **Outbound webhooks** — `item.*`, `collection.*`, `file.*`, `ping` via `OutboundWebhookDispatcher` / `DeliverOutboundWebhookJob` ([catalog](https://docs.qiick.io/externa/webhooks)).
- **Scheduled publish** — versioned items; admin UI + every-minute schedule.
- **AI / import jobs** — e.g. `ImportCollectionJob` on the queue.

For “when item updates → Slack / rebuild / CRM”, start with [webhooks](https://docs.qiick.io/externa/webhooks) before writing PHP.

## Skeleton: model `saved` listener

Core emits webhooks from writers (`CollectionItemValuesWriter`, `CollectionItemPublisher`), not a dedicated `ItemUpdated` domain event. For in-process automation, observe the model (or listen after you define your own event):

```php
// app/Providers/AppServiceProvider.php (boot)
use App\Models\CollectionItem;

CollectionItem::saved(function (CollectionItem $item): void {
    if ($item->wasRecentlyCreated) {
        return; // or handle create separately
    }

    // Fast, safe work only — queue anything slow:
    \App\Jobs\SyncItemToLegacyCrm::dispatch($item->id);
});
```

Or a class-based listener on a **custom** event you fire from an observer — same pattern as Laravel docs. Keep CMS upgrades clean: put custom code in `app/` (or a package), not in vendor.

## Skeleton: queued job

```php
<?php

namespace App\Jobs;

use App\Models\CollectionItem;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class SyncItemToLegacyCrm implements ShouldQueue
{
    use Queueable;

    public function __construct(public int $itemId) {}

    public function handle(): void
    {
        $item = CollectionItem::query()->find($this->itemId);
        if ($item === null) {
            return;
        }

        // HTTP / SDK call…
    }
}
```

Require a worker (`queue:listen` / Horizon) — see [Operations](https://docs.qiick.io/externa/operations). Outbound webhook delivery already uses `DeliverOutboundWebhookJob` the same way.

## Skeleton: schedule

`routes/console.php` already schedules Externa maintenance. Add your own command next to it:

```php
use Illuminate\Support\Facades\Schedule;

Schedule::command('collections:process-schedules')->everyMinute();

// Your nightly digest, etc.
Schedule::command('app:send-editorial-digest')->dailyAt('07:30');
```

Production: cron → `php artisan schedule:run` every minute (or Laravel’s scheduler systemd unit).

## Webhooks instead of Flows

Point Project settings → Webhook URL at Make / n8n / Zapier / your API. Filter on `type` (`item.updated`, `item.published`, …). Verify `X-Externa-Signature`. Recipes: [Webhooks](https://docs.qiick.io/externa/webhooks) · [Rebuild / purge](https://docs.qiick.io/externa/webhook-rebuild-purge).

## vs Directus Flows (cheat sheet)

| Directus Flow idea  | Externa                                      |
| ------------------- | -------------------------------------------- |
| Filter → webhook    | Outbound webhook + Make/n8n filter on `type` |
| Filter → run script | Job / model hook in `app/`                   |
| Schedule trigger    | `Schedule::` in `routes/console.php`         |
| Publish later       | Built-in `publish_at` / `unpublish_at`       |
| Nested Flow UI      | Not provided — code or external automation   |
