Bin Scan

Retrieve TrueFruit Bin Scan measurements by orchard and date, including size, colour, blemish, picking quality, and optional intake or bin breakdowns.

Use these endpoints to retrieve fruit size, colour, blemish, picking quality, grade class, and defect data captured after fruit has been picked and scanned in bins. The data supports these response types:

  • Orchard-level results (granularity: orchard) — Returns distributions aggregated across all scanned bins for a specific orchard and measurement date.
  • Bin results (granularity: bin) — Returns distributions per bin in bin_distributions.
  • Intake results (granularity: bin_group) — Returns distributions per intake in bin_group_distributions.
  • Picking team results (granularity: picking_team or granularity: bin_group_picking_team) — Returns distributions per picking team in picking_team_distributions or per intake and picking team pair in bin_group_picking_team_distributions.
  • Harvest event results (granularity: harvest_event) — Returns distributions per mobile-app harvest event in harvest_event_distributions.

The measurements endpoint lists measurements by orchard and date, while the detail endpoint returns full distributions for a single orchard and date. Use granularity on the detail endpoint when you need a breakdown. The size distribution endpoint returns an orchard-level size distribution for a single orchard and date, optionally filtered by blemish category. Grade class, picking quality, and categorised defect results are supported only for certain crops. These fields can be null for unsupported crops; grade class results can also be null when a measurement has not been graded, and categorised defect results when none are available.

Recommended patterns for fetching TrueFruit bin scan data

How to fetch Bin Scan size and grade distributions per orchard

  1. First pull per orchard size measurement dates for a given time period using the farming/truefruit/binscan/measurements/ endpoint. The response returns a list of objects containing an orchard_id and measurement_date. Filter the response using the processed_date query parameter. Using the processed_date is the most robust approach because it avoids missing records where there was a delay between when the data was collected and when it became available to consume. If you are fetching data on a cron, for example once a day, use the date you last fetched data on.
  2. To fetch the detailed orchard distributions and aggregated metrics, pass the orchard_id and measurement_date received in the farming/truefruit/binscan/measurements/ response into the farming/truefruit/binscan/measurements/{orchard_id}/{measurement_date} endpoint. By default, the response returns orchard-level aggregates.

How to fetch an orchard-level size distribution filtered by blemish category

  1. Retrieve orchard_id and measurement_date from farming/truefruit/binscan/measurements/, using the processed_date filter described above when fetching new measurements.
  2. Pass those values to farming/truefruit/binscan/measurements/{orchard_id}/{measurement_date}/size_distribution/. Add blemish_filters to include only fruit in the selected blemish categories; if you pass multiple categories, select a consecutive range. This endpoint returns an orchard-level size distribution, not bin or intake breakdowns.

How to fetch Bin Scan size and grade distributions per intake

  1. First pull per orchard size measurement dates for a given time period using the farming/truefruit/binscan/measurements/ endpoint.
  2. Pass the orchard_id and measurement_date received in the measurements response into the farming/truefruit/binscan/measurements/{orchard_id}/{measurement_date} endpoint.
  3. Set granularity=bin_group to retrieve intake records in bin_group_distributions. Each record includes bin_group_id, the external intake, shipment, or delivery number, which can be null for bins without one. Intake rows also appear in bin_distributions for backward compatibility; use bin_group_distributions for new integrations.

Optional parameters

Use these query parameters on the detailed endpoint when you need a different response shape:

ParameterTypeDefaultDescription
granularitystringorchardSelect orchard, bin, bin_group, picking_team, bin_group_picking_team, or harvest_event. Non-orchard results appear in the corresponding *_distributions array described above.
size_distribution_formatstringharvest_ranges_by_piecesSelect 1mm, 2mm, 2.5mm, 5mm, harvest_ranges_by_weight, or harvest_ranges_by_pieces. harvest_ranges is deprecated.
bloom_numberinteger1Select a bloom for crops that flower more than once per season; values range from 1 to 6.
grade_classescomma-separated grade class labelsNo filterRestrict size, colour, blemish, and defect distributions at every level to fruit in these classes. Use labels from grade_class_distribution, such as Class 3. Picking quality and grade class distributions still cover every class. Requires a harvest-range size_distribution_format, not a millimetre interval.

Bin Scan Measurement Compact

KeyTypeDescription
farm_idintegerThe unique identifier of the farm, provided by Aerobotics, which the measurement belongs to.
orchard_idintegerThe unique identifier of the orchard, provided by Aerobotics, which the measurement belongs to.
measurement_datedateThe date on which the data was collected.
processed_datedateThe date on which the data completed processing.
average_fruit_size_mmnumberThe average fruit size of the distribution in millimeters.
count_fruit_measuredintegerTotal number of fruit included in the size distribution.

Example response

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "farm_id": 1234,
      "orchard_id": 5678,
      "measurement_date": "2025-11-15",
      "processed_date": "2025-11-16",
      "average_fruit_size_mm": 67.4,
      "count_fruit_measured": 8420
    }
  ]
}

Bin Scan Measurement Detailed

KeyTypeDescription
farm_idintegerThe unique identifier of the farm, provided by Aerobotics, which the measurement belongs to.
orchard_idintegerThe unique identifier of the orchard, provided by Aerobotics, which the measurement belongs to.
measurement_datedateThe date on which the data was collected.
processed_datedateThe date on which the data completed processing.
size_distribution[][Size Distribution Record]The size distribution of fruit bucketed by either mm ranges or harvest size categories.
average_fruit_size_mmnumberThe average fruit size of the distribution in millimeters.
count_fruit_measuredintegerTotal number of fruit included in the size distribution.
blemish_distribution[][Grade Distribution Record] | nullAn array of grade distribution records that can be used to build a histogram of blemish severity.
color_distribution[][Grade Distribution Record] | nullAn array of grade distribution records that can be used to build a histogram of fruit colour categories.
count_binsintegerThe number of bins measured.
bin_distributions[][Bin Distribution Record]Per-bin records when granularity=bin. Also contains intake rows when granularity=bin_group for backward compatibility; use bin_group_distributions instead.
bin_group_distributions[][Bin Group Distribution Record]Per-intake records when granularity=bin_group.
picking_team_distributions[][Picking Team Distribution Record]Per-picking-team records when granularity=picking_team.
bin_group_picking_team_distributions[][Bin Group Picking Team Distribution Record]Per-intake and picking-team records when granularity=bin_group_picking_team.
harvest_event_distributions[][Harvest Event Distribution Record]Per-harvest-event records when granularity=harvest_event.
picking_quality[Picking Quality Record] | nullOrchard-level picking quality summary for supported crops; can be null for unsupported crops.
grade_class_distribution[][Grade Class Percentage Record] | nullShare of fruit in each configured grade class, in grade class order. Supported for certain crops; null when not graded or unsupported.
defect_distribution[][Defect Category Record] | nullShare of assessed fruit in each defect category. Supported for certain crops; null when categorised results are unavailable or the crop is unsupported.

Bin Scan Size Distribution

Use GET /farming/truefruit/binscan/measurements/{orchard_id}/{measurement_date}/size_distribution/ to retrieve the orchard-level size distribution, optionally limited to selected blemish categories. This endpoint does not return bin or intake breakdowns.

ParameterTypeDefaultDescription
orchard_id (path)integerRequiredIdentifier of the orchard from the measurements response.
measurement_date (path)date string (YYYY-MM-DD)RequiredDate the measurement was collected, from the measurements response.
size_distribution_format (query)stringharvest_ranges_by_piecesSelect 1mm, 2mm, 2.5mm, 5mm, harvest_ranges_by_weight, or harvest_ranges_by_pieces. harvest_ranges is deprecated.
bloom_number (query)integer1Select a bloom for crops that flower more than once per season; values range from 1 to 6.
blemish_filters (query)comma-separated blemish categoriesNo filterInclude fruit from one category or consecutive categories in this order: Unblemished, Slight, Moderate, Significant, Severe. For example, blemish_filters=Slight,Moderate selects adjacent categories; Slight,Severe is not a valid consecutive range.
limit (query)integerNot specifiedNumber of results per page, as listed in the endpoint definition.
offset (query)integerNot specifiedInitial result index, as listed in the endpoint definition.

The response is a single object, not a paginated list. The endpoint definition lists limit and offset but does not describe their effect on this response.

KeyTypeDescription
farm_idintegerUnique identifier of the farm.
orchard_idintegerUnique identifier of the orchard.
measurement_datedateDate on which the data was collected.
processed_datedateDate on which the data completed processing.
size_distribution[][Size Distribution Record]Orchard-level size distribution in millimetre ranges or harvest size categories. With blemish_filters, includes only fruit in the selected categories.
average_fruit_size_mmnumberAverage fruit size of the distribution in millimetres.
count_fruit_measuredintegerTotal number of fruit included in the size distribution.

Example response without blemish_filters (illustrative values):

{
  "farm_id": 1234,
  "orchard_id": 5678,
  "measurement_date": "2025-11-15",
  "processed_date": "2025-11-16",
  "size_distribution": [
    {"bin_range": "64-65", "percentage": 18.0, "label": null},
    {"bin_range": "66-67", "percentage": 41.5, "label": null},
    {"bin_range": "68-69", "percentage": 40.5, "label": null}
  ],
  "average_fruit_size_mm": 67.4,
  "count_fruit_measured": 8420
}

A missing measurement returns 404 with {"detail": "No data found"}. A temporary server failure returns 500 with {"detail": "Unable to complete request at this stage. Please try again shortly"}.

Size Distribution Record

KeyTypeDescription
bin_rangestringSize range of the histogram bin in millimeters.
percentagenumberPercentage of fruit sizes that fall within the corresponding bin range.
labelstring | nullName of the histogram bin range. Typically the harvest size category names. (optional)

Grade Distribution Record

KeyTypeDescription
labelstringName of the histogram bin range defined by Aerobotics colour or blemish severity labels.
percentagenumberPercentage of fruit that fall within the corresponding colour or blemish category.

Picking Quality Record

KeyTypeDescription
count_visible_stemsintegerNumber of fruit with visible stems in the image.
picking_quality_types[][Picking Quality Type Record]A list of picking quality types and their percentage of fruit in each type.

Picking Quality Type Record

KeyTypeDescription
labelstringPicking quality type label. Classes include good_stem, long_stem, and pulled_stem.
percentagenumberPercentage of fruit that fall within the corresponding picking quality type.

Grade Class Percentage Record

KeyTypeDescription
labelstringGrade class label configured in grade settings, such as Class 1 or Juice.
percentage_by_piecesnumber | nullPercentage of fruit by count in the grade class.
percentage_by_weightnumber | nullPercentage of fruit by weight in the grade class.

Defect Category Record

KeyTypeDescription
labelstring | nullConfigured defect category, such as noDefect, possibleRisk, progressive, or cosmetic. null groups uncategorised defect types. Categories may be added or renamed.
percentagenumberPercentage of assessed fruit in the category. noDefect comes first, followed by other categories in descending order.
defect_types[][Defect Type Percentage Record]Detected defect types in the category, largest first. Undetected types are omitted.

Defect Type Percentage Record

KeyTypeDescription
labelstringDetected defect type, such as mould_rot or scarring.
percentagenumberPercentage of assessed fruit with the defect type.

Bin Distribution Record

The following fields describe per-bin records when granularity=bin. Other breakdowns share the distribution and summary fields, but have different identifiers as described below.

KeyTypeDescription
bin_idintegerUnique identifier for a bin. Returned when available.
bin_external_idstring | nullExternal system identifier for a bin. Returned when available.
bin_fruit_weight_gnumber | nullFruit weight in grams, manually captured on the Aerobotics mobile app when available.
bin_group_idstring | nullExternal bin shipment, intake, or delivery number. Returned when available.
latitudenumber | nullLatitude of the bin location.
longitudenumber | nullLongitude of the bin location.
blemish_distribution[][Grade Distribution Record] | nullBlemish severity distribution.
color_distribution[][Grade Distribution Record] | nullColour distribution.
size_distribution[][Size Distribution Record]Size distribution.
average_fruit_size_mmnumberAverage fruit size in millimeters.
count_fruit_measuredintegerTotal number of fruit included in the size distribution.
count_binsintegerNumber of bins covered by the distributions.
picking_quality[Picking Quality Record] | nullPicking quality summary for supported crops; can be null for unsupported crops.
grade_class_distribution[][Grade Class Percentage Record] | nullGrade class shares for supported crops; null when bins have not been graded or the crop is unsupported.
defect_distribution[][Defect Category Record] | nullCategorised defect shares for supported crops; null when results are unavailable or the crop is unsupported.

Bin Group Distribution Record

Each record in bin_group_distributions contains the distribution and summary fields from the Bin Distribution Record (blemish_distribution, color_distribution, size_distribution, average_fruit_size_mm, count_fruit_measured, count_bins, picking_quality, grade_class_distribution, and defect_distribution), plus:

KeyTypeDescription
bin_group_idstring | nullExternal shipment, intake, or delivery number. null for bins without one.

Picking Team Distribution Record

Each record in picking_team_distributions contains the distribution and summary fields listed in the Bin Group Distribution Record, plus:

KeyTypeDescription
picking_team_namestring | nullName of the team that harvested the bins. null for bins without one.

Bin Group Picking Team Distribution Record

Each record in bin_group_picking_team_distributions contains the distribution and summary fields listed in the Bin Group Distribution Record, plus:

KeyTypeDescription
bin_group_idstring | nullExternal shipment, intake, or delivery number. null for bins without one.
picking_team_namestring | nullName of the team that harvested the bins. null for bins without one.

Harvest Event Distribution Record

Each record in harvest_event_distributions contains the distribution and summary fields listed in the Bin Group Distribution Record, plus:

KeyTypeDescription
bin_group_idstring | nullExternal shipment, intake, or delivery number. null for bins without one.
picking_team_namestring | nullName of the team that harvested the bins. null for bins without one.
timedate-time | nullTime the harvest event was logged on the mobile app.
notestring | nullNote logged with the harvest event.

The following detail responses are illustrative. Optional fields may be absent; grade class and categorised defect results can be null as described above.

Example orchard-level response

{
  "farm_id": 1234,
  "orchard_id": 5678,
  "measurement_date": "2025-11-15",
  "processed_date": "2025-11-16",
  "size_distribution": [
    {
      "bin_range": "64-65",
      "percentage": 18.0,
      "label": null
    },
    {
      "bin_range": "66-67",
      "percentage": 41.5,
      "label": null
    },
    {
      "bin_range": "68-69",
      "percentage": 40.5,
      "label": null
    }
  ],
  "average_fruit_size_mm": 67.4,
  "count_fruit_measured": 8420,
  "blemish_distribution": [],
  "color_distribution": [],
  "count_bins": 24,
  "picking_quality": {
    "count_visible_stems": 214,
    "picking_quality_types": [
      {
        "label": "good_stem",
        "percentage": 83.2
      },
      {
        "label": "long_stem",
        "percentage": 10.5
      },
      {
        "label": "pulled_stem",
        "percentage": 6.3
      }
    ]
  },
  "grade_class_distribution": [
    {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
    {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
  ],
  "defect_distribution": [
    {"label": "noDefect", "percentage": 83.2, "defect_types": []},
    {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
  ]
}

Example response with granularity=bin_group (read intake rows from bin_group_distributions)

{
  "farm_id": 1234,
  "orchard_id": 5678,
  "measurement_date": "2025-11-15",
  "processed_date": "2025-11-16",
  "size_distribution": [
    {"bin_range": "64-65", "percentage": 18.0, "label": null},
    {"bin_range": "66-67", "percentage": 41.5, "label": null},
    {"bin_range": "68-69", "percentage": 40.5, "label": null}
  ],
  "average_fruit_size_mm": 67.4,
  "count_fruit_measured": 8420,
  "blemish_distribution": [],
  "color_distribution": [],
  "count_bins": 24,
  "grade_class_distribution": [
    {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
    {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
  ],
  "defect_distribution": [
    {"label": "noDefect", "percentage": 83.2, "defect_types": []},
    {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
  ],
  "bin_group_distributions": [
    {
      "bin_group_id": "intake-001",
      "size_distribution": [
        {"bin_range": "64-65", "percentage": 24.0, "label": null},
        {"bin_range": "66-67", "percentage": 39.0, "label": null},
        {"bin_range": "68-69", "percentage": 37.0, "label": null}
      ],
      "average_fruit_size_mm": 67.1,
      "count_fruit_measured": 4010,
      "count_bins": 12,
      "blemish_distribution": [],
      "color_distribution": [],
      "picking_quality": {
        "count_visible_stems": 96,
        "picking_quality_types": [
          {"label": "good_stem", "percentage": 81.0},
          {"label": "long_stem", "percentage": 12.0},
          {"label": "pulled_stem", "percentage": 7.0}
        ]
      },
      "grade_class_distribution": [
        {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
        {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
      ],
      "defect_distribution": [
        {"label": "noDefect", "percentage": 83.2, "defect_types": []},
        {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
      ]
    }
  ]
}

Example response with granularity=bin

{
  "farm_id": 1234,
  "orchard_id": 5678,
  "measurement_date": "2025-11-15",
  "processed_date": "2025-11-16",
  "size_distribution": [
    {
      "bin_range": "64-65",
      "percentage": 18.0,
      "label": null
    },
    {
      "bin_range": "66-67",
      "percentage": 41.5,
      "label": null
    },
    {
      "bin_range": "68-69",
      "percentage": 40.5,
      "label": null
    }
  ],
  "average_fruit_size_mm": 67.4,
  "count_fruit_measured": 8420,
  "blemish_distribution": [],
  "color_distribution": [],
  "count_bins": 24,
  "grade_class_distribution": [
    {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
    {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
  ],
  "defect_distribution": [
    {"label": "noDefect", "percentage": 83.2, "defect_types": []},
    {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
  ],
  "bin_distributions": [
    {
      "bin_id": 9001,
      "bin_external_id": "BIN-001",
      "bin_fruit_weight_g": null,
      "latitude": -33.9249,
      "longitude": 18.4241,
      "size_distribution": [
        {
          "bin_range": "64-65",
          "percentage": 22.0,
          "label": null
        },
        {
          "bin_range": "66-67",
          "percentage": 38.0,
          "label": null
        },
        {
          "bin_range": "68-69",
          "percentage": 40.0,
          "label": null
        }
      ],
      "average_fruit_size_mm": 67.3,
      "count_fruit_measured": 2050,
      "count_bins": 1,
      "blemish_distribution": [],
      "color_distribution": [],
      "picking_quality": {
        "count_visible_stems": 52,
        "picking_quality_types": [
          {
            "label": "good_stem",
            "percentage": 82.0
          },
          {
            "label": "long_stem",
            "percentage": 11.0
          },
          {
            "label": "pulled_stem",
            "percentage": 7.0
          }
        ]
      },
      "grade_class_distribution": [
        {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
        {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
      ],
      "defect_distribution": [
        {"label": "noDefect", "percentage": 83.2, "defect_types": []},
        {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
      ]
    }
  ]
}

Example response with granularity=picking_team (read team rows from picking_team_distributions)

{
  "farm_id": 1234,
  "orchard_id": 5678,
  "measurement_date": "2025-11-15",
  "processed_date": "2025-11-16",
  "size_distribution": [
    {"bin_range": "64-65", "percentage": 18.0, "label": null},
    {"bin_range": "66-67", "percentage": 41.5, "label": null},
    {"bin_range": "68-69", "percentage": 40.5, "label": null}
  ],
  "average_fruit_size_mm": 67.4,
  "count_fruit_measured": 8420,
  "blemish_distribution": [],
  "color_distribution": [],
  "count_bins": 24,
  "grade_class_distribution": [
    {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
    {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
  ],
  "defect_distribution": [
    {"label": "noDefect", "percentage": 83.2, "defect_types": []},
    {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
  ],
  "picking_team_distributions": [
    {
      "picking_team_name": "Team A",
      "size_distribution": [
        {"bin_range": "64-65", "percentage": 22.0, "label": null},
        {"bin_range": "66-67", "percentage": 38.0, "label": null},
        {"bin_range": "68-69", "percentage": 40.0, "label": null}
      ],
      "average_fruit_size_mm": 67.3,
      "count_fruit_measured": 2050,
      "count_bins": 6,
      "blemish_distribution": [],
      "color_distribution": [],
      "picking_quality": null,
      "grade_class_distribution": [
        {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
        {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
      ],
      "defect_distribution": [
        {"label": "noDefect", "percentage": 83.2, "defect_types": []},
        {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
      ]
    }
  ]
}

Example response with granularity=harvest_event&bloom_number=2&grade_classes=Class%203

Pass the grade class label as a URL-encoded query value. The size_distribution_format defaults to harvest_ranges_by_pieces, which is compatible with grade_classes. bloom_number=2 selects the second bloom; the response has no separate bloom-number field. The grade class distribution and picking quality are not narrowed by grade_classes.

{
  "farm_id": 1234,
  "orchard_id": 5678,
  "measurement_date": "2025-11-15",
  "processed_date": "2025-11-16",
  "size_distribution": [{"bin_range": "64-65", "percentage": 100.0, "label": "Class 3"}],
  "average_fruit_size_mm": 67.4,
  "count_fruit_measured": 8420,
  "blemish_distribution": [],
  "color_distribution": [],
  "count_bins": 24,
  "grade_class_distribution": [
    {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
    {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
  ],
  "defect_distribution": [
    {"label": "noDefect", "percentage": 83.2, "defect_types": []},
    {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
  ],
  "picking_quality": null,
  "harvest_event_distributions": [
    {
      "bin_group_id": "intake-001",
      "picking_team_name": "Team A",
      "time": "2025-11-15T10:30:00Z",
      "note": null,
      "size_distribution": [{"bin_range": "64-65", "percentage": 100.0, "label": "Class 3"}],
      "average_fruit_size_mm": 67.1,
      "count_fruit_measured": 4010,
      "count_bins": 12,
      "blemish_distribution": [],
      "color_distribution": [],
      "grade_class_distribution": [
        {"label": "Class 1", "percentage_by_pieces": 41.5, "percentage_by_weight": 40.8},
        {"label": "Class 3", "percentage_by_pieces": 58.5, "percentage_by_weight": 59.2}
      ],
      "defect_distribution": [
        {"label": "noDefect", "percentage": 83.2, "defect_types": []},
        {"label": "cosmetic", "percentage": 16.8, "defect_types": [{"label": "scarring", "percentage": 16.8}]}
      ],
      "picking_quality": null
    }
  ]
}

Recipes