Reviewed on 13 October 2026 against the local client working tree and AppEngine checkout at f60e6b48. This is a source-contract review, not certification of a remote deployment. Existing uncommitted JavaScript app-key changes were inspected and preserved; fetch and build your reviewed revision before relying on them.
Video tutorials for this topic
Important differences and current alternatives
| Area | Current source behavior | Integration guidance |
|---|---|---|
| App credential exchange | Backend /profile/app/key consumes appId, secret, optional domain; not legacy key | JavaScript appKey is optional. Flutter constructor still requires it; an empty string accommodates registrations without a legacy key. |
| App registration | POST /profile/app/register permits ConfigAdmin; new app identity is a user with System group | Organization-level app registration is not platform organization creation. Protect the resulting secret; do not embed a privileged credential in browser/mobile code. |
| Revocation | Revoked app credential is refused by a new key exchange | Do not promise that revocation alone immediately invalidates every previously issued token. |
| JS current profile | auth.profile() uses a parameterless route that is not the self-service route | Use client.get('client-data/profile'). |
| JS own orders | orders.mine() omits the route's author parameter | Use client.get('client-data/orders'). |
| JS one order | orders.get() sends a query while the current alias uses path parameters | Use client.get('storefront/order/get/me/' + encodeURIComponent(orderNumber)) or the customer-data detail route with its required order number. |
| JS signup | Helper signature omits password and does not adopt returned tokens | Use generic signup for a password-based flow, inspect response and establish your host's session. |
| JS verification/refresh | No challenge, refresh, logout or persistence manager | Complete challenge via generic requests; trusted host owns renewal and cookies. A 200 challenge is not sign-in. |
| Header differences | JS forwards its person token unchanged; Flutter prefixes Bearer | Supply an unprefixed issued token to Flutter. Follow the specific JS transport contract; avoid accidentally doubling a prefix in an adapter. |
| Ordinary customer bearer | JS without app credentials still puts the customer token in x-client-authorization | Use a deliberate trusted-server adapter for routes authenticated by the ordinary Authorization bearer. See the portal companion. |
| Repository permissions | Read/write helpers remain subject to authorization; account writes have domain-only restrictions | Do not use repository CRUD to change passwords, roles, identity records or to bypass business side effects. |
| Sensitive partial writes | Generic partial update refuses user, customer, apikey, user_security, two_factor_backup | Use the dedicated account/security endpoints with appropriate authority. |
| Generic account deletion | Repository delete rejects user/customer deletion | Use the documented user/customer deletion API and its permissions. |
| Account selection | Customer shared-account selection reissues a session | Store replacement access/refresh tokens before reloading purchasing data. Selecting a company does not grant manager status. |
| Flutter restore | Loads stored user/token without a network check | Validate with a protected call before claiming the restored session is accepted by the server. |
| Flutter remembered sessions | Saved tokens go into preferences; signInWithSaved does not switch org and may read another cached user | Use a custom isolated secure store; explicitly sign in the desired staff/customer until cross-account restoration has been verified or corrected. |
| Flutter organization switch | Signs out and changes org, retains app credentials | Provide credentials matching the new org and isolate its storage. |
| Flutter uploads | Separate multipart path, not the ordinary send/retry path | Verify upload failures and renewal separately; do not promise shared retry semantics. |
| Retry differences | JS replays a server 401 once; Flutter additionally retries recognized transient failures | Writes need operation-specific reconciliation/idempotency. A lost response may follow a committed write. |
| Chat | Separate Flutter package; customer token is required; config affects AI/agent routing | Persist server-issued chatSessionId and use the returned chatId. Email alone is not a general session identifier. |
AppEngine-specific sequences
For reservations, start from the saved booking's definition and service, obtain actual availability, choose a returned slot and submit the documented business operation. Carry required form answers when creating a booking. Do not replace that with a repository status update. A conflict does not imply that the original booking should be cancelled.
For a customer portal, read the authenticated profile and owned-record endpoints. An order number, ticket number and reservation sk are different identifiers. A capability-style email/code cancellation route is different from a customer-owned route: the portal source first reads the owned booking on the trusted server, derives the saved values, then cancels.
For commerce, use server pricing and the complete checkout/provider flow. A quote is not a paid order; a configured gateway is not a completed payment. The JS package provides transport/helpers, not a payment UI, webhook processor or automatic shipping-provider setup.
For support chat, get the signed-in customer's token from the active session, connect the separate socket package, wait for authentication, and retain the server's chat session context. A backend supporting guest chat does not mean the Flutter support package currently supports guests: it refuses an empty token.
Source basis
Client implementation:
appmint_js_client/src/{index,config,transport,types,errors}.tsappmint_flutter_client/lib/appmint_flutter_client.dartappmint_flutter_client/lib/src/{config,http,repository,errors,call}.dartappmint_flutter_client/lib/src/auth/{auth,results,session_store}.dartappmint_flutter_chat/lib/src/{config,service,controller}.dart
AppEngine implementation in the sibling repository:
src/users/users.controller.ts,users.service.ts: app registration/exchange, customer sign-in/signup, refresh, magic code and account selection.src/users/auth/jwt.auth.guard.ts: authenticated identity and organization boundaries.src/client-account/client-account.controller.ts: self-service profile and shared-account routes.src/storefront/storefront.controller.ts: current order aliases and checkout.src/repositories/repository.controller.ts: query envelope, partial updates and guarded account deletion.src/chat/chat.gateway.ts: socket authentication, session identifiers and configured routing.
Keep these guides focused on client behavior. Use the maintained AppEngine API reference for current business payloads and sequences rather than copying a frozen endpoint inventory into every application.
