Artisan commands
integrations:install
Interactive installer for a new (or updated) integration. Introspects the provider's credentialDataClass() and metadataDataClass() to figure out which fields to ask about, validates them against the provider's rules, runs the health check if the provider implements HasHealthCheck, and upserts the row in integrations.
php artisan integrations:install {provider} [--name=] [--credential=key=value ...] [--metadata=key=value ...] [--force]Arguments and options
| Argument / option | Description |
|---|---|
provider | The provider key registered in config/integrations.php (e.g. github). |
--name= | Friendly name for the row. Defaults to the provider's name(). |
--credential=key=value | Set a credential field non-interactively. Repeatable. |
--metadata=key=value | Set a metadata field non-interactively. Repeatable. |
--force | Skip the overwrite and failed-health-check confirmations. |
Interactive flow
php artisan integrations:install githubThe command prompts for every required field declared on the provider's credential / metadata Data class. Optional fields (nullable, or with a default) use their declared default unless you override them with --credential=name=value or --metadata=name=value. Field names matching /secret|token|key|password/i are prompted with masked input.
If an integration with the same provider + name already exists, the command confirms before overwriting its credentials and metadata. --force skips the confirmation.
Non-interactive flow
Pass every required field through flags and disable prompts:
php artisan integrations:install github \
--name="Acme GitHub" \
--credential=token=ghp_abc123 \
--metadata=owner=acme \
--metadata=repo=widgets \
--no-interaction --forceUnder --no-interaction, any missing required field fails the command before touching the database, so a half-configured row is never written. Malformed flag values (no = separator) are warned about and ignored; the subsequent validation pass surfaces the resulting missing fields.
Health check
If the provider implements HasHealthCheck, the command calls healthCheck() against the freshly saved row. On a pass, it records the success; on a fail (including thrown exceptions), it asks whether to keep the row for a later retry or roll it back. --force keeps the row without prompting.
Providers without a Data class
If credentialDataClass() / metadataDataClass() return null, the command falls back to the keys in credentialRules() / metadataRules(). It prompts only for fields whose rule contains the required token; others are skipped unless you set them via --credential / --metadata. Types and defaults come from the Data class when one is present; the rules are the source of truth for validation.
integrations:sync
Find overdue integrations and dispatch sync jobs.
php artisan integrations:syncFinds all active integrations where next_sync_at has passed and dispatches a SyncIntegration job for each. Add to your scheduler:
Schedule::command('integrations:sync')->everyMinute();integrations:list-failed-items
Show sync items that exhausted their retries and need operator attention.
php artisan integrations:list-failed-items
php artisan integrations:list-failed-items --integration=7 --since="2026-01-01"Prints a table from integration_sync_items (id, integration, event, external id, error, attempts, created). A failed item holds the cursor at it until it's resolved: retry the underlying job with php artisan queue:retry <uuid>, or skip it (below).
integrations:skip-sync-item
Mark a permanently-failed sync item as skipped so the cursor can advance past it.
php artisan integrations:skip-sync-item <id>Only failed items can be skipped. The command sets the row to skipped and dispatches FinaliseSyncRun so the run reconciles and the cursor catches up.
integrations:advance-cursor
Re-reconcile any sync runs for an integration that are still stuck in processing.
php artisan integrations:advance-cursor <integration>Dispatches FinaliseSyncRun for each unreconciled run. FinaliseSyncRun bails on its own if a run's items aren't all terminal yet, so this is always safe to run. Useful as a manual nudge if a finally callback was lost (e.g. a queue outage).
integrations:list
Show all integrations with health, last sync, and request counts.
php artisan integrations:listExample output:
+----------+----------+---------+---------------------+----------+-----------+
| Name | Provider | Health | Last Synced | Requests | Error Rate|
+----------+----------+---------+---------------------+----------+-----------+
| Prod ZD | zendesk | healthy | 2026-03-22 10:15:00 | 1,243 | 0.8% |
| GitHub | github | degraded| 2026-03-22 10:10:00 | 891 | 12.3% |
+----------+----------+---------+---------------------+----------+-----------+integrations:health
Detailed health report with error rates, response times, and top errors.
php artisan integrations:healthintegrations:test
Run HasHealthCheck on all supporting integrations.
php artisan integrations:testintegrations:stats
Show request counts, error rates, and cache hit ratios per integration.
php artisan integrations:statsintegrations:prune
Clean up old request and log records based on configured retention.
php artisan integrations:pruneAdd to your scheduler:
Schedule::command('integrations:prune')->daily();Configure retention in config/integrations.php:
'pruning' => [
'requests_days' => 90,
'logs_days' => 365,
'chunk_size' => 1000,
],integrations:recover-webhooks
Reset stale processing webhooks to pending and re-dispatch them.
php artisan integrations:recover-webhooksAdd to your scheduler:
Schedule::command('integrations:recover-webhooks')->hourly();A webhook is considered stale after webhook.processing_timeout seconds (default 30 minutes).
integrations:replay-webhook
Re-dispatch a stored webhook payload.
php artisan integrations:replay-webhook {webhookId}Reconstructs the request from stored data and re-dispatches it through handleWebhook().
make:integration-provider
Scaffold a new provider class. See Scaffolding Providers.
php artisan make:integration-provider {name} [--sync] [--webhooks] [--oauth] [--health-check] [--all]