06 — Routing Map
System: PyroRadius ISP Billing & RADIUS Management
Stack: Laravel 13 · Inertia.js v2 · React 18 · PostgreSQL 16
Last Updated: 2026-07-13
Overview
PyroRadius routes are defined across four files:
| File |
Purpose |
routes/web.php |
All authenticated web application routes |
routes/auth.php |
Login, logout, password reset |
routes/portal.php |
Customer self-service portal (separate auth guard) |
routes/api.php |
AJAX/API endpoints consumed by the frontend |
All web routes (except auth routes) are wrapped in the auth middleware group. Role and permission enforcement is handled inside controllers using $this->authorize() or Gate::allows() checks, not at the route level. This keeps the route file clean and centralises access logic.
Middleware Groups
| Group Name |
Middleware Applied |
Used On |
web |
EncryptCookies, AddQueuedCookies, VerifyCsrfToken, ShareErrorsFromSession, HandleInertiaRequests |
All web routes |
auth |
Authenticate (redirects to login if unauthenticated) |
All protected routes |
portal |
Authenticate:portal (portal guard) |
Customer portal routes |
api |
throttle:api, SubstituteBindings |
API routes (session auth via Sanctum) |
Auth Routes (routes/auth.php)
These routes are not behind the auth middleware — they are publicly accessible (except logout).
| Name |
Method |
URI |
Controller@Method |
Notes |
login |
GET |
/login |
AuthController@showLogin |
Renders Auth/Login Inertia page |
login.submit |
POST |
/login |
AuthController@login |
Validates credentials, starts session |
logout |
POST |
/logout |
AuthController@logout |
Destroys session |
password.request |
GET |
/forgot-password |
PasswordResetController@request |
Renders forgot password page |
password.email |
POST |
/forgot-password |
PasswordResetController@email |
Sends reset link |
password.reset |
GET |
/reset-password/{token} |
PasswordResetController@showReset |
Reset form |
password.update |
POST |
/reset-password |
PasswordResetController@update |
Stores new password |
Dashboard Routes
Prefix: / — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
dashboard |
GET |
/ |
DashboardController@index |
view_dashboard |
Dashboard/Index |
dashboard.online |
GET |
/dashboard/online-stats |
DashboardController@onlineStats |
view_dashboard |
— (AJAX JSON) |
dashboard.health |
GET |
/health |
HealthController@index |
view_health |
Health/Index |
dashboard.health.check |
POST |
/health/check |
HealthController@runCheck |
view_health |
— (AJAX) |
Customer Routes
Prefix: /customers — Middleware: auth
Core CRUD
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
customers.index |
GET |
/customers |
CustomerController@index |
view_customers |
Customers/Index |
customers.create |
GET |
/customers/create |
CustomerController@create |
create_customers |
Customers/Create |
customers.store |
POST |
/customers |
CustomerController@store |
create_customers |
— (redirects) |
customers.show |
GET |
/customers/{customer} |
CustomerController@show |
view_customers |
Customers/Show |
customers.edit |
GET |
/customers/{customer}/edit |
CustomerController@edit |
edit_customers |
Customers/Edit |
customers.update |
PUT |
/customers/{customer} |
CustomerController@update |
edit_customers |
— (redirects) |
customers.destroy |
DELETE |
/customers/{customer} |
CustomerController@destroy |
delete_customers |
— (redirects) |
Customer Actions
| Name |
Method |
URI |
Controller@Method |
Permission |
Notes |
customers.recharge |
POST |
/customers/{customer}/recharge |
CustomerController@recharge |
recharge_customers |
Triggers full billing + RADIUS flow |
customers.status |
POST |
/customers/{customer}/status |
CustomerController@updateStatus |
edit_customers |
Toggle active/suspended/disconnected |
customers.ledger |
GET |
/customers/{customer}/ledger |
CustomerController@ledger |
view_customers |
Customers/Ledger Inertia page |
customers.portal-login |
POST |
/customers/{customer}/portal-login |
CustomerController@generatePortalLink |
edit_customers |
Issues a signed portal URL |
customers.expiry |
PUT |
/customers/{customer}/expiry |
CustomerController@updateExpiry |
edit_customers |
Manually set expiry date |
customers.bulk-status |
POST |
/customers/bulk-status |
CustomerController@bulkStatus |
edit_customers |
Batch suspend/activate |
customers.import |
GET |
/customers/import |
ImportController@showCustomers |
import_data |
Import/Customers |
customers.import.store |
POST |
/customers/import |
ImportController@importCustomers |
import_data |
CSV upload + queue |
Billing Routes
Prefix: /billing — Middleware: auth
Invoices
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
billing.invoices.index |
GET |
/billing/invoices |
InvoiceController@index |
view_billing |
Billing/Invoices/Index |
billing.invoices.show |
GET |
/billing/invoices/{invoice} |
InvoiceController@show |
view_billing |
Billing/Invoices/Show |
billing.invoices.create |
GET |
/billing/invoices/create |
InvoiceController@create |
create_billing |
Billing/Invoices/Create |
billing.invoices.store |
POST |
/billing/invoices |
InvoiceController@store |
create_billing |
— |
billing.invoices.destroy |
DELETE |
/billing/invoices/{invoice} |
InvoiceController@destroy |
delete_billing |
— |
billing.invoices.pdf |
GET |
/billing/invoices/{invoice}/pdf |
InvoiceController@pdf |
view_billing |
PDF download response |
Payments
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
billing.payments.index |
GET |
/billing/payments |
PaymentController@index |
view_billing |
Billing/Payments/Index |
billing.payments.show |
GET |
/billing/payments/{payment} |
PaymentController@show |
view_billing |
Billing/Payments/Show |
billing.payments.receipt |
GET |
/billing/payments/{payment}/receipt |
PaymentController@receipt |
view_billing |
PDF receipt download |
billing.payments.reverse |
POST |
/billing/payments/{payment}/reverse |
PaymentController@reverse |
reverse_payments |
Reversal with reason |
Archive
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
billing.archive.index |
GET |
/billing/archive |
BillingArchiveController@index |
view_billing |
Billing/Archive/Index |
billing.archive.show |
GET |
/billing/archive/{month} |
BillingArchiveController@show |
view_billing |
Billing/Archive/Show |
billing.archive.run |
POST |
/billing/archive/run |
BillingArchiveController@run |
manage_billing |
Triggers month-end archive |
Batches
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
billing.batches.index |
GET |
/billing/batches |
InvoiceBatchController@index |
view_billing |
Billing/Batches/Index |
billing.batches.create |
GET |
/billing/batches/create |
InvoiceBatchController@create |
create_billing |
Billing/Batches/Create |
billing.batches.store |
POST |
/billing/batches |
InvoiceBatchController@store |
create_billing |
Queues batch generation |
billing.batches.show |
GET |
/billing/batches/{batch} |
InvoiceBatchController@show |
view_billing |
Billing/Batches/Show |
Package Routes
Prefix: /packages — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
packages.index |
GET |
/packages |
PackageController@index |
view_packages |
Packages/Index |
packages.create |
GET |
/packages/create |
PackageController@create |
manage_packages |
Packages/Create |
packages.store |
POST |
/packages |
PackageController@store |
manage_packages |
— |
packages.edit |
GET |
/packages/{package}/edit |
PackageController@edit |
manage_packages |
Packages/Edit |
packages.update |
PUT |
/packages/{package} |
PackageController@update |
manage_packages |
Triggers RadiusService::syncPackage() |
packages.destroy |
DELETE |
/packages/{package} |
PackageController@destroy |
manage_packages |
Checks no active customers |
NAS Routes
Prefix: /nas — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
nas.index |
GET |
/nas |
NasController@index |
view_nas |
Nas/Index |
nas.create |
GET |
/nas/create |
NasController@create |
manage_nas |
Nas/Create |
nas.store |
POST |
/nas |
NasController@store |
manage_nas |
— |
nas.edit |
GET |
/nas/{nas}/edit |
NasController@edit |
manage_nas |
Nas/Edit |
nas.update |
PUT |
/nas/{nas} |
NasController@update |
manage_nas |
— |
nas.destroy |
DELETE |
/nas/{nas} |
NasController@destroy |
manage_nas |
— |
nas.sessions |
GET |
/nas/{nas}/sessions |
NasController@sessions |
view_nas |
Nas/Sessions |
nas.disconnect |
POST |
/nas/{nas}/sessions/{session}/disconnect |
NasController@disconnect |
manage_nas |
Sends MikroTik API disconnect |
OLT Routes
Prefix: /olt — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
olt.index |
GET |
/olt |
OltController@index |
view_olt |
Olt/Index |
olt.create |
GET |
/olt/create |
OltController@create |
manage_olt |
Olt/Create |
olt.store |
POST |
/olt |
OltController@store |
manage_olt |
— |
olt.edit |
GET |
/olt/{olt}/edit |
OltController@edit |
manage_olt |
Olt/Edit |
olt.update |
PUT |
/olt/{olt} |
OltController@update |
manage_olt |
— |
olt.destroy |
DELETE |
/olt/{olt} |
OltController@destroy |
manage_olt |
— |
WhatsApp Routes
Prefix: /whatsapp — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
whatsapp.index |
GET |
/whatsapp |
WhatsAppController@index |
view_whatsapp |
WhatsApp/Index |
whatsapp.outbox |
GET |
/whatsapp/outbox |
WhatsAppController@outbox |
view_whatsapp |
WhatsApp/Outbox |
whatsapp.templates.index |
GET |
/whatsapp/templates |
WhatsAppController@templates |
manage_whatsapp |
WhatsApp/Templates |
whatsapp.templates.store |
POST |
/whatsapp/templates |
WhatsAppController@storeTemplate |
manage_whatsapp |
— |
whatsapp.send |
POST |
/whatsapp/send |
WhatsAppController@send |
manage_whatsapp |
Manual message send |
whatsapp.settings |
GET |
/whatsapp/settings |
WhatsAppController@settings |
manage_whatsapp |
WhatsApp/Settings |
whatsapp.settings.update |
PUT |
/whatsapp/settings |
WhatsAppController@updateSettings |
manage_whatsapp |
— |
Notification Routes
Prefix: /notifications — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
notifications.index |
GET |
/notifications |
NotificationController@index |
view_notifications |
Notifications/Index |
notifications.mark-read |
POST |
/notifications/{notification}/read |
NotificationController@markRead |
— |
Any authenticated user |
notifications.mark-all-read |
POST |
/notifications/read-all |
NotificationController@markAllRead |
— |
Any authenticated user |
Campaign Routes
Prefix: /campaigns — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
campaigns.index |
GET |
/campaigns |
CampaignController@index |
manage_campaigns |
Campaigns/Index |
campaigns.create |
GET |
/campaigns/create |
CampaignController@create |
manage_campaigns |
Campaigns/Create |
campaigns.store |
POST |
/campaigns |
CampaignController@store |
manage_campaigns |
Queues campaign dispatch |
campaigns.show |
GET |
/campaigns/{campaign} |
CampaignController@show |
manage_campaigns |
Campaigns/Show |
campaigns.destroy |
DELETE |
/campaigns/{campaign} |
CampaignController@destroy |
manage_campaigns |
Only if status=draft |
Report Routes
Prefix: /reports — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
reports.index |
GET |
/reports |
ReportController@index |
view_reports |
Reports/Index |
reports.revenue |
GET |
/reports/revenue |
ReportController@revenue |
view_reports |
Reports/Revenue |
reports.customers |
GET |
/reports/customers |
ReportController@customers |
view_reports |
Reports/Customers |
reports.expiry |
GET |
/reports/expiry |
ReportController@expiry |
view_reports |
Reports/Expiry |
reports.radius |
GET |
/reports/radius |
ReportController@radius |
view_reports |
Reports/Radius |
reports.dealer |
GET |
/reports/dealer |
ReportController@dealer |
view_reports |
Reports/Dealer |
reports.export |
GET |
/reports/{type}/export |
ReportController@export |
view_reports |
CSV/Excel download |
Settings Routes
Prefix: /settings — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
settings.general |
GET |
/settings |
SettingsController@general |
manage_settings |
Settings/General |
settings.general.update |
PUT |
/settings |
SettingsController@updateGeneral |
manage_settings |
— |
settings.company |
GET |
/settings/company |
SettingsController@company |
manage_settings |
Settings/Company |
settings.company.update |
PUT |
/settings/company |
SettingsController@updateCompany |
manage_settings |
— |
settings.radius |
GET |
/settings/radius |
SettingsController@radius |
manage_settings |
Settings/Radius |
settings.radius.update |
PUT |
/settings/radius |
SettingsController@updateRadius |
manage_settings |
— |
settings.cron |
GET |
/settings/cron |
CronJobController@index |
manage_settings |
Settings/CronJobs |
settings.cron.update |
PUT |
/settings/cron/{job} |
CronJobController@update |
manage_settings |
Toggle enable/disable |
User Management Routes
Prefix: /users — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
users.index |
GET |
/users |
UserController@index |
manage_users |
Users/Index |
users.create |
GET |
/users/create |
UserController@create |
manage_users |
Users/Create |
users.store |
POST |
/users |
UserController@store |
manage_users |
— |
users.edit |
GET |
/users/{user}/edit |
UserController@edit |
manage_users |
Users/Edit |
users.update |
PUT |
/users/{user} |
UserController@update |
manage_users |
— |
users.destroy |
DELETE |
/users/{user} |
UserController@destroy |
manage_users |
Cannot delete self |
roles.index |
GET |
/roles |
RoleController@index |
manage_roles |
Roles/Index |
roles.create |
GET |
/roles/create |
RoleController@create |
manage_roles |
Roles/Create |
roles.store |
POST |
/roles |
RoleController@store |
manage_roles |
— |
roles.edit |
GET |
/roles/{role}/edit |
RoleController@edit |
manage_roles |
Roles/Edit |
roles.update |
PUT |
/roles/{role} |
RoleController@update |
manage_roles |
— |
Audit Routes
Prefix: /audit — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
audit.index |
GET |
/audit |
AuditController@index |
view_audit |
Audit/Index |
audit.show |
GET |
/audit/{log} |
AuditController@show |
view_audit |
Audit/Show |
audit.export |
GET |
/audit/export |
AuditController@export |
view_audit |
CSV download |
Import Routes
Prefix: /import — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
import.index |
GET |
/import |
ImportController@index |
import_data |
Import/Index |
import.customers |
POST |
/import/customers |
ImportController@importCustomers |
import_data |
— |
import.packages |
POST |
/import/packages |
ImportController@importPackages |
import_data |
— |
import.logs |
GET |
/import/logs |
ImportController@logs |
import_data |
Import/Logs |
TR-069 Routes
Prefix: /tr069 — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
tr069.index |
GET |
/tr069 |
Tr069Controller@index |
manage_tr069 |
Tr069/Index |
tr069.devices |
GET |
/tr069/devices |
Tr069Controller@devices |
manage_tr069 |
Tr069/Devices |
tr069.device.show |
GET |
/tr069/devices/{device} |
Tr069Controller@show |
manage_tr069 |
Tr069/Device |
tr069.provision |
POST |
/tr069/devices/{device}/provision |
Tr069Controller@provision |
manage_tr069 |
— |
Graph Routes
Prefix: /graphs — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
graphs.index |
GET |
/graphs |
GraphController@index |
view_graphs |
Graphs/Index |
graphs.nas |
GET |
/graphs/nas/{nas} |
GraphController@nas |
view_graphs |
Graphs/Nas |
graphs.customer |
GET |
/graphs/customer/{customer} |
GraphController@customer |
view_graphs |
Graphs/Customer |
Ticket Routes
Prefix: /tickets — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
tickets.index |
GET |
/tickets |
TicketController@index |
view_tickets |
Tickets/Index |
tickets.create |
GET |
/tickets/create |
TicketController@create |
create_tickets |
Tickets/Create |
tickets.store |
POST |
/tickets |
TicketController@store |
create_tickets |
— |
tickets.show |
GET |
/tickets/{ticket} |
TicketController@show |
view_tickets |
Tickets/Show |
tickets.update |
PUT |
/tickets/{ticket} |
TicketController@update |
edit_tickets |
Status + assignment |
tickets.comment |
POST |
/tickets/{ticket}/comments |
TicketController@comment |
view_tickets |
Any authenticated user |
Engineer Routes
Prefix: /engineer — Middleware: auth
| Name |
Method |
URI |
Controller@Method |
Permission |
Inertia Component |
engineer.dashboard |
GET |
/engineer |
EngineerController@dashboard |
engineer_access |
Engineer/Dashboard |
engineer.tasks |
GET |
/engineer/tasks |
EngineerController@tasks |
engineer_access |
Engineer/Tasks |
engineer.tasks.update |
PUT |
/engineer/tasks/{task} |
EngineerController@updateTask |
engineer_access |
— |
Customer Portal Routes (routes/portal.php)
Guard: portal — Middleware: auth:portal
Prefix: /portal
| Name |
Method |
URI |
Controller@Method |
Notes |
portal.login |
GET |
/portal/login |
PortalAuthController@showLogin |
Token-based or phone/password |
portal.login.submit |
POST |
/portal/login |
PortalAuthController@login |
— |
portal.logout |
POST |
/portal/logout |
PortalAuthController@logout |
— |
portal.dashboard |
GET |
/portal/dashboard |
PortalController@dashboard |
Customer overview |
portal.invoices |
GET |
/portal/invoices |
PortalController@invoices |
Own invoices only |
portal.payments |
GET |
/portal/payments |
PortalController@payments |
Own payment history |
portal.profile |
GET |
/portal/profile |
PortalController@profile |
Edit contact info |
portal.profile.update |
PUT |
/portal/profile |
PortalController@updateProfile |
— |
API Routes (routes/api.php)
All API routes use session cookie authentication (Sanctum stateful) with CSRF. No API token required for frontend AJAX calls.
| Name |
Method |
URI |
Controller@Method |
Permission |
Response |
api.customers.search |
GET |
/api/customers |
Api\CustomerController@search |
view_customers |
JSON array |
api.customers.filter |
GET |
/api/customers/filter |
Api\CustomerController@filter |
view_customers |
Paginated JSON |
api.nas.traffic |
GET |
/api/nas/{nas}/traffic |
Api\NasController@traffic |
view_nas |
JSON (MikroTik + SNMP) |
api.nas.online |
GET |
/api/nas/{nas}/online |
Api\NasController@online |
view_nas |
JSON session list |
api.dashboard.online |
GET |
/api/dashboard/online |
Api\DashboardController@online |
view_dashboard |
JSON count + list |
api.packages.availability |
GET |
/api/packages/{package}/availability |
Api\PackageController@availability |
view_packages |
JSON |
api.whatsapp.outbox |
GET |
/api/whatsapp/outbox |
Api\WhatsAppController@outbox |
view_whatsapp |
Paginated JSON |
api.customers.ledger |
GET |
/api/customers/{customer}/ledger |
Api\CustomerController@ledger |
view_customers |
JSON ledger entries |
api.invoices.search |
GET |
/api/invoices |
Api\InvoiceController@search |
view_billing |
JSON invoices for typeahead |
api.radius.status |
GET |
/api/radius/{username}/status |
Api\RadiusController@status |
view_nas |
JSON RADIUS entry state |
api.health.ping |
GET |
/api/health/ping |
Api\HealthController@ping |
— |
{"status":"ok"} |
Route Model Binding
Laravel's implicit route model binding resolves these models automatically from the {param} in the URI:
| Param |
Model |
Key |
{customer} |
App\Models\Customer |
id |
{invoice} |
App\Models\Invoice |
id |
{payment} |
App\Models\Payment |
id |
{package} |
App\Models\Package |
id |
{nas} |
App\Models\Nas |
id |
{olt} |
App\Models\Olt |
id |
{user} |
App\Models\User |
id |
{role} |
App\Models\Role |
id |
{ticket} |
App\Models\Ticket |
id |
{log} |
App\Models\AuditLog |
id |