> ## Documentation Index
> Fetch the complete documentation index at: https://docs.exowizz.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Understand how Exo resources work and what methods are available.

A Resource is the core building block of Exo. One Resource definition drives your API shape, trigger events, and webhook payload data.

## How resources work

When your Laravel app boots, Exo scans the configured resources directory and registers every Resource class it finds. For each Resource, Exo:

1. Creates API endpoints under `/exo-api/resources/{name}` for listing, creating, updating, and deleting records
2. Attaches model observers that emit `on_create`, `on_update`, and `on_delete`
3. Makes the resource available for webhook subscriptions

## Required methods

Every Resource must extend `Exowizz\Exo\Resource` and implement four methods:

```php theme={null}
use Exowizz\Exo\Resource;
use Illuminate\Database\Eloquent\Model;

class ContactResource extends Resource
{
    public function name(): string
    {
        return 'contact';
    }

    public function model(): string
    {
        return 'App\Models\Contact';
    }

    public function triggers(): array
    {
        return ['on_create', 'on_update', 'on_delete'];
    }

    public function transform(Model $model): array
    {
        return [
            'id' => $model->id,
            'name' => $model->name,
            'email' => $model->email,
        ];
    }
}
```

| Method        | What it does                                                            |
| ------------- | ----------------------------------------------------------------------- |
| `name()`      | A unique identifier used in API URLs, e.g. `/exo-api/resources/contact` |
| `model()`     | The fully-qualified Eloquent model class to expose                      |
| `triggers()`  | Which events fire webhooks: `on_create`, `on_update`, `on_delete`       |
| `transform()` | Converts a model instance into the array returned by the API            |

## Optional methods by level

Start with the required four methods. Add optional methods as your integration grows:

| Method                  | Purpose                                              | Default                        |
| ----------------------- | ---------------------------------------------------- | ------------------------------ |
| `createRules()`         | Validation rules for create requests                 | `[]`                           |
| `updateRules()`         | Validation rules for update requests                 | `[]`                           |
| `supportsCreate()`      | Whether creation is allowed                          | `true`                         |
| `supportsUpdate()`      | Whether updates are allowed                          | `true`                         |
| `supportsDelete()`      | Whether deletion is allowed                          | `true`                         |
| `ownerColumn()`         | Scope records to a user                              | `null` (admin-only)            |
| `ownerIsRelationship()` | Whether the owner column is a relationship           | `false`                        |
| `searchableColumns()`   | Columns searchable via `?search=`                    | `[]` (disabled)                |
| `applySearch()`         | Custom search query logic                            | OR LIKE on `searchableColumns` |
| `baseQuery()`           | Starting query (add scopes, eager loads)             | `Model::query()`               |
| `performCreate()`       | Custom create logic                                  | `Model::create()`              |
| `performUpdate()`       | Custom update logic                                  | `$model->update()`             |
| `webhookQueue()`        | Queue name for this resource's webhooks              | `config('exo.queue')`          |
| `webhookMaxAttempts()`  | Override delivery attempt limit for this resource    | `null`                         |
| `webhookBackoff()`      | Override delivery backoff schedule for this resource | `null`                         |
| `recordAllEvents()`     | Persist events even without matching subscriptions   | `false`                        |
| `isAdmin()`             | Whether the current user is an admin                 | Uses `config('exo.is_admin')`  |

## Trigger values

The built-in observer emits only these trigger names:

* `on_create`
* `on_update`
* `on_delete`

## Creating resources

The fastest way to create a resource is with the Artisan command:

```bash theme={null}
php artisan exo:resource ContactResource --model="App\Models\Contact" --triggers=on_create,on_update,on_delete
```

This generates a file at `app/Exo/Resources/ContactResource.php` with all methods stubbed out.

You can also run the command without arguments for an interactive experience:

```bash theme={null}
php artisan exo:resource
```

<Note>
  Exo auto-discovers resources from `config('exo.resources_path')` (default: `app/Exo/Resources`) using `config('exo.resources_namespace')` (default: `App\\Exo\\Resources\\`).
</Note>
