Looking to hire Laravel developers? Try LaraJobs

laravel-n8n-bridge maintained by oriceon

Description
Full-featured bidirectional Laravel 13+ bridge for n8n — DB-driven workflows, inbound/outbound tools, queue, circuit breaker, webhook auth.
Last update
2026/04/22 15:26 (dev-main)
License
Downloads
8

Comments
comments powered by Disqus

Laravel N8N Bridge

🔗 laravel-n8n-bridge

A full-featured, bidirectional Laravel 13+ bridge for n8n — DB-driven workflows, secured outbound webhook, secured inbound webhook receiver, circuit breakers, delivery statistics, tools exposed to n8n, DB queue system with live progress tracking, and multi-channel failure notifications.

Latest Version PHP Version Laravel License Tests


✨ What this package does

Unlike other n8n packages for Laravel — which are simple outbound HTTP clients — laravel-n8n-bridge is a complete bidirectional integration:

Feature Other packages laravel-n8n-bridge
Trigger workflow outbound
Outbound auth (token / bearer / HMAC-SHA256)
Outbound rate limiting (global + per-workflow)
Webhook mode (test / production / auto)
Inbound webhook receiver
Webhook auth (one key, all routes)
Rotatable API keys with grace period
Circuit Breaker per workflow
DB-driven workflows (not config files)
DB Queue with priority, batches, DLQ
Live progress tracking + broadcasting
Estimated completion time (EMA)
Tool system — GET/POST/PATCH/DELETE
OpenAPI schema auto-generated
Daily statistics with chart-ready data
Notifications Slack/Discord/Teams/Mail
Idempotency native
DLQ + replay
Artisan commands ✅ (20+)
Full Pest test suite ✅ (832 tests)

📋 Requirements

  • PHP 8.5+
  • Laravel 13.x
  • n8n (self-hosted or cloud)

🚀 Installation

composer require oriceon/laravel-n8n-bridge

⚙️ Configuration

If you want to publish the config or migrations, you can do so with:

php artisan vendor:publish --tag="n8n-bridge-config"
php artisan vendor:publish --tag="n8n-bridge-migrations"

Then, run the migrations

php artisan migrate

Set .env variables

# n8n instance (multiple supported via config)
N8N_BRIDGE_N8N_DEFAULT_API_BASE_URL=https://n8n.myapp.com
N8N_BRIDGE_N8N_DEFAULT_API_KEY=your-n8n-api-key
N8N_BRIDGE_N8N_DEFAULT_WEBHOOK_BASE_URL=https://n8n.myapp.com/webhook
# Optional: explicit test URL (null = auto-derived by replacing /webhook → /webhook-test)
N8N_BRIDGE_N8N_DEFAULT_WEBHOOK_TEST_BASE_URL=https://n8n.myapp.com/webhook-test

# Table prefix (default: n8n → n8n__workflows__lists etc.)
N8N_BRIDGE_TABLE_PREFIX=n8n

# Notifications
N8N_BRIDGE_NOTIFY_ENABLED=true
N8N_BRIDGE_NOTIFY_CHANNELS=slack,mail
N8N_BRIDGE_NOTIFY_SLACK_WEBHOOK=https://hooks.slack.com/services/xxx
N8N_BRIDGE_NOTIFY_DISCORD_WEBHOOK=https://discord.com/api/webhooks/xxx
N8N_BRIDGE_NOTIFY_MAIL_TO=ops@myapp.com
N8N_BRIDGE_NOTIFY_ERROR_RATE=20.0

# Outbound rate limiting (0 = unlimited)
N8N_BRIDGE_OUTBOUND_RATE_LIMIT=0

# Queue system
N8N_BRIDGE_QUEUE_DEFAULT=default
N8N_BRIDGE_QUEUE_DELETE_CHECKPOINTS=true
N8N_BRIDGE_QUEUE_DURATION_SAMPLES=50

🔑 Authentication

All /n8n/* routes require an X-N8N-Key header. One credential key works across all modules — inbound, tools, and queue progress. Multiple credentials can be attached to the same resource; any of their keys are accepted.

# Create a credential + key
php artisan n8n:credential:create "Production" --instance=default
# → outputs: n8br_sk_a3f9b2c1...

# In n8n: Personal → Credentials → Create credential → Header Auth
# Name:  X-N8N-Key
# Value: n8br_sk_a3f9b2c1...

# Attach to endpoints/tools (many-to-many)
php artisan n8n:credential:attach {id} --all
php artisan n8n:credential:attach {id} --inbound=invoice-paid --tool=invoices

See docs/credentials.md for rotation, IP whitelisting, grace periods, multi-credential setups, and detach commands.


📥 Inbound — receive data from n8n

1. Create an endpoint

php artisan n8n:endpoint:create invoice-paid \
  --handler="App\N8n\InvoicePaidHandler" \
  --queue=high

2. Write the handler

namespace App\N8n;

use Oriceon\N8nBridge\DTOs\N8nPayload;
use Oriceon\N8nBridge\Inbound\N8nInboundHandler;

final class InvoicePaidHandler extends N8nInboundHandler
{
    public function handle(N8nPayload $payload): void
    {
        $invoice = Invoice::findOrFail($payload->required('invoice_id'));
        $invoice->update([
            'status'  => 'paid',
            'paid_at' => $payload->getCarbon('paid_at'),
        ]);
    }

    public function rules(): array
    {
        return [
            'invoice_id' => 'required|integer',
            'paid_at'    => 'required|date',
        ];
    }
}

3. Configure in n8n

URL:    POST https://myapp.com/n8n/in/invoice-paid
Header: X-N8N-Key: n8br_sk_...
Header: X-N8N-Execution-Id: {{ $execution.id }}

Security pipeline

Every request passes through 6 layers automatically:

POST /n8n/in/{slug}
        │
        ▼  1. RateLimiter      → 429 if exceeded
        ▼  2. ApiKeyVerifier   → 401 if key invalid
        ▼  3. IpWhitelist      → 403 if IP not allowed
        ▼  4. HmacVerifier     → 401 if signature mismatch
        ▼  5. IdempotencyCheck → 200 skip if already processed
        ▼  6. PayloadStore     → persist delivery to DB
        ▼  ACK 202 + dispatch job to queue

See docs/inbound.md for HMAC, rate limits, IP whitelist, DLQ, and handler validation.


📤 Outbound — trigger n8n from Laravel

use Oriceon\N8nBridge\Facades\N8nBridge;

// By workflow name
N8nBridge::trigger('order-shipped', [
    'order_id'   => $order->id,
    'shipped_at' => now()->toIso8601String(),
]);

// Sync (waits for HTTP response)
N8nBridge::trigger($workflow, $payload, async: false);

Automatic from Eloquent models

use Oriceon\N8nBridge\Concerns\TriggersN8nOnEvents;

class Invoice extends Model
{
    use TriggersN8nOnEvents;

    protected array $n8nTriggers = [
        'created' => 'invoice-created',
        'updated' => [
            'workflow'  => 'invoice-status-changed',
            'only_when' => ['status', 'paid_at'],
        ],
    ];
}

Webhook mode (test vs production URL)

Each workflow has a webhook_mode that controls which n8n URL is called:

use Oriceon\N8nBridge\Enums\WebhookMode;

N8nWorkflow::find($id)->update([
    'webhook_mode' => WebhookMode::Auto,        // default — /webhook-test in dev, /webhook in prod
    // 'webhook_mode' => WebhookMode::Production, // always /webhook
    // 'webhook_mode' => WebhookMode::Test,        // always /webhook-test
]);

With Auto, the URL is selected based on APP_ENV: production/webhook, anything else → /webhook-test.

See docs/outbound.md for full details.

Outbound authentication

Protect your n8n webhooks with a per-workflow secret (AES-256 encrypted at rest):

use Oriceon\N8nBridge\Auth\WebhookAuthService;
use Oriceon\N8nBridge\Enums\WebhookAuthType;

N8nWorkflow::where('name', 'order-shipped')->update([
    'auth_type' => WebhookAuthType::HmacSha256, // or HeaderToken / Bearer
    'auth_key'  => WebhookAuthService::generateKey(),
]);

Auth headers are added automatically by both the outbound dispatcher and the queue worker.

Outbound rate limiting

Prevent flooding n8n with too many requests per minute:

N8N_BRIDGE_OUTBOUND_RATE_LIMIT=30   # global: 30 req/min (0 = unlimited)

Per-workflow override:

N8nWorkflow::where('name', 'bulk-sync')
    ->update(['rate_limit' => 10]);  // 10 req/min for this workflow

When the limit is exceeded: async triggers are re-dispatched after the window resets; sync triggers fail immediately; queue worker releases the job back to pending with a delay.

See docs/outbound.md for auth types, rate limiting, n8n credential setup, and the HMAC verification Code node.


🔧 Tool System — n8n calls Laravel

Define typed Laravel endpoints that n8n nodes call as an internal API.

php artisan make:n8n-tool GetInvoiceTool
final class GetInvoiceTool extends N8nToolHandler
{
    public function get(N8nToolRequest $request): N8nToolResponse
    {
        return N8nToolResponse::item(
            Invoice::findOrFail($request->required('id')),
            fn($i) => ['id' => $i->id, 'total' => $i->total, 'status' => $i->status]
        );
    }
}
GET  /n8n/tools/schema          → full OpenAPI 3 spec (import into n8n)
GET  /n8n/tools/{name}          → handler->get()
GET  /n8n/tools/{name}/{id}     → handler->getById()
POST /n8n/tools/{name}          → handler->post()
PATCH /n8n/tools/{name}/{id}    → handler->patch()
DELETE /n8n/tools/{name}/{id}   → handler->delete()

See docs/tools.md for filters, pagination, rate limiting, and schema definition.


📋 Queue System — async jobs with live progress

use Oriceon\N8nBridge\Enums\QueueJobPriority;use Oriceon\N8nBridge\Queue\QueueDispatcher;

$job = QueueDispatcher::workflow('invoice-processing')
    ->payload(['invoice_id' => $invoice->id])
    ->priority(QueueJobPriority::High)
    ->maxAttempts(5)
    ->idempotent("invoice-{$invoice->id}")
    ->dispatch();

n8n sends checkpoint progress back:

POST /n8n/queue/progress/{jobUuid}
{ "node": "send_email", "status": "completed", "progress_percent": 75 }

POST /n8n/queue/progress/{jobUuid}
{ "node": "__done__", "status": "completed" }

Real-time updates via Laravel Echo:

window.Echo.private(`n8n-job.${jobId}`)
    .listen('N8nQueueJobProgressUpdatedEvent', (e) => {
        updateTimeline(e.checkpoint);
        if (e.is_terminal) console.log('Done:', e.job_status);
    });

See docs/queue.md for full queue documentation — priorities, batches, DLQ, worker setup, Supervisor config, and estimated completion time.


🔄 Circuit Breaker

Closed ──(5 consecutive failures)──→ Open
  ↑                                       │
  │ (2× consecutive success) (60s cooldown)│
  └──── HalfOpen ←───────────────────────┘

See docs/circuit-breaker.md.


📊 Statistics

$overview = N8nBridge::stats()->overview();
// ['total_deliveries' => 14823, 'success_rate' => 98.4, 'avg_duration_ms' => 142]

$chart = N8nBridge::stats()
    ->forWorkflow($workflow)
    ->lastDays(30)
    ->toChartData();

See docs/statistics.md.


🔔 Notifications

Alerts sent automatically on DLQ, circuit breaker open, and high error rate:

N8N_BRIDGE_NOTIFY_CHANNELS=slack,discord,mail
N8N_BRIDGE_NOTIFY_SLACK_WEBHOOK=https://hooks.slack.com/services/xxx
N8N_BRIDGE_NOTIFY_MAIL_TO=ops@myapp.com

See docs/notifications.md.


🗄️ Database Tables

With the default n8n prefix:

Table Description
n8n__credentials__lists Credential identities (one per n8n instance)
n8n__api_keys__lists Rotatable API keys (many per credential)
n8n__endpoints__credentials Endpoint ↔ credential pivot (many-to-many)
n8n__tools__credentials Tool ↔ credential pivot (many-to-many)
n8n__workflows__lists Workflows synced from n8n
n8n__endpoints__lists Inbound endpoints
n8n__deliveries__lists Full delivery log
n8n__circuit_breakers__lists Per-workflow circuit breaker state
n8n__stats__lists Daily aggregated statistics
n8n__tools__lists Tool definitions
n8n__event_subscriptions__lists Laravel event → workflow mappings
n8n__queue__jobs DB queue jobs
n8n__queue__batches Batch grouping
n8n__queue__failures Per-attempt failure history
n8n__queue__checkpoints Live progress nodes from n8n

🛠️ Artisan Commands

# Webhook & endpoint management
php artisan n8n:credential:create "Production" --instance=default
php artisan n8n:credential:rotate {id} --grace=300
php artisan n8n:endpoint:create invoice-paid --handler="App\N8n\Handler"
php artisan n8n:endpoint:list
php artisan n8n:endpoint:rotate invoice-paid --grace=300

# Workflow sync
php artisan n8n:workflows:sync --instance=default
php artisan n8n:workflow:auth-setup "Workflow name" --type=header_token

# Testing
php artisan n8n:test-inbound invoice-paid --payload='{"invoice_id":42}'
php artisan n8n:test-inbound invoice-paid --dry-run

# DLQ
php artisan n8n:dlq:list
php artisan n8n:dlq:retry
php artisan n8n:dlq:retry {delivery-id}

# Queue
php artisan n8n:queue:work
php artisan n8n:queue:work --queue=critical --sleep=1
php artisan n8n:queue:status
php artisan n8n:queue:retry
php artisan n8n:queue:cancel {uuid}
php artisan n8n:queue:prune --days=30

# Stats & health
php artisan n8n:stats --last=30
php artisan n8n:health --instance=default

# Generators
php artisan make:n8n-tool GetInvoiceTool

🧪 Tests

composer test           # 846 tests (Unit + Feature + Architecture)
composer analyse        # PHPStan level 8

📚 Documentation

Guide Description
docs/credentials.md Credential keys, rotation, IP whitelist
docs/inbound.md Inbound handler, pipeline, HMAC, idempotency
docs/outbound.md Outbound triggers, Eloquent trait, event subscriptions, outbound auth, webhook mode
docs/tools.md Tool handlers, routing, OpenAPI schema
docs/queue.md DB queue, priorities, batches, DLQ, live progress
docs/circuit-breaker.md State machine, configuration
docs/statistics.md Stats aggregation, chart data
docs/notifications.md Alert channels, thresholds
docs/security.md Key hashing, HMAC, timing attacks
docs/multitenancy.md Multi-tenant setup
docs/n8n-setup.md Configuring n8n credentials and nodes
docs/testing.md Testing handlers, tools, and queue jobs
docs/upgrade.md Upgrade guide

📄 License

MIT — Copyright © 2026 Valentin Ivașcu