Guide ·

One API for Your Flutter App and Web Dashboard: A Practical Guide

How to design one Node.js or PHP REST API that serves both a Flutter mobile app and a web dashboard: versioning, auth, errors, roles and push notifications.

By Ritesh Singh, full-stack developer

A very common product shape today is a web dashboard for the business and a mobile app for customers or field staff. Both need the same data: users, orders, cases, bookings, payments. The cleanest way to build this is one backend API that both clients use, instead of two separate systems that slowly drift apart. Most of the products I build follow this pattern, for example a legal case management platform where the Next.js web app and the mobile app share one Node.js API, and a web radio platform whose JSON API also feeds the station's Flutter app.

Sharing an API sounds simple, but a mobile app puts constraints on the backend that a website alone never does. This guide covers the decisions that matter most when one REST API, written in Node.js/Express or PHP, has to serve a Flutter app and a web dashboard at the same time.

Why one API instead of two

With one API, business rules live in one place. A discount, a permission check or a status change is written once and behaves the same on the website and in the app. Bugs are fixed once. New clients, such as a second app, can be added later without copying logic. The cost is that the API has to be designed for its slowest-moving client, and that client is almost always the mobile app.

1. Version the API from the first release

You can redeploy a website in minutes, and every visitor gets the new version on their next page load. A mobile app is different. Store review takes time, and many users do not update for weeks or months. That means old app builds will keep calling your API long after you have changed it.

Put a version in the path from day one, such as /api/v1/. Add new fields freely, because older apps simply ignore them, but never rename or remove a field, or change its type, inside the same version. When a breaking change is unavoidable, add /api/v2/ for the new behaviour and keep v1 running until usage drops.

It also helps to add a small endpoint that returns the minimum supported app version. The Flutter app checks it on start and shows an "Update required" screen when it is too old. This gives you a safe way to retire an old API version without leaving users with a broken app.

2. Use authentication that suits both clients

Browsers and mobile apps store credentials differently. A common approach that works well for both is a short-lived access token, such as a JWT valid for 15 to 60 minutes, plus a longer-lived refresh token that can be revoked on the server. On the web dashboard, keep tokens in HttpOnly cookies so page scripts cannot read them. In Flutter, store the refresh token in secure storage backed by the Android Keystore and iOS Keychain, for example with the flutter_secure_storage package, not in plain shared preferences.

Build the refresh flow into the app's HTTP client once: when a request returns 401, refresh the token and retry the request a single time. Keep a record of refresh tokens per device on the server, so a user can log out of a lost phone without being logged out everywhere else.

3. Agree on one response and error format

The fastest way to slow down a mobile team is inconsistent responses. Pick one shape for success and one for errors, and use it on every endpoint. A useful error response contains a stable machine-readable code, a human-readable message and, for form validation, the message for each field. The app can then highlight the right input without parsing English text.

A few small rules save a lot of debugging later. Send dates in ISO 8601 format in UTC and let each client format them for the user's time zone. Send money as integer amounts in the smallest unit, such as paise, or as strings, never as floating-point numbers. Use the correct HTTP status codes, so the Flutter client can tell a validation error (422) from an expired login (401) or a server problem (500).

4. Keep mobile payloads small

Dashboards on office broadband can afford large responses. An app on a weak mobile connection cannot. Paginate every list endpoint, and return only the fields a list screen needs, with a separate detail endpoint for the full record. Resize images on upload and serve thumbnails for lists. Enable gzip or Brotli compression on the server. These changes make the app feel faster without touching any Flutter code.

5. Enforce roles and permissions in the API

When a web dashboard and an app share a backend, they usually serve different roles: an owner or admin on the web, staff or customers on the phone. Hiding a button in the interface is not security. Every endpoint must check on the server who the user is and what they may see or change. In the legal platform, for example, advocates, office staff and clients see different data, and that rule is enforced by the API rather than by each screen.

6. Plan push notifications and background work

Mobile apps usually need push notifications: a new booking, a status change, a reminder for a hearing date. Store each device's push token, such as a Firebase Cloud Messaging token, against the user and the device, and remove tokens that the push service reports as invalid. Send notifications from a background job or queue rather than inside the API request, so a slow push service never slows down the user who triggered the change.

7. Document the API and give the app a staging server

Mobile developers should not have to read backend code to know what an endpoint returns. Keep endpoint documentation, for example an OpenAPI file or a shared Postman collection, up to date with every change. Run a staging copy of the API with test data, so app builds under review or in testing never touch production records. When the backend and both clients are deployed with containers, staging is cheap to run; my guide to deploying a Next.js app and API with Coolify shows one way to host both on a single VPS.

A quick checklist before launch

Before the first app release, check that every route is under a version prefix, that old app builds have a forced-update path, that tokens refresh and can be revoked per device, that every error uses the same format, that list endpoints are paginated, that permissions are enforced on the server, that push tokens are cleaned up, and that the API has documentation and a staging environment. None of this is complicated on its own, but adding it after launch is much harder than starting with it.

Need one developer for the API and the app?

Because I build the backend and the clients together, the API, the Flutter or React Native app and the Next.js dashboard are designed as one product, with one person accountable for all of it. If you already have a backend, I can review it and connect a new app to it. See my Node.js and PHP API development service, or send me a short brief about your product.

Related services

Hire me for this

Want this done for your product?

Start your project →