APIs & services

Every backend service the app calls today, and every live endpoint with who calls it and when.

Services the app talks to12 on the gateway host, plus S3 and Firebase
ServiceBase pathUsed forEndpoints
Common TLD (ctld)/ctld/api/...Common / BRBASE platform: farmer profile photo, farmer role maps, inventory and inventory products, tenant products.
Reads use client-built SQL-like criteria strings (criteria=isActive=true AND iE.id in (...)). TLD prefix set in app/…/urvi/core/ApplicationClass.kt:116-121.
8
Program TLD (ptld)/ptld/api/...Program platform: work nodes (centres) and the custom worknodeietag/urvi endpoints that create and update farmers (IE).
POST worknodeietag/urvi is also used as a get-or-create when a farmer is opened.
3
Reporting datasets (rtld)/rtld/api/dataset/v1/execute?name=X&version=1&format=json&params=...Legacy reporting dataset engine: about 25 named read-only datasets.
Params are KEY=value--KEY2=value strings built on the device. Several dataset names are season-specific (…2425, IsKAP202324).
16
commons-report-service/gateway/commons-report-service/api/v1/datasets/name/{X}/executeNew reporting dataset engine: about 15 named datasets, including the farmer list used by data setup.
Same params grammar as rtld. Some datasets are called on both engines by different client paths.
21
portfolio-service/gateway/portfolio-service/api/v1/...Crop plans (portfolios and line items), crop photos and geofences, farming models (ATM/DKG), harvests, compact blocks, practices, and ref-data config (CLASS.PORTFOLIO_APP_CONFIG).
Ref-data paging signals more pages with HTTP 206. One read is a POST (line-items/ownerEntities/latest).
25
asset-service/gateway/asset-service/api/v1/...Land and cattle assets, asset attachments (KML geofence, images), endorsements, endorsement comments and attachments, annual action plans.
Asset POST returns the new id as a plain integer.
18
assessment-service/gateway/assessment-service/api/v1/...Assessment instances and AIA default responses / attachments (certification, activity history).
Called through the commons-assessment-urvi-lib library and app/…/urvi/utility/AssessmentUtil.kt; library internals are documented separately.
2
urvi-app-service/gateway/urvi-app-service/api/v1/...Existing Urvi-specific service: device sessions (device binding) and remote app actions (remote logout / clear data).
The natural home for the new App Service (BFF).
5
sync-service/sync-service/api/v1/data/...Telemetry: periodic snapshot of the whole offline queue (so) and clickstream.
The queue snapshot contains full request bodies, including PII.
2
raw-data-service/raw-data-service/report/ryss-abstract/...VO and SHG abstract reports, downloaded as Excel files.2
Platform static files/ie-registration/assets/json/...Static crop list JSON served by the platform host.
Fetched on data setup and again on Home.
1
S3 static datahttps://pcf-static-public-data.s3.ap-south-1.amazonaws.com/Public static reference data: igx-static-data/asset/ref_data.json, asset/classification.json.
No auth. Fetched on every Home open.
2
Bridge session API (ctld){base}/ctld/api/session/v1 and /ctld/api/device/deviceid/v1 on bridge_base_url, or federation_url for ap.gov usersLogin (session creation) and device registration, called by account-lib through bridge-security-api 8.0.3.
Credentials go in X-USER / X-PASS headers; the token comes back in the X-SESSIONID response header.
2
FirebaseFirebase SDKs (Firestore, Storage, FCM, Remote Config, Crashlytics, In-App Messaging)Ops telemetry and fallback storage: Firestore SYNC_LOG, PLI_IMAGE, URVI_ATTACHMENT_ISSUE and DB dumps; Storage fallback for crop photos (userId/farmerId/pliId/pliId.ext); FCM topic push; Remote Config flags (show_force_sync, show_analytics_tab, current_season_value).
Firestore receives raw operations with PII. Images in Storage are invisible to the backend except via Firestore metadata.
5

Today the app talks directly to about 12 backend services on one gateway host, plus public S3 files and Firebase. There is no single client-facing API: the device knows every service prefix, about 40 report dataset names, and the query syntax of each. The rewrite replaces all of this with one App Service (/gateway/urvi-app-service/api/v2/..., written /v2/... here; see App Service), the app's only backend. The bff column in the endpoint table below shows which App Service endpoint replaces each current call.

Path shorthands: A: = app/src/main/java/org/platformcommons/urvi/, D: = data/src/main/java/org/mindtree/app/agricultor/data/.

How the base URL and environment are chosen

The build type decides the environment. There are no product flavors and no buildConfigFields. The URLs are string resources in each build type's build_type_config.xml.

SettingDebugRelease
bridge_base_url / http_base_urlhttps://dev.platformcommons.org/https://login.platformcommons.org/
federation_url (AP-Gov / RYSS users)https://ryss.ap.gov.in/https://ryss.ap.gov.in/
asset_base_url (static JSON)S3 pcf-static-public-data/igx-static-data/same
  1. app/…/urvi/core/ApplicationClass.kt:65 sets the default base URL from bridge_base_url.
  2. If the account name looks like user@@ap.gov and federation is on, lines 66-75 switch the host to federation_url.
  3. Every Retrofit client reads BaseURLUtil.getBaseURL(context) (account-lib) when it is built.
  4. Service prefixes are set in app/…/urvi/core/ApplicationClass.kt:116-121: ctld (Common), ptld (Program), rtld (Reporting), ltld.

The result: debug builds send ap.gov users to production RYSS. Moving between prod and dev means editing commented-out XML blocks by hand.

HTTP stacks

Five stacks run side by side, with three JSON libraries (Gson, Jackson, Moshi).

StackWhereJSONUsed for
Retrofit APIInterfaceapp/…/urvi/datasource/network/retrofit/APIInterface.ktGsonMost online reads, telemetry, S3 files
Retrofit SetupService / SetupServiceNewdata/…/data/setup/SetupService.kt, data/…/data/setup_new/SetupServiceNew.ktJacksonData setup reads
Retrofit DeviceSessionApiapp/…/urvi/view/deviceregistration/DeviceSessionApi.ktGsonurvi-app-service device binding
Bridge CoreAPI Operationdata/…/data/manager/CoreAPIManager.kt (core-api, offline-core, offline-android libraries)Gson"Do it now" reads (dooNowOrThrow) and the offline write queue (dooWithRetry)
Generated Bridge APIsDataSetAPI, ProductAPI, AssessmentInstanceAssesseAPIGsonTenant user data, products, assessments

All Retrofit clients share one OkHttp client (data/…/data/net/OkHttpClientInterceptor.kt) with AuthInterceptor. CoreAPI uses its own Apache HttpClient.

Auth and headers

  • Login: account-lib's login screens sign in against the base URL host. The result is an Android Account (login@@tenant) in AccountManager. The session token is the AccountManager auth token. The password is also stored there in plain text.
  • The only header sent is X-SESSIONID (sometimes spelled X-Sessionid). There is no tenant, app-version or device-id header. X-APPID is defined (data/…/data/setup/SetupConstants.kt:11) but never sent.
  • Refresh: data/…/data/net/AuthInterceptor.kt re-authenticates and retries once on 401 or 400. Retrying on 400 is a bug: a validation error triggers a re-login.
  • Queued writes get the session id stamped when they are queued, so the stored token goes stale. BaseResponseHandler forces a new session on a gateway 500 (up to 5 attempts).
  • The offline queue adds X-REQUESTID (a random UUID per POST/PUT/PATCH, working as an idempotency key) and X-ACK-REQUESTID.
  • Device binding (release only): after login the app checks or registers the device with urvi-app-service. A mismatch blocks the app. Pending remote actions (LOGOUT, CLEAR_APP_DATA) run when the device-registration screen opens.
  • Hardcoded secrets (values not copied): APP_KEY at app/src/debug/res/values/build_type_config.xml:7 and app/src/release/res/values/build_type_config.xml:7; keystore passwords at app/build.gradle:25-28; keystore and Nexus credentials at app/config/signing.properties:1-3 and app/config/publish.properties:7-9; the keystore file itself is committed.

Dataset and criteria query style

Most reads do not call a REST resource. They run a named report dataset:

EnginePath
Legacy (rtld)GET /rtld/api/dataset/v1/execute?name=X&version=1&format=json&params=...
New (commons-report-service)GET /gateway/commons-report-service/api/v1/datasets/name/X/execute
  • Parameters are one string the device builds itself: KEY=value--KEY2=value, for example WORK_NODE_VO_ALIAS=...--LIMIT_OFFSET=0--LIMIT_ROW_COUNT=250.
  • Common-platform reads take SQL-like criteria built on the device: criteria=isActive=true AND iE.id in (...).
  • Some dataset names carry a season or year (AAP2025_26, PlusOneMasterFarmerIEID2425, IsKAP202324). Every new season needs an app release.
  • Ref-data paging uses HTTP 206 to mean "more pages".

Chattiness

MomentCallsDetail
Login4-5tenant user data, work-node hierarchy, device check or register, remote actions
Data setup for N farmersabout 10 + 4·⌈N/30⌉ + 3·⌈items/50⌉count, ⌈N/250⌉ farmer pages, then roles, assets, portfolios and farming models per 30 farmers, then attachments per 50 items, plus config
Data setup, 1,500 farmers300+each call has its own failure handling and resume prefs
Every Home cold startabout 15ref-data, AAP reject reasons, YouTube links, practices, crop list, two S3 files, tenant products, disabled lands, device check, remote actions, endorsements, comments, analytics, FCM subscribe, Remote Config
Per-farmer refresh6-10assets, asset attachments, portfolio, PLI attachments, farming model, its attachments, plus metrics
Create one farmer offline7+ queued opsIE, IE_FLAT, role map, assets, portfolio, crop photo, geofence, each waiting on the one before

Key problems

  1. Tight coupling. The device knows 12 service prefixes, about 40 dataset names, the params grammar and criteria syntax. A dataset rename breaks the app.
  2. Season-specific endpoints are hardcoded, so every season needs a release.
  3. Five HTTP stacks and three JSON libraries; geography lookups are duplicated in three classes.
  4. Fan-out at setup: hundreds of chunked calls instead of one paged snapshot.
  5. Writes need client-side orchestration: ordering and server-id back-fill live on the device in about 40 response handlers. A failure leaves partial server state.
  6. Get-or-create on read: opening a farmer POSTs to /ptld/.../worknodeietag/urvi.
  7. Uploads wait for parent server ids, and a Firebase Storage fallback bypasses the backend.
  8. Telemetry ships the raw sync queue (full bodies, including PII) every 6 hours, and to Firestore on errors.
  9. Auth quirks: re-login on 400, stale tokens on queued ops, no version or device headers, so the server cannot enforce a minimum app version.
  10. Push is broken and unsafe: the client was meant to hold a server key and send to topics every device receives.
  11. Debug builds hit production for ap.gov users.

What the App Service changes

TodayApp Service
12 services + S3 + FirebaseOne host per environment, chosen by URL only
Dataset names, criteria=, 206 paging, season names on the deviceHidden behind typed endpoints
X-SESSIONID onlyAuthorization, X-Tenant, X-App-Version, X-Device-Id, Idempotency-Key; server-enforced minimum version
~15 Home calls, 10-12 config callsPOST /v2/session/bootstrap + GET /v2/config (ETag / 304)
50-300+ setup callsGET /v2/farmers/snapshot (fully hydrated pages) + GET /v2/farmers/changes?since=
Ordered queue of per-entity writesPOST /v2/sync/batch keyed by client appId, idempotent; POST /v2/files for uploads
Client-sent FCM, topic broadcastServer push targeted by user and VO, via registered device tokens

Endpoint catalogue