Custom Routes
All custom API routes go in routes/custom.php. This file is auto-loaded inside the authenticated middleware group, so every route requires a logged-in user by default.
Available Middleware
Your routes have access to the following middleware out of the box:
auth:sanctum— Already applied; the user is authenticatedentitled:feature_name— Gate by plan feature (returns 403 if the org's plan does not include it)org.can:permission_name— Check org-level role permission (e.g.,org.can:create_projects)
Accessing the Current Organization
Inside any controller, get the user's active organization:
$org = $request->user()->activeOrganization();
All queries should be scoped to this organization to enforce multi-tenancy.
Example: Adding Routes
// routes/custom.php
use App\Http\Controllers\Custom\ProjectController;
Route::prefix('projects')
->middleware('entitled:projects')
->group(function () {
Route::get('/', [ProjectController::class, 'index'])
->middleware('org.can:view_projects');
Route::post('/', [ProjectController::class, 'store'])
->middleware('org.can:create_projects');
Route::get('/{project}', [ProjectController::class, 'show'])
->middleware('org.can:view_projects');
Route::patch('/{project}', [ProjectController::class, 'update'])
->middleware('org.can:update_projects');
Route::delete('/{project}', [ProjectController::class, 'destroy'])
->middleware('org.can:delete_projects');
});
Middleware Stacking
You can stack multiple middleware on a group or individual route:
Route::prefix('reports')
->middleware(['entitled:analytics', 'org.can:view_reports'])
->group(function () {
Route::get('/summary', [ReportController::class, 'summary']);
Route::get('/export', [ReportController::class, 'export']);
});
Route Prefix
All routes in routes/custom.php are automatically prefixed with /api. So a route defined as /projects is accessible at /api/projects.