APIs & services
Every backend service the app calls today, and every live endpoint with who calls it and when.
| Service | Base path | Used for | Endpoints |
|---|---|---|---|
| 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¶ms=... | 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}/execute | New 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 data | https://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 users | Login (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 |
| Firebase | Firebase 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.
| Setting | Debug | Release |
|---|---|---|
bridge_base_url / http_base_url | https://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 |
app/…/urvi/core/ApplicationClass.kt:65sets the default base URL frombridge_base_url.- If the account name looks like
user@@ap.govand federation is on, lines 66-75 switch the host tofederation_url. - Every Retrofit client reads
BaseURLUtil.getBaseURL(context)(account-lib) when it is built. - 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).
| Stack | Where | JSON | Used for |
|---|---|---|---|
Retrofit APIInterface | app/…/urvi/datasource/network/retrofit/APIInterface.kt | Gson | Most online reads, telemetry, S3 files |
Retrofit SetupService / SetupServiceNew | data/…/data/setup/SetupService.kt, data/…/data/setup_new/SetupServiceNew.kt | Jackson | Data setup reads |
Retrofit DeviceSessionApi | app/…/urvi/view/deviceregistration/DeviceSessionApi.kt | Gson | urvi-app-service device binding |
Bridge CoreAPI Operation | data/…/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 APIs | DataSetAPI, ProductAPI, AssessmentInstanceAssesseAPI | Gson | Tenant 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 spelledX-Sessionid). There is no tenant, app-version or device-id header.X-APPIDis defined (data/…/data/setup/SetupConstants.kt:11) but never sent. - Refresh:
data/…/data/net/AuthInterceptor.ktre-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.
BaseResponseHandlerforces 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) andX-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_KEYatapp/src/debug/res/values/build_type_config.xml:7andapp/src/release/res/values/build_type_config.xml:7; keystore passwords atapp/build.gradle:25-28; keystore and Nexus credentials atapp/config/signing.properties:1-3andapp/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:
| Engine | Path |
|---|---|
| Legacy (rtld) | GET /rtld/api/dataset/v1/execute?name=X&version=1&format=json¶ms=... |
| 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 exampleWORK_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
| Moment | Calls | Detail |
|---|---|---|
| Login | 4-5 | tenant user data, work-node hierarchy, device check or register, remote actions |
| Data setup for N farmers | about 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 farmers | 300+ | each call has its own failure handling and resume prefs |
| Every Home cold start | about 15 | ref-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 refresh | 6-10 | assets, asset attachments, portfolio, PLI attachments, farming model, its attachments, plus metrics |
| Create one farmer offline | 7+ queued ops | IE, IE_FLAT, role map, assets, portfolio, crop photo, geofence, each waiting on the one before |
Key problems
- Tight coupling. The device knows 12 service prefixes, about 40 dataset names, the params grammar and criteria syntax. A dataset rename breaks the app.
- Season-specific endpoints are hardcoded, so every season needs a release.
- Five HTTP stacks and three JSON libraries; geography lookups are duplicated in three classes.
- Fan-out at setup: hundreds of chunked calls instead of one paged snapshot.
- 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.
- Get-or-create on read: opening a farmer POSTs to
/ptld/.../worknodeietag/urvi. - Uploads wait for parent server ids, and a Firebase Storage fallback bypasses the backend.
- Telemetry ships the raw sync queue (full bodies, including PII) every 6 hours, and to Firestore on errors.
- 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.
- Push is broken and unsafe: the client was meant to hold a server key and send to topics every device receives.
- Debug builds hit production for ap.gov users.
What the App Service changes
| Today | App Service |
|---|---|
| 12 services + S3 + Firebase | One host per environment, chosen by URL only |
Dataset names, criteria=, 206 paging, season names on the device | Hidden behind typed endpoints |
X-SESSIONID only | Authorization, X-Tenant, X-App-Version, X-Device-Id, Idempotency-Key; server-enforced minimum version |
| ~15 Home calls, 10-12 config calls | POST /v2/session/bootstrap + GET /v2/config (ETag / 304) |
| 50-300+ setup calls | GET /v2/farmers/snapshot (fully hydrated pages) + GET /v2/farmers/changes?since= |
| Ordered queue of per-entity writes | POST /v2/sync/batch keyed by client appId, idempotent; POST /v2/files for uploads |
| Client-sent FCM, topic broadcast | Server push targeted by user and VO, via registered device tokens |