This project integrates Laravel with n8n to provide an asynchronous API service for AI-powered ad script refactoring. It demonstrates a robust architecture for delegating AI processing tasks from a Laravel application to n8n workflows, ensuring proper error handling and idempotent operations.
sequenceDiagram
participant Client as API Consumer
participant LaravelAPI as Laravel API (/api/ad-scripts)
participant LaravelQueue as Laravel Queue (Redis)
participant N8nTriggerJob as TriggerN8nWorkflow Job
participant N8nWorkflow as n8n Workflow
participant OpenAI as AI Agent (GPT-4o)
participant LaravelCallback as Laravel Callback (/api/ad-scripts/{id}/result)
Client->>+LaravelAPI: POST /api/ad-scripts (JSON: ref_script, outcome_desc)
LaravelAPI->>LaravelAPI: Validate, Create AdScriptTask (status: PENDING)
LaravelAPI->>LaravelQueue: Dispatch N8nTriggerJob
LaravelAPI-->>-Client: HTTP 202 Accepted (task_id, status)
LaravelQueue->>+N8nTriggerJob: Process Job
N8nTriggerJob->>N8nTriggerJob: Update Task Status (PROCESSING)
N8nTriggerJob->>+N8nWorkflow: POST /webhook-test/ad-script-refactor-openrouter (task_id, script, outcome, AUTH)
N8nWorkflow-->>-N8nTriggerJob: HTTP 200 OK (Webhook received)
N8nWorkflow->>+OpenAI: Analyze & Generate Script
OpenAI-->>-N8nWorkflow: new_script, analysis
alt Success
N8nWorkflow->>+LaravelCallback: POST /api/ad-scripts/{id}/result (JSON: new_script, analysis, HMAC_AUTH)
LaravelCallback->>LaravelCallback: Verify HMAC, Validate, Update AdScriptTask (status: COMPLETED)
LaravelCallback-->>-N8nWorkflow: HTTP 200 OK
else AI/Workflow Error
N8nWorkflow->>+LaravelCallback: POST /api/ad-scripts/{id}/result (JSON: error_details, HMAC_AUTH)
LaravelCallback->>LaravelCallback: Verify HMAC, Validate, Update AdScriptTask (status: FAILED)
LaravelCallback-->>-N8nWorkflow: HTTP 200 OK
end
- Docker and Docker Compose
make(optional, for using Makefile targets)
-
Clone the repository
git clone <repository-url> cd laravel-n8n-ad-refactor
-
Environment Setup
cp .env.example .env
Edit
.envand set the following required variables:APP_KEY(generate usingphp artisan key:generate)- Database credentials (or keep defaults for Docker setup)
N8N_TRIGGER_WEBHOOK_URL(URL to n8n webhook)N8N_AUTH_HEADER_KEY(header name for authenticating to n8n)N8N_AUTH_HEADER_VALUE(secret value for authenticating to n8n)N8N_CALLBACK_HMAC_SECRET(shared secret for verifying callbacks from n8n)
-
Start the Services
make dev-setup
Or manually with Docker:
docker-compose up -d docker-compose exec app composer install docker-compose exec app php artisan migrate
-
n8n Workflow Setup
- Access n8n at http://localhost:5678
- Import the workflow from
n8n/workflows/ad-script-refactor-workflow.json - Configure OpenAI credentials in n8n
- Ensure the trigger webhook uses header authentication matching your
N8N_AUTH_HEADER_KEYandN8N_AUTH_HEADER_VALUE - Ensure the callback HTTP request computes an HMAC signature using
N8N_CALLBACK_HMAC_SECRET - For detailed n8n setup instructions, see n8n/README.md
- Laravel: http://localhost:8000
- n8n: http://localhost:5678
curl -X POST http://localhost:8000/api/ad-scripts \
-H "Content-Type: application/json" \
-d '{"reference_script": "function oldAd() { var count = 0; if(count == 0) { alert(\"First visit!\"); } }", "outcome_description": "Modernize to ES6+ with const/let and template literals"}'Response (202 Accepted):
{
"data": {
"id": "uuid-string",
"status": "pending",
"reference_script": "function oldAd() { var count = 0; if(count == 0) { alert(\"First visit!\"); } }",
"outcome_description": "Modernize to ES6+ with const/let and template literals"
}
}curl -X GET http://localhost:8000/api/ad-scripts/{task_id}Response (200 OK):
{
"data": {
"id": "uuid-string",
"status": "completed",
"reference_script": "function oldAd() { var count = 0; if(count == 0) { alert(\"First visit!\"); } }",
"outcome_description": "Modernize to ES6+ with const/let and template literals",
"new_script": "function oldAd() { let count = 0; if(count === 0) { alert(`First visit!`); } }",
"analysis": "Modernized using let instead of var, strict equality, and template literals."
}
}make testOr for test coverage:
make test-coverage- PHP CS Fixer:
make cs-fix - PHPStan:
make analyse - Husky Git Hooks: Automatically validate commits
- Asynchronous Processing: Tasks are processed in the background using Laravel queues
- Idempotent Operations: Callback endpoints are designed to handle duplicate requests
- Error Handling: Comprehensive error handling and reporting
- Security: HMAC signature verification for callbacks
- Rate Limiting: API endpoints are rate-limited to prevent abuse
- "5 Lines or Less": Methods are kept small and focused for readability
- Interface-based Design: Components are decoupled through interfaces
- Defensive Programming: Comprehensive validation and error handling
- Test-Driven Development: High test coverage for core functionality
MIT
This project uses a programmatic Postman collection and Newman for automated API testing.
- Ensure your Laravel app is running at
http://localhost:8000. - Install Newman globally if you haven't:
yarn global add newman newman-reporter-htmlextra
- Run the API tests:
yarn test:api
- This uses
postman/Ad_Script_Refactor_API.postman_collection.jsonandpostman/local_dev.postman_environment.json. - An HTML report will be generated at
postman/report.html.
- This uses
- Use the
test:api:ciscript or run Newman directly with the CI environment file:yarn test:api:ci
- This uses
postman/ci.postman_environment.json(secrets should be injected at runtime). - A JUnit XML report will be generated at
postman/junit_report.xml.
- This uses
postman/local_dev.postman_environment.json: For local development/testing.postman/ci.postman_environment.json: For CI/CD pipelines (use secret injection for sensitive values).
- Edit
postman/Ad_Script_Refactor_API.postman_collection.jsondirectly (code-first approach). - See the Postman Collection Format v2.1.0 docs for structure and scripting options.