tomatophp/filament-api
TomatoPHP Filament API adds RESTful endpoints to Filament resources, letting you expose CRUD operations, filters, and relationships via Laravel Sanctum authentication. Generate and manage model APIs directly from your admin panel.
Architecture fit. The package is a thin introspection layer over Filament resources: it reads the resource definition (form schema, table definition, model binding) and emits CRUD routes plus a controller that translates Filament form state into Eloquent writes and JSON reads. Architecturally this is not a new service, a proxy, or a data layer — it is a route generator that binds your existing admin-panel source of truth to an HTTP surface. That makes the fit binary rather than gradual:
The hard coupling to Filament internals is the load-bearing architectural fact. This is not a soft dependency on a library's public API; it is a dependency on Filament's resource lifecycle and form/table component contracts. A Filament major upgrade is, in practice, an upgrade to this package's assumptions about Filament. Treat the two as a single pinned unit in composer.json and schedule the pairing as a migration project with a window, not as a patch bump.
Integration feasibility. Install is genuinely cheap if the precondition holds: Laravel 10/11/12, PHP 8.1+, Filament v3/v4, Sanctum. Roughly a composer require, install:api, publish config, migrate, annotate one resource. The precondition is the whole estimate — if Filament is not already in production, adopting Filament to get the generator inverts the cost calculation and this becomes a platform migration disguised as a package evaluation. Feasibility check is therefore one question, asked first: is Filament already the source of truth for these entities in production? If no, stop and re-scope.
Beyond the install, the real integration work is three things the package does not do for you: authorization, contract documentation, and the test suite that pins the contract. Budget those explicitly. They are not large, but they are not zero, and they are the difference between a demo and something you can put on-call.
Technical risk. Ranked by expected cost, not likelihood alone:
canAccess/canViewAny are panel-scoped; generated API routes are not the panel. Assuming they fire is a security defect, not a config gap. The same applies with double force to multi-tenancy: getEloquentQuery() may be tenant-scoped by the panel's current tenant, which an API request does not have. This is the risk that can end a project.getEloquentQuery() and yours to own.Key questions to resolve before commitment. (a) Is Filament already in production for these models? (b) Who is the named owner of the generated API contract? (c) Which single consumer class are we serving first, and are their release cycles coordinated with ours? (d) Does any exposed resource participate in multi-tenancy? (e) Have we demonstrated — with a failing-then-passing test — 403 on unauthorized access and tenant isolation? (f) What is the documented divergence trigger at which we fork or hand-write?
Stack fit and sequencing. The adoption sequence is not "install, then expose everything." It is:
curl the index, confirm paginated JSON. This is a half-day, and it converts the rest of the work from exploration into scoping.api/v1 on day one. Retrofitting versioning is pure churn and it is free now.auth:sanctum in the package config, throttle:api, config/cors.php paths including api/*, and an explicit authorization decision per resource — policy middleware or overridden controller methods. Sanctum abilities per consumer class (categories:read) are cheap and tell you which integration broke something.Sanctum::actingAs. This is the highest-leverage artifact in the whole adoption: it is what makes a future fork safe, what catches Filament-upgrade breakage, and what turns "resource refactor" from an incident into a PR that fails CI.Migration path. There is no migration in the traditional sense — nothing is replaced. The relevant path is from hand-written or nonexistent endpoints to generated ones, and it should be per-resource and reversible: if a generated endpoint fails the go/no-go tests, that resource stays hand-written and the rest proceed. Treat generation as a default you can opt out of per resource, not an all-or-nothing cutover.
Compatibility. Pin Filament and this package together with explicit bounds; if the package does not declare an upper bound on Filament, add one yourself. Do not let a composer update on a Friday choose your upgrade window.
Contract management. Assume there is no OpenAPI emission and plan accordingly: hand-author the spec or point Scribe at the generated routes. Also enumerate the query-parameter names for filters and sorting — Filament table filter state is Livewire-shaped and the resulting query string is not self-documenting. Renaming a filter is a breaking change for anyone who bookmarked it; document it as such.
Go/no-go gates. Four tests constitute the decision, and anything you cannot demonstrate with a passing test you do not have: (1) policy enforcement returns 403 for an unauthorized user on a generated route; (2) tenant A cannot read tenant B's row; (3) a relationship write behaves as expected; (4) an invalid payload returns a sane 422 with field errors. Passing all four on the pilot resource is the gate to broader rollout.
Exit strategy. Decide the fork trigger in advance and write it down — e.g., "if Filament major support lags more than one release cycle, or if more than N endpoints require hand-written replacement, we fork and own." Forking here is genuinely cheap; what is not cheap is forking without a named owner.
Maintenance. Code maintenance is low — this is a thin layer and the generated surface is small. Process maintenance is the real cost and it is ongoing: exposed resources now need change governance. Add "does this touch an API-exposed resource?" to the PR template. Assign contract ownership. Keep the endpoint test suite green as the enforcement mechanism. Teams systematically under-budget this because it does not look like engineering work; it is the thing that prevents the mobile app breaking on a Tuesday for reasons nobody can trace.
Support and failure modes. The predictable failure modes, in the order support will encounter them:
route:list --path=api, every time.unique needs ignoreRecord: true and required on create often becomes sometimes on update. Test a PATCH that omits fields before launch.The debugging sequence is stable enough to write into a runbook: route:list → resolved middleware stack → dd() in the generated controller → query log. Nine times in ten it is registration or model binding, both of which that sequence isolates quickly.
Scaling. Scaling characteristics are Laravel's, not the package's — plain Eloquent reads and writes behind Sanctum and your middleware. There is no unusual runtime, no extra hop, no proprietary store. The scaling risks are therefore conventional and addressable: N+1 on index, missing pagination discipline, and unbounded filter combinations. The one non-conventional scaling limit is organisational: the number of consumers with uncoordinated release cycles. The package is comfortable with a handful; it is not built for a public developer ecosystem with a published contract and deprecation policy, and treating it as one is a scoping error rather than a scaling one.
Ramp-up. A Filament-fluent team installs and ships the pilot in roughly a day. A team not fluent in Filament lifecycle hooks, resource contracts, and form component internals will struggle, because every debugging path runs through Filament internals. Factor that into staffing: this is not a package you hand to a Laravel generalist on a team that has never run Filament. The compensating factor is that the code is readable and forkable — a competent Laravel engineer can read the controller end to end in under an hour and know exactly what the contract is, which is more than can be said for most API layers of this size.
Programme-level summary. This is a velocity instrument for a bounded, already-Filament-shaped CRUD surface serving coordinated consumers — and it is a legitimate reason not to spend a sprint on serialization plumbing. It should be recorded in planning as an explicit bet with a monitored divergence point and a documented exit, not absorbed as an implementation detail. Adopt conditionally on the four gates, pin the version pair, name an owner, and put the endpoint tests in place before the second resource. Under those conditions it converts an integration-gated roadmap item from a sequential dependency into a parallel workstream, which is the strongest argument for it and the metric against which it should be reviewed.
How can I help you explore Laravel packages today?