goldnead/statamic-app-api
A Statamic addon that exposes your site’s content through a clean, app-ready JSON API. Connect mobile apps and custom frontends to collections, entries, and taxonomies using Laravel-powered endpoints built for simple integration and flexible configuration.
Architecture fit
This package is a thin HTTP/API layer over statamic-payments (billing, subscriptions, cancellations) with optional enrichment from statamic-teams (team billing identity). It follows a sensible Laravel package shape: routes under billing/*, config-driven behaviour (billing.cancellation_copy_to_team), and response DTOs extended additively (ends_at, copied_to). v0.2.1 moves it from "reimplemented upstream logic" to "delegates to upstream" — a meaningful architectural improvement that reduces behavioural drift between the API surface and the Statamic control panel / customer portal.
Integration feasibility
Straightforward for any Laravel app already running Statamic with statamic-payments. The hard constraint is explicit and unambiguous: statamic-payments >= 1.29.2. The team-copy feature additionally requires statamic-teams and a populated billing.email; without it the feature degrades silently (no copy sent), which is acceptable but must be documented as expected behaviour rather than a failure. No migration steps, no schema changes, no config file republication implied — though the new config key will need to be present for anyone who has published and version-pinned their config.
Technical risk
Support\Cancellations::cancel() reduces duplication but ties this package to a namespace that reads as internal/support-tier rather than a guaranteed public contract. A patch release upstream that changes that signature breaks cancellation for every consumer of this package at once — and cancellation is a revenue-affecting path.via: app-api from the log entry is a low-severity but real regression: any dashboards, alerts, or audit queries filtering on that marker will quietly return zero results rather than erroring. This is the kind of change that is discovered weeks later during a reconciliation.billing.cancellation_copy_to_team defaulting to on means upgrading changes customer-facing communication without an opt-in action. The guard (skip when the billing address equals the canceller's address) is correct and thoughtful, but the default still needs a conscious decision per deployment, especially in multi-tenant or EU contexts.Gekündigt, läuft bis … / Beendet am …) shows the package carries user-visible strings. Any team shipping non-German UI inherits a translation dependency that is not called out in these notes.Key questions
Support\Cancellations::cancel() a supported public API upstream, or may it change without a major version bump? What is our pinning strategy?via: app-api? If so, what replaces it as the API-originated marker?ends_at match the field name and semantics already exposed elsewhere (Portal\Display::ending()), or are we introducing a second shape for the same concept?statamic-teams is absent but the config flag is on — silent skip, logged warning, or hard error?Stack fit
Requires Laravel + Statamic, statamic-payments >= 1.29.2, and optionally statamic-teams. The package sits in the API/BFF tier in front of billing — no database ownership of its own, which keeps it easy to add and easy to remove. Fit is good for teams already standardized on the Statamic payments stack; it is not a general-purpose billing abstraction and should not be adopted as one.
Migration path
Low effort, gated on one prerequisite. Sequence: (1) upgrade statamic-payments to ≥1.29.2 and verify the portal ending() copy matches the new API copy; (2) upgrade this package; (3) decide the value of billing.cancellation_copy_to_team before deploying rather than after; (4) audit log queries for via: app-api and adjust. There is no data migration and no downtime requirement. The label and field changes are additive from a consumer perspective — ends_at and copied_to are new fields, so existing clients parsing the response will not break.
Compatibility
ends_at and copied_to are safe for existing clients; document them so front-ends can start surfacing "Kündigung läuft bis" state.statamic-payments >= 1.29.2 floor is now a hard part of this package's contract. Any environment pinned below that will fail on the cancellation path, which is exactly the path you least want failing in production.Sequencing
Treat the upstream version bump as the primary change and this package as the follow-on. Pin both together in composer.json so they cannot drift apart in CI. Ship the API upgrade before announcing the team-copy behaviour to customers, so support has the switch available on day one.
Maintenance
Ongoing maintenance is now largely delegated to upstream — a net reduction in surface area for us, but it converts "we fix our copy of the logic" into "we wait for upstream." Budget for version-tracking rather than code-ownership. The internal-looking Support\ dependency is the item most likely to force an unplanned patch.
Support
Two new support vectors: (a) "the cancellation email went to someone who didn't cancel" — answer is the config flag, which support must be able to locate in the CP under Checkout; (b) "my monitoring shows no API cancellations" — answer is the via marker removal. Both need runbook entries before rollout, not after the first ticket.
Scaling No scaling concerns introduced. The added email is one extra send per cancellation, only when a distinct team billing address exists — negligible volume against any realistic cancellation rate. It does mean cancellation now has an outbound dependency on the mail transport: a mail outage should not fail the cancellation itself, and this should be verified explicitly.
Failure modes
Support\Cancellations::cancel() signature change → cancellation endpoint returns 500 for all consumers simultaneously. Highest blast radius, lowest detectability until a customer tries to cancel.via: app-api → silently empty audit trail for API-originated cancellations.Ramp-up Low. The package needs no new infrastructure and the API surface is unchanged for existing integrations. The real ramp-up cost is institutional: whoever owns billing must know that (1) upstream version is now load-bearing, (2) the team-copy default is on, and (3) the audit marker changed. All three are fifteen-minute conversations that are expensive to have after an incident.
How can I help you explore Laravel packages today?