Skip to content

Qualifications

Every program returned by GET /programs can include a qualifications array and an optional qualifier expression. Qualifications define conditions that must be met before a participant's potential earnings are considered qualified — they gate whether an offer pays out at all.

There are currently seven qualification types: aggregated_amount, aggregated_quantity, brand_count, share_of_wallet_percent, yoy_amount_index, amount_average_index, and property.


At a Glance

Qualification Type What It Measures Typical Use Case
Aggregated Amount Total dollar amount of matching transactions "Buy at least $100,000 of crop protection to qualify"
Aggregated Quantity Total quantity of matching transactions "Purchase at least 500 gallons to qualify"
Brand Count Count of distinct matching brands "Buy across at least 2 herbicide brands to qualify"
Share of Wallet Percent Ratio of one product group's volume to another "At least 30% of your herbicide acres must be our brand"
YoY Amount Index Year-over-year dollar comparison "Purchase the same or more than last year"
Amount Average Index Comparison of amounts with averaging "Current year purchases must meet or exceed the 3-year average"
Property An externally provided value from the request "Business plan must be marked as achieved"

Core Concepts

Qualification vs. Qualifier

These two terms are related but distinct:

  • Qualification — a single measurable condition (e.g., "total purchases ≥ $50,000"). Each qualification evaluates independently and produces a met / not met result.
  • Qualifier — a boolean expression that combines one or more qualification results using AND / OR logic to determine the final qualified status for a program or offer. For example: "purchase_volume AND (loyalty_tier OR business_plan_achieved)".

If no qualifier expression is provided, the program or offer is considered qualified by default.

Evaluation Levels

Qualifications can be defined at two levels:

Level Scope Effect
Program All offers in the program If the program qualifier evaluates to false, none of its offers are evaluated
Offer A single offer If the offer qualifier evaluates to false, that specific offer does not pay out

Program-level qualifications are evaluated first. Only offers belonging to qualified programs proceed to offer-level qualification evaluation.

Operators

Every qualification compares an actual computed value against a target using an operator:

Operator Meaning
greater_than_or_equal_to Actual must be ≥ target
greater_than Actual must be > target
less_than_or_equal_to Actual must be ≤ target
less_than Actual must be < target
equal_to Actual must exactly equal target

Waiving Qualifications

Qualifications can be waived per request by passing a waive_qualifications property in the calculation request. A waived qualification is treated as met regardless of the actual computed value — the waived: true flag is set in the response while met reflects the real evaluation.

{
  "properties": [
    {
      "type": "waive_qualifications",
      "key": "waive_qualifications",
      "value": [
        {
          "program_key": "corteva.2026.retailer.national.crop_protection",
          "qualification_key": "minimum_purchase_volume",
          "offer_key": null
        }
      ]
    }
  ]
}

When offer_key is null, the waiver applies to the qualification at the program level. When an offer_key is specified, only that offer's instance of the qualification is waived.


Qualification Types

Aggregated Amount

Sums the dollar amount of transactions matching the specified filters and compares the total against a target value. This is the most common qualification type.

Programs Response

{
  "type": "aggregated_amount",
  "key": "minimum_cp_purchases",
  "label": "Minimum Crop Protection Purchases",
  "operator": "greater_than_or_equal_to",
  "value": 100000.0,
  "filters": [
    {
      "period_key": "incentive_period",
      "sku_keys": ["agri_shield_insecticide_2.5_gal_53551", "agri_shield_insecticide_bulk_63374", "crop_guard_30_l_herbicide_2.5_gal_22654"],
      "transaction_type": "retailer_purchases_from_distribution"
    }
  ],
  "attributes": []
}

Reading this: The participant must purchase at least $100,000 worth of agri_shield_insecticide_2.5_gal_53551, agri_shield_insecticide_bulk_63374, and crop_guard_30_l_herbicide_2.5_gal_22654 during the incentive_period from distribution. The dollar amounts of all matching transactions are summed and compared against the target.

Note

The filters can include multiple entries with different period keys, SKU sets, or transaction types. All matching transactions across all filter entries are summed together.


Aggregated Quantity

Sums the quantity of transactions matching the specified filters. Identical in structure to aggregated_amount, but measures units purchased rather than dollars spent.

Programs Response

{
  "type": "aggregated_quantity",
  "key": "minimum_gallons_purchased",
  "label": "Minimum Gallons Purchased",
  "operator": "greater_than_or_equal_to",
  "value": 500.0,
  "filters": [
    {
      "period_key": "incentive_period",
      "sku_keys": ["agri_shield_insecticide_2.5_gal_53551"],
      "transaction_type": "retailer_purchases_from_distribution"
    }
  ],
  "attributes": []
}

Reading this: The participant must purchase at least 500 units of the specified SKU during the incentive_period. The quantity from each matching transaction is summed.


Share of Wallet Percent

Measures the ratio of one product group's volume to another, expressed as a percentage. This is used when a manufacturer wants to ensure a minimum share of a participant's total business in a category.

The qualification has a numerator and denominator, each with their own filters:

  • Numerator — the product group being measured (e.g., "our brand's herbicide")
  • Denominator — the total category (e.g., "all herbicide from any brand")
  • Target — the minimum percentage the numerator must represent of the denominator

Programs Response

{
  "type": "share_of_wallet_percent",
  "key": "herbicide_share_of_wallet",
  "label": "Herbicide Share of Wallet",
  "operator": "greater_than_or_equal_to",
  "value": 30.0,
  "numerator": {
    "filters": [
      {
        "period_key": "incentive_period",
        "sku_keys": ["harvest_max_pro_herbicide_2.5_gal_46367", "harvest_max_pro_herbicide_bulk_73826"],
        "transaction_type": "retailer_purchases_from_distribution"
      }
    ]
  },
  "denominator": {
    "filters": [
      {
        "period_key": "incentive_period",
        "sku_keys": ["harvest_max_pro_herbicide_2.5_gal_46367", "harvest_max_pro_herbicide_bulk_73826", "knock_down_herbicide_2.5_gal_44159", "knock_down_herbicide_bulk_52335"],
        "transaction_type": "retailer_purchases_from_distribution"
      }
    ]
  },
  "attributes": []
}

Reading this: The participant's purchases of harvest_max_pro_herbicide_2.5_gal_46367 and harvest_max_pro_herbicide_bulk_73826 must represent at least 30% of their total herbicide purchases (including competitor products). The engine computes the target as denominator_amount × 30 / 100 and compares the numerator amount against it.


YoY Amount Index

Compares the current year dollar amount against a prior year amount to measure year-over-year growth. Like share of wallet, this uses a numerator/denominator structure:

  • Numerator — current year transactions
  • Denominator — prior year transactions
  • Target — the index value the ratio must meet (e.g., 100.0 means "match or exceed last year")

Programs Response

{
  "type": "yoy_amount_index",
  "key": "yoy_growth_requirement",
  "label": "Year-over-Year Growth",
  "operator": "greater_than_or_equal_to",
  "value": 100.0,
  "numerator": {
    "filters": [
      {
        "period_key": "incentive_period",
        "sku_keys": ["agri_shield_insecticide_2.5_gal_53551", "agri_shield_insecticide_bulk_63374"],
        "transaction_type": "retailer_purchases_from_distribution"
      }
    ]
  },
  "denominator": {
    "filters": [
      {
        "period_key": "prior_year_period",
        "sku_keys": ["agri_shield_insecticide_2.5_gal_53551", "agri_shield_insecticide_bulk_63374"],
        "transaction_type": "retailer_purchases_from_distribution"
      }
    ]
  },
  "attributes": []
}

Reading this: The participant's current year purchases must be at least 100% of their prior year purchases (i.e., no decline). The numerator sums current-period transactions; the denominator sums prior-period transactions. The engine computes the target as the denominator amount scaled by the index value.

Note

If the denominator (prior year) is zero or negative, the qualification is automatically considered met — you can't grow relative to nothing.


Amount Average Index

Similar to YoY Amount Index but supports averaging over multiple periods using a divisor. This allows comparisons like "current year vs. 3-year average."

Programs Response

{
  "type": "amount_average_index",
  "key": "three_year_average_growth",
  "label": "3-Year Average Growth Requirement",
  "operator": "greater_than_or_equal_to",
  "value": 100.0,
  "numerator": {
    "filters": [
      {
        "period_key": "incentive_period",
        "sku_keys": ["agri_shield_insecticide_2.5_gal_53551"],
        "transaction_type": "retailer_purchases_from_distribution"
      }
    ]
  },
  "denominator": {
    "filters": [
      {
        "period_key": "prior_three_year_period",
        "sku_keys": ["agri_shield_insecticide_2.5_gal_53551"],
        "transaction_type": "retailer_purchases_from_distribution"
      }
    ],
    "divisor": 3.0
  },
  "attributes": []
}

Reading this: The participant's current year purchases must meet or exceed 100% of their average annual purchases over the prior three years. The denominator total is divided by 3.0 before comparison.


Brand Count

Counts the number of distinct brands represented by transactions matching the specified filters, then compares that count against a target value. This is useful when a program requires a participant to buy across multiple brands rather than just multiple SKUs from the same brand.

A brand count qualification can further refine the set being counted with:

  • brand_keys — the brands that are eligible to count toward the total
  • excluded_sku_keys — specific SKUs to ignore even if they would otherwise match the filters

Programs Response

{
  "type": "brand_count",
  "key": "minimum_herbicide_brand_count",
  "label": "Minimum Herbicide Brand Count",
  "operator": "greater_than_or_equal_to",
  "value": 2,
  "filters": [
    {
      "period_key": "incentive_period",
      "sku_keys": [
        "harvest_max_pro_herbicide_2.5_gal_46367",
        "harvest_max_pro_herbicide_bulk_73826",
        "knock_down_herbicide_2.5_gal_44159",
        "knock_down_herbicide_bulk_52335",
        "crop_guard_30_l_herbicide_2.5_gal_22654"
      ],
      "transaction_type": "retailer_purchases_from_distribution"
    }
  ],
  "brand_keys": [
    "harvest_max_pro_herbicide",
    "knock_down_herbicide",
    "crop_guard_30_l_herbicide"
  ],
  "excluded_sku_keys": ["knock_down_herbicide_bulk_52335"],
  "attributes": []
}

Reading this: The participant must purchase qualifying products from at least 2 distinct brands during the incentive_period. Only the listed brand_keys count toward the total, and knock_down_herbicide_bulk_52335 is ignored even if it appears in matching transactions.


Property

Uses an externally provided value from the calculation request rather than computing a value from transactions. This is for conditions that the engine cannot derive from transaction data — business metrics, certifications, plan achievements, etc.

A property qualification specifies:

  • property.key — the key to look up in the request's properties
  • property.typenumber or boolean
  • property.level — where the property is provided: request, entity, or transaction

Programs Response — Numeric Property

{
  "type": "property",
  "key": "business_plan_achievement",
  "label": "Business Plan Achievement",
  "operator": "greater_than_or_equal_to",
  "value": 85.0,
  "property": {
    "key": "business_plan_achieved_percent",
    "type": "number",
    "level": "request"
  },
  "attributes": []
}

Reading this: The requestor must pass a business_plan_achieved_percent property at the request level with a value of at least 85.0. This is an externally maintained metric — the engine uses whatever value is provided.

Programs Response — Boolean Property

{
  "type": "property",
  "key": "sustainability_certified",
  "label": "Sustainability Certification",
  "operator": "equal_to",
  "value": true,
  "property": {
    "key": "is_sustainability_certified",
    "type": "boolean",
    "level": "entity"
  },
  "attributes": []
}

Reading this: The entity must have is_sustainability_certified set to true. Boolean properties always use equal_to as the operator.


Calculations Response

The calculations response includes a qualification_results array alongside potential_earnings. Each entry reports the evaluation outcome for one qualification:

{
  "qualification_results": [
    {
      "offer_key": "corteva.2026.retailer.national.crop_protection.base",
      "qualification_key": "minimum_cp_purchases",
      "met": true,
      "waived": false,
      "target": "100000",
      "operator": "greater_than_or_equal_to",
      "actual": "128500",
      "difference": "28500"
    },
    {
      "offer_key": "corteva.2026.retailer.national.crop_protection.base",
      "qualification_key": "yoy_growth_requirement",
      "met": false,
      "waived": false,
      "target": "115000",
      "operator": "greater_than_or_equal_to",
      "actual": "108000",
      "difference": "-7000"
    }
  ]
}

Reading this:

Field Meaning
offer_key The offer this qualification applies to
qualification_key The key from the qualification definition
met Whether the actual value satisfied the operator + target
waived Whether this qualification was waived in the request
target The threshold value that must be met
operator How actual is compared to target
actual The computed value from transactions (or the provided property value)
difference actual - targetpositive means the target was exceeded, negative means it was not met

Note

Qualification results are flattened to the offer level. Program-level qualifications are duplicated across all offers in the program, so each offer row is self-contained.


The Qualifier Expression

The qualifier field on a program or offer is a boolean expression that combines qualification keys with AND and OR operators. The engine evaluates each qualification independently, then substitutes the results into the expression to determine the final qualified status.

{
  "qualifier": "minimum_cp_purchases AND yoy_growth_requirement"
}

This means: the program is qualified only if both minimum_cp_purchases and yoy_growth_requirement are met (or waived).

More complex expressions are supported:

{
  "qualifier": "minimum_cp_purchases AND (yoy_growth_requirement OR business_plan_achievement)"
}

This means: must meet minimum_cp_purchases and at least one of the other two.

If qualifier is null or absent, the program/offer is considered qualified regardless of individual qualification results.


Summary

  • Qualifications gate whether offers pay out by evaluating measurable conditions against targets
  • Seven types cover transaction aggregates, brand counts, ratios, year-over-year comparisons, averages, and externally provided values
  • Qualifiers combine qualification results with boolean logic (AND / OR) to determine the final qualified status
  • Qualifications can be waived per request without changing the underlying evaluation
  • Results include met, waived, target, actual, and difference for full transparency