API contracts / App Service v2 / Crops & harvest

A farmer's Crop Actual blocks for a season / month

OperationlistFarmerCropBlocks
Call
GET /gateway/urvi-app-service/api/v2/farmers/{farmerId}/crop-blocks
Group
Crops & harvest
Features
Crop Actual (portfolio), Crop Actual harvest, PMDS and A Grade crop details, Compact Block
Replaces today

Use case. Called online by Crop Actual on swipe-to-refresh (when the farmer is synced and the interval has passed), after a PART_OF_COMPACT_BLOCK rejection, and as the online source for month copy-forward (last month's blocks). Returns blocks with crops, practices, PMDS / A Grade details, photo and geofence URLs, harvest status and compact-block link.

Rules.

  • Only the latest version per tileId unless allVersions=true.

Error codes. NOT_FOUND

Parameters

NameInTypeRequiredMeaningExample
X-App-VersionheaderstringYesApp version `major.minor.patch+build`. Too old -> 426 `VERSION_TOO_OLD`. · pattern ^\d+\.\d+\.\d+(\+\d+)?$2.0.0+200
X-Device-Idheaderstring (uuid)YesApp-scoped device UUID (not ANDROID_ID).6b1f2c3d-0000-4000-8000-00000000d001
X-Request-Idheaderstring (uuid)NoClient-generated request id for tracing; echoed in responses and problems.0e0c5a1b-0000-4000-8000-0000000000a1
Accept-LanguageheaderstringNoLanguage for messages and labels. · one of en, te, ta; default "en"te
X-TenantheaderstringNoTenant code; must match the token. Urvi: `ap.gov`. · one of ap.govap.gov
farmerIdpathstringYesFarmer server id or client UUID (`aliasId`). With a UUID unknown to the server, the farmer is created from the flat master record (get-or-create). · min length 1; max length 643f6c1a2e-0000-4000-8000-00000000f001
seasonquerystringNo`current`, `previous` or an explicit season like `2025-26`; the server maps it to year-specific datasets. · pattern ^(current|previous|\d{4}-\d{2})$; default "current"current
monthquerystringNo`yyyy-MM`; default current month. · pattern ^\d{4}-(0[1-9]|1[0-2])$2025-10
allVersionsquerybooleanNoInclude every monthly version. · default falsefalse

Request

No body.

Responses

200 Crop blocks.

Schema CropBlock.

Example 200 body
[
  {
    "id": 840001,
    "clientId": "5b8e3c4a-0000-4000-8000-000000008193",
    "version": 4,
    "createdAt": "2025-10-01T08:00:00+05:30",
    "updatedAt": "2025-10-14T09:30:00+05:30",
    "active": true,
    "farmerId": 700001,
    "farmerClientId": "3f6c1a2e-0000-4000-8000-000000061441",
    "landId": 810001,
    "landClientId": "4a7d2b3f-0000-4000-8000-000000004097",
    "landChecksum": "c1a5e0d7",
    "tileId": "TILE-840001",
    "planType": "SEASON_ACTUAL",
    "season": "2025-26",
    "month": "2025-10",
    "cropType": "AGRICULTURE",
    "crops": [
      {
        "clientId": "5b8e3c4a-0000-4000-8000-000000008449",
        "id": 841001,
        "productCode": "PADDY",
        "acres": 1.5,
        "isMajor": true,
        "seedVariety": "BPT-5204",
        "expectedHarvestDate": "2025-12-15",
        "harvestStatus": "NOT_STARTED",
        "placeholder": false
      },
      {
        "clientId": "5b8e3c4a-0000-4000-8000-000000008450",
        "id": 841002,
        "productCode": "RED_GRAM",
        "acres": 0.5,
        "isMajor": false,
        "harvestStatus": "NOT_STARTED",
        "placeholder": false
      }
    ],
    "practiceCodes": [
      "AP-GOV-KAP-100_PERCENT_CHEMICAL_FREE_NATURAL_FARMING",
      "AP-GOV-KAP-BEEJAMRUTHAM"
    ],
    "sowingDate": "2025-07-10",
    "photo": {
      "fileId": "7a6b5c4d-0000-4000-8000-000000000225",
      "kind": "PHOTO_CROP",
      "url": "https://files.example.invalid/urvi/signed/crop-840001.jpg"
    },
    "geofence": {
      "polygon": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              80.1001,
              16.5001
            ],
            [
              80.1012,
              16.5001
            ],
            [
              80.1012,
              16.501
            ],
            [
              80.1001,
              16.501
            ],
            [
              80.1001,
              16.5001
            ]
          ]
        ]
      },
      "captureMethod": "OSM_MOTION",
      "accuracyM": 4.5,
      "pointCount": 4,
      "capturedAt": "2025-10-14T09:30:00+05:30",
      "areaAcres": 2.4,
      "kmlUrl": "https://files.example.invalid/urvi/signed/land-1001.kml"
    },
    "changeLog": [],
    "compactBlockId": 860001,
    "editable": false,
    "totalAcres": 2
  }
]
FieldTypeRequiredRulesMeaning
idinteger (int64)Noserver-setServer id (assigned by the App Service).
clientIdstring (uuid)YesClient-generated UUID (the app's `appId`/`aliasId`). Stable for the life of the entity and used for idempotent creates and parent references.
versioninteger (int64)No≥ 1; server-setMonotonic server version; send as `baseVersion` on updates.
createdAtstring (date-time)Noserver-set
updatedAtstring (date-time)Noserver-set
activebooleanNoFalse once soft-deleted / disabled.
farmerIdinteger (int64)NoServer id (assigned by the App Service).
farmerClientIdstring (uuid)No
landIdinteger (int64)NoServer id (assigned by the App Service).
landClientIdstring (uuid)NoLand, by client UUID (may be created earlier in the same batch).
landChecksumstringNoChecksum of the land when the block was edited; stale -> `LAND_CHECKSUM_MISMATCH`.
tileIdstringNoStable tile id (was `titleId`) shared by every monthly version of the block.
planTypestringNoone of SEASON_ACTUAL, PLANNEDSEASON_ACTUAL = Crop Actual (PLANNED is legacy Crop Plan, read-only).
seasonstringNopattern ^\d{4}-\d{2}$Season label, e.g. `2025-26`.
monthstringNopattern ^\d{4}-(0[1-9]|1[0-2])$Calendar month, `yyyy-MM`.
cropTypeCropTypeNoone of AGRICULTURE, HORTICULTURE, POLYCROPPING, PMDS, RDS, A_GRADE, NO_NF_CROP
cropTypeChangeReasonstringNoone of WRONG_ENTRY, SOIL_INCORPORATION, INTEGRATION_WITH_KHARIF, CROP_FAILED, HARVEST_COMPLETE, OTHER
cropTypeChangeReasonTextstringNopattern ^[A-Za-z0-9\-() ]*$; max length 100
cropsCropLine[]Nomin items 1Main crops; >= 1. A_GRADE allows exactly 1; PMDS is the `AP_GOV_PMDS` crop.
practiceCodesstring[]Nomin items 1NF practices; >= 1 (`PRACTICE_REQUIRED`).
sowingDatestring (date)NoBetween today minus `formLimits.cropBlock.sowingLookbackMonths` and today (`SOWING_DATE_OUT_OF_RANGE`).
pmdsPmdsDetailsNo
aGradeAGradeDetailsNoA Grade: exactly one main crop (`A_GRADE_CROP_COUNT`) and >= 2 associated and bio-diversity crops (`A_GRADE_ASSOCIATED_CROPS_MIN`).
photoAttachmentNo
geofenceGeofenceNoBoundary of a land parcel, crop block or ATM plot. Send `polygon` or `kmlFileId` (or both).
changeLogCropChange[]No
compactBlockIdinteger | null (int64)Noserver-setServer id (assigned by the App Service).
editablebooleanNoserver-setFalse when in a compact block, land disabled or harvested.
totalAcresnumber (double)Noserver-setSum of crop acres. Unit: acres.

400 Malformed request or schema violation.

Schema Problem.

Example 400 body
{
  "type": "https://urvi.example.invalid/problems/validation-failed",
  "title": "Validation failed",
  "status": 400,
  "detail": "One or more fields are invalid.",
  "code": "VALIDATION_FAILED",
  "requestId": "0e0c5a1b-0000-4000-8000-0000000000a1",
  "errors": [
    {
      "field": "/mobile",
      "code": "INVALID_MOBILE",
      "message": "Mobile must be 10 digits starting 6-9."
    }
  ]
}

401 Missing, invalid or expired access token. Refresh once, then ask the user to log in; pending outbox ops stay intact.

Schema Problem.

Example 401 body
{
  "type": "https://urvi.example.invalid/problems/token-expired",
  "title": "Session expired",
  "status": 401,
  "detail": "The access token has expired.",
  "code": "TOKEN_EXPIRED",
  "requestId": "0e0c5a1b-0000-4000-8000-0000000000a1"
}

403 Authenticated but not allowed (role, tenant, device binding or feature switch).

Schema Problem.

Example 403 body
{
  "type": "https://urvi.example.invalid/problems/role-not-allowed",
  "title": "Not allowed",
  "status": 403,
  "detail": "Your role cannot perform this action.",
  "code": "ROLE_NOT_ALLOWED",
  "requestId": "0e0c5a1b-0000-4000-8000-0000000000a1"
}

404 Resource not found or outside the user's work nodes.

Schema Problem.

Example 404 body
{
  "type": "https://urvi.example.invalid/problems/not-found",
  "title": "Not found",
  "status": 404,
  "detail": "No such resource in your work area.",
  "code": "NOT_FOUND",
  "requestId": "0e0c5a1b-0000-4000-8000-0000000000a1"
}

426 App version below the minimum; block the UI with an update prompt. Pending outbox ops are kept.

Schema Problem.

Example 426 body
{
  "type": "https://urvi.example.invalid/problems/version-too-old",
  "title": "Update required",
  "status": 426,
  "detail": "Please update Urvi to continue.",
  "code": "VERSION_TOO_OLD",
  "requestId": "0e0c5a1b-0000-4000-8000-0000000000a1",
  "minAppVersion": "2.0.0"
}

429 Rate limited per device / user. Respect `Retry-After`.

Schema Problem.

Example 429 body
{
  "type": "https://urvi.example.invalid/problems/rate-limited",
  "title": "Too many requests",
  "status": 429,
  "detail": "Slow down and retry later.",
  "code": "RATE_LIMITED",
  "requestId": "0e0c5a1b-0000-4000-8000-0000000000a1",
  "retryAfterSeconds": 30
}

500 Unexpected server error; retry with backoff (writes are idempotent).

Schema Problem.

Example 500 body
{
  "type": "https://urvi.example.invalid/problems/internal-error",
  "title": "Server error",
  "status": 500,
  "detail": "Something went wrong. Please try again.",
  "code": "INTERNAL_ERROR",
  "requestId": "0e0c5a1b-0000-4000-8000-0000000000a1"
}