--- description: RESTful API design, routing patterns, webhooks, and HTTP communication globs: routes/*.php, app/Http/Controllers/**/*.php, app/Http/Resources/*.php, app/Http/Requests/*.php alwaysApply: false --- # Coolify API & Routing Architecture ## Routing Structure Coolify implements **multi-layered routing** with web interfaces, RESTful APIs, webhook endpoints, and real-time communication channels. ## Route Files ### Core Route Definitions - **[routes/web.php](mdc:routes/web.php)** - Web application routes (21KB, 362 lines) - **[routes/api.php](mdc:routes/api.php)** - RESTful API endpoints (13KB, 185 lines) - **[routes/webhooks.php](mdc:routes/webhooks.php)** - Webhook receivers (815B, 22 lines) - **[routes/channels.php](mdc:routes/channels.php)** - WebSocket channel definitions (829B, 33 lines) - **[routes/console.php](mdc:routes/console.php)** - Artisan command routes (592B, 20 lines) ## Web Application Routing ### Authentication Routes ```php // Laravel Fortify authentication Route::middleware('guest')->group(function () { Route::get('/login', [AuthController::class, 'login']); Route::get('/register', [AuthController::class, 'register']); Route::get('/forgot-password', [AuthController::class, 'forgotPassword']); }); ``` ### Dashboard & Core Features ```php // Main application routes Route::middleware(['auth', 'verified'])->group(function () { Route::get('/dashboard', Dashboard::class)->name('dashboard'); Route::get('/projects', ProjectIndex::class)->name('projects'); Route::get('/servers', ServerIndex::class)->name('servers'); Route::get('/teams', TeamIndex::class)->name('teams'); }); ``` ### Resource Management Routes ```php // Server management Route::prefix('servers')->group(function () { Route::get('/{server}', ServerShow::class)->name('server.show'); Route::get('/{server}/edit', ServerEdit::class)->name('server.edit'); Route::get('/{server}/logs', ServerLogs::class)->name('server.logs'); }); // Application management Route::prefix('applications')->group(function () { Route::get('/{application}', ApplicationShow::class)->name('application.show'); Route::get('/{application}/deployments', ApplicationDeployments::class); Route::get('/{application}/environment-variables', ApplicationEnvironmentVariables::class); Route::get('/{application}/logs', ApplicationLogs::class); }); ``` ## RESTful API Architecture ### API Versioning ```php // API route structure Route::prefix('v1')->group(function () { // Application endpoints Route::apiResource('applications', ApplicationController::class); Route::apiResource('servers', ServerController::class); Route::apiResource('teams', TeamController::class); }); ``` ### Authentication & Authorization ```php // Sanctum API authentication Route::middleware('auth:sanctum')->group(function () { Route::get('/user', function (Request $request) { return $request->user(); }); // Team-scoped resources Route::middleware('team.access')->group(function () { Route::apiResource('applications', ApplicationController::class); }); }); ``` ### Application Management API ```php // Application CRUD operations Route::prefix('applications')->group(function () { Route::get('/', [ApplicationController::class, 'index']); Route::post('/', [ApplicationController::class, 'store']); Route::get('/{application}', [ApplicationController::class, 'show']); Route::patch('/{application}', [ApplicationController::class, 'update']); Route::delete('/{application}', [ApplicationController::class, 'destroy']); // Deployment operations Route::post('/{application}/deploy', [ApplicationController::class, 'deploy']); Route::post('/{application}/restart', [ApplicationController::class, 'restart']); Route::post('/{application}/stop', [ApplicationController::class, 'stop']); Route::get('/{application}/logs', [ApplicationController::class, 'logs']); }); ``` ### Server Management API ```php // Server operations Route::prefix('servers')->group(function () { Route::get('/', [ServerController::class, 'index']); Route::post('/', [ServerController::class, 'store']); Route::get('/{server}', [ServerController::class, 'show']); Route::patch('/{server}', [ServerController::class, 'update']); Route::delete('/{server}', [ServerController::class, 'destroy']); // Server actions Route::post('/{server}/validate', [ServerController::class, 'validate']); Route::get('/{server}/usage', [ServerController::class, 'usage']); Route::post('/{server}/cleanup', [ServerController::class, 'cleanup']); }); ``` ### Database Management API ```php // Database operations Route::prefix('databases')->group(function () { Route::get('/', [DatabaseController::class, 'index']); Route::post('/', [DatabaseController::class, 'store']); Route::get('/{database}', [DatabaseController::class, 'show']); Route::patch('/{database}', [DatabaseController::class, 'update']); Route::delete('/{database}', [DatabaseController::class, 'destroy']); // Database actions Route::post('/{database}/backup', [DatabaseController::class, 'backup']); Route::post('/{database}/restore', [DatabaseController::class, 'restore']); Route::get('/{database}/logs', [DatabaseController::class, 'logs']); }); ``` ## Webhook Architecture ### Git Integration Webhooks ```php // GitHub webhook endpoints Route::post('/webhooks/github/{application}', [GitHubWebhookController::class, 'handle']) ->name('webhooks.github'); // GitLab webhook endpoints Route::post('/webhooks/gitlab/{application}', [GitLabWebhookController::class, 'handle']) ->name('webhooks.gitlab'); // Generic Git webhooks Route::post('/webhooks/git/{application}', [GitWebhookController::class, 'handle']) ->name('webhooks.git'); ``` ### Deployment Webhooks ```php // Deployment status webhooks Route::post('/webhooks/deployment/{deployment}/success', [DeploymentWebhookController::class, 'success']); Route::post('/webhooks/deployment/{deployment}/failure', [DeploymentWebhookController::class, 'failure']); Route::post('/webhooks/deployment/{deployment}/progress', [DeploymentWebhookController::class, 'progress']); ``` ### Third-Party Integration Webhooks ```php // Monitoring webhooks Route::post('/webhooks/monitoring/{server}', [MonitoringWebhookController::class, 'handle']); // Backup status webhooks Route::post('/webhooks/backup/{backup}', [BackupWebhookController::class, 'handle']); // SSL certificate webhooks Route::post('/webhooks/ssl/{certificate}', [SslWebhookController::class, 'handle']); ``` ## WebSocket Channel Definitions ### Real-Time Channels ```php // Private channels for team members Broadcast::channel('team.{teamId}', function ($user, $teamId) { return $user->teams->contains('id', $teamId); }); // Application deployment channels Broadcast::channel('application.{applicationId}', function ($user, $applicationId) { return $user->hasAccessToApplication($applicationId); }); // Server monitoring channels Broadcast::channel('server.{serverId}', function ($user, $serverId) { return $user->hasAccessToServer($serverId); }); ``` ### Presence Channels ```php // Team collaboration presence Broadcast::channel('team.{teamId}.presence', function ($user, $teamId) { if ($user->teams->contains('id', $teamId)) { return ['id' => $user->id, 'name' => $user->name]; } }); ``` ## API Controllers ### Location: [app/Http/Controllers/Api/](mdc:app/Http/Controllers) #### Resource Controllers ```php class ApplicationController extends Controller { public function index(Request $request) { return ApplicationResource::collection( $request->user()->currentTeam->applications() ->with(['server', 'environment']) ->paginate() ); } public function store(StoreApplicationRequest $request) { $application = $request->user()->currentTeam ->applications() ->create($request->validated()); return new ApplicationResource($application); } public function deploy(Application $application) { $deployment = $application->deploy(); return response()->json([ 'message' => 'Deployment started', 'deployment_id' => $deployment->id ]); } } ``` ### API Responses & Resources ```php // API Resource classes class ApplicationResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'fqdn' => $this->fqdn, 'status' => $this->status, 'git_repository' => $this->git_repository, 'git_branch' => $this->git_branch, 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, 'server' => new ServerResource($this->whenLoaded('server')), 'environment' => new EnvironmentResource($this->whenLoaded('environment')), ]; } } ``` ## API Authentication ### Sanctum Token Authentication ```php // API token generation Route::post('/auth/tokens', function (Request $request) { $request->validate([ 'name' => 'required|string', 'abilities' => 'array' ]); $token = $request->user()->createToken( $request->name, $request->abilities ?? [] ); return response()->json([ 'token' => $token->plainTextToken, 'abilities' => $token->accessToken->abilities ]); }); ``` ### Team-Based Authorization ```php // Team access middleware class EnsureTeamAccess { public function handle($request, Closure $next) { $teamId = $request->route('team'); if (!$request->user()->teams->contains('id', $teamId)) { abort(403, 'Access denied to team resources'); } return $next($request); } } ``` ## Rate Limiting ### API Rate Limits ```php // API throttling configuration RateLimiter::for('api', function (Request $request) { return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); }); // Deployment rate limiting RateLimiter::for('deployments', function (Request $request) { return Limit::perMinute(10)->by($request->user()->id); }); ``` ### Webhook Rate Limiting ```php // Webhook throttling RateLimiter::for('webhooks', function (Request $request) { return Limit::perMinute(100)->by($request->ip()); }); ``` ## Route Model Binding ### Custom Route Bindings ```php // Custom model binding for applications Route::bind('application', function ($value) { return Application::where('uuid', $value) ->orWhere('id', $value) ->firstOrFail(); }); // Team-scoped model binding Route::bind('team_application', function ($value, $route) { $teamId = $route->parameter('team'); return Application::whereHas('environment.project', function ($query) use ($teamId) { $query->where('team_id', $teamId); })->findOrFail($value); }); ``` ## API Documentation ### OpenAPI Specification - **[openapi.json](mdc:openapi.json)** - API documentation (373KB, 8316 lines) - **[openapi.yaml](mdc:openapi.yaml)** - YAML format documentation (184KB, 5579 lines) ### Documentation Generation ```php // Swagger/OpenAPI annotations /** * @OA\Get( * path="/api/v1/applications", * summary="List applications", * tags={"Applications"}, * security={{"bearerAuth":{}}}, * @OA\Response( * response=200, * description="List of applications", * @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Application")) * ) * ) */ ``` ## Error Handling ### API Error Responses ```php // Standardized error response format class ApiExceptionHandler { public function render($request, Throwable $exception) { if ($request->expectsJson()) { return response()->json([ 'message' => $exception->getMessage(), 'error_code' => $this->getErrorCode($exception), 'timestamp' => now()->toISOString() ], $this->getStatusCode($exception)); } return parent::render($request, $exception); } } ``` ### Validation Error Handling ```php // Form request validation class StoreApplicationRequest extends FormRequest { public function rules() { return [ 'name' => 'required|string|max:255', 'git_repository' => 'required|url', 'git_branch' => 'required|string', 'server_id' => 'required|exists:servers,id', 'environment_id' => 'required|exists:environments,id' ]; } public function failedValidation(Validator $validator) { throw new HttpResponseException( response()->json([ 'message' => 'Validation failed', 'errors' => $validator->errors() ], 422) ); } } ``` ## Real-Time API Integration ### WebSocket Events ```php // Broadcasting deployment events class DeploymentStarted implements ShouldBroadcast { public $application; public $deployment; public function broadcastOn() { return [ new PrivateChannel("application.{$this->application->id}"), new PrivateChannel("team.{$this->application->team->id}") ]; } public function broadcastWith() { return [ 'deployment_id' => $this->deployment->id, 'status' => 'started', 'timestamp' => now() ]; } } ``` ### API Event Streaming ```php // Server-Sent Events for real-time updates Route::get('/api/v1/applications/{application}/events', function (Application $application) { return response()->stream(function () use ($application) { while (true) { $events = $application->getRecentEvents(); foreach ($events as $event) { echo "data: " . json_encode($event) . "\n\n"; } usleep(1000000); // 1 second } }, 200, [ 'Content-Type' => 'text/event-stream', 'Cache-Control' => 'no-cache', ]); }); ```