APIs & services / portfolio-service

Download crop line-item attachments (photos, geofences) in bulk.

Endpointtoday's app
Call
GET /gateway/portfolio-service/api/v1/portfolios/line-items/portfoliosForLineItemIds?portfolioLineItemIds=&returnAllMimeType=true
Service
portfolio-service
Features
Data download (Cadre), Data download (Unit / FMT), Farmer hub (option tiles), Crop Actual (portfolio), Geofencing
When
Data download; per-farmer refresh
Auth
X-SESSIONID header (AuthInterceptor adds it; re-auth on 401/400)
In the App Service

Use case

Online bulk read of crop line item attachments after portfolios are downloaded (data download, unit data download, farmer hub refresh, SetupForUser). PLI ids are sent in chunks of 50; for each PLI the newest image becomes the PLI photo URL and the newest KML is written to files/geofencing and linked as the PLI geofence. Chunk failures are collected and the step fails with a combined message.

Headers

HeaderValueNotes
X-SESSIONID<session token>Added by AuthInterceptor (data/net/AuthInterceptor.kt) when the call does not set it; on HTTP 401 or 400 the interceptor invalidates the token, fetches a new one and retries the request once.

Parameters

ParamInRequiredExampleNotes
portfolioLineItemIdsqueryYes6001,6002CSV, chunk of 50.
returnAllMimeTypequeryNotrueSent as true by the 'Clean' variant (current callers); SetupForUser uses the older variant without it.

Request

No body. PLI ids (chunk 50/100)

Response

Example response body (synthetic data)
{
  "6001": [
    {
      "attachmentDateTime": "2026-07-01T10:15:00.000+05:30",
      "fileName": "pli_6001.jpg",
      "attachmentKind": "ATTACHMENT_KIND.IMAGE",
      "attachmentKindMetaData": null,
      "attachmentKindIdentifier": 6001,
      "attachmentUUID": "a1b2c3d4-0000-4000-8000-000000000401",
      "id": 88001,
      "uuid": "a1b2c3d4-0000-4000-8000-000000000402",
      "tempAttachmentURL": "https://<storage-host>/signed/pli_6001.jpg?sig=<redacted>",
      "appCreatedAt": "1780000000000"
    },
    {
      "attachmentDateTime": "2026-07-01T10:15:00.000+05:30",
      "fileName": "geofence_tile_0001.kml",
      "attachmentKind": "ATTACHMENT_KIND.GEOFENCE",
      "attachmentKindMetaData": "<?xml version=\"1.0\"?><kml>...polygon...</kml>",
      "attachmentKindIdentifier": 6001,
      "attachmentUUID": "a1b2c3d4-0000-4000-8000-000000000401",
      "id": 88002,
      "uuid": "a1b2c3d4-0000-4000-8000-000000000402",
      "tempAttachmentURL": "https://<storage-host>/signed/geofence_tile_0001.kml?sig=<redacted>",
      "appCreatedAt": "1780000000000"
    }
  ]
}
FieldTypeRequiredNotes
<pliId> (map key)stringPLI server id.
<pliId>[].idintegerAttachment id; highest id per type wins. Stored as imageAttachmentId / geoFenceAttachments / geoFencingFileId.
<pliId>[].fileNamestringExtension decides handling: .jpg/.jpeg/.png/.webp = photo, .kml = geofence.
<pliId>[].tempAttachmentURLstringSigned URL saved as the image URL (or KML path fallback).
<pliId>[].attachmentKindMetaDatastringFor KML, the file content; saved to files/geofencing/<fileName>.
<pliId>[].attachmentDateTimestringSaved as geoFencingCreatedOn.
<pliId>[].appCreatedAtstringSaved as imageCreatedAt.
<pliId>[].attachmentKind, attachmentKindIdentifier, attachmentUUID, uuidmixedDeserialised but not read by the app.

Errors

StatusWhenWhat the app does
401 / 400Session token expiredAuthInterceptor invalidates the token, gets a fresh session id and retries the request once.
any non-2xxOther failuresFailure added to a list; step throws joined messages; per-PLI parse errors are logged and skipped.

Source

  • data/src/main/java/org/mindtree/app/agricultor/data/setup/SetupService.kt
  • app/src/main/java/org/platformcommons/urvi/view/datasetup/DataSetupViewModel.kt
  • app/src/main/java/org/platformcommons/urvi/view/datasetup/UnitDataSetupViewModel.kt
  • app/src/main/java/org/platformcommons/urvi/view/option/OptionViewModel.kt
  • data/src/main/java/org/mindtree/app/agricultor/data/setup/SetupForUser.kt
  • data/src/main/java/org/mindtree/app/agricultor/data/setup/AttachmentResponse.kt