Skip to content

Changelog

All notable changes to the API will be documented here.

2026-07-15

Added

Adds the following program related label fields to GET /programs.

  • channel_label
  • audience_label
  • program_name_label
  • program_supplier_label
{
  "data": [
    {
      "key": "bradley.2026.retailer.local.bradley_local.tcp_austin_tx_999",
      "label": "2025 - 2026 Bradley → Retailer → Local → Bradley Local → TCP Austin TX 999",
      "summary": "Retailers earn varying incentives when selling Bradley products in 2026 season:",
      "description": "Retailers can earn varying incentives when selling specified Bradley products",
      "attributes": [
        {
          "type": "program_sheet",
          "value": "",
          "label": "Bradley 2025-26 Local Program"
        },
        {
          "type": "program_request_id",
          "value": "1",
          "label": "AgVend Request Id"
        }
      ],
      "time_frame": "2026",
      "channel": "retailer",
      "channel_label": "Retailer",
      "audience": "local",
      "audience_label": "Local",
      "program_name": "bradley_local",
      "program_name_label": "Bradley Local",
      "key_dates": [],
      "start_date": "2025-10-01",
      "end_date": "2026-09-30",
      "sku_keys": [],
      "time_periods": [],
      "transaction_types": [],
      "properties": [],
      "program_supplier_key": "bradley",
      "program_supplier_label": "Bradley",
      "version": "2026-07-14T20:38:06Z",
      ...

2026-07-06

Added

A new state query parameter has been added to GET /programs, allowing clients to filter programs by their lifecycle state. A new pending state is introduced alongside the existing released state, so programs that are not yet ready for release can be deployed and queried separately.

GET /programs

The state query parameter is optional and defaults to released, preserving existing behavior. No changes to the response JSON shape — the response body is identical regardless of which state is requested.

GET /programs?program_supplier_key=...&time_frame=2026

Returns released programs (unchanged default).

GET /programs?program_supplier_key=...&time_frame=2026&state=pending

Returns programs in the pending state — those deployed but not yet ready for release.

Invalid state values return a 400 Bad Request error.

2026-06-29

Added

Add GET /calculations/requirements

A new endpoint is added to help with request-construction fields that are nested under each returned program and offer.

GET /calculations/requirements?program_supplier_key=...&time_frame=...&participant-key:...

The endpoint should aggregate over all programs returned for:

  • participant-key header
  • program_supplier_key query param
  • time_frame query param
{
  "data": [
    {
      "transaction_requirements": {
        "fields": [
          {
            "field": "seller",
            "required_attributes": [
              "key"
            ],
            "transaction_types": [
              "retailer_purchases_from_distribution",
              "retailer_sales_to_growers"
            ],
            "omit_transaction_when_missing": true
          },
          {
            "field": "purchaser",
            "required_attributes": [
              "id"
            ],
            "transaction_types": [
              "retailer_purchases_from_distribution"
            ],
            "omit_transaction_when_missing": true
          }
        ],
        "properties": [
          {
            "key": "invoice_number",
            "type": "string",
            "transaction_types": [
              "retailer_purchases_from_distribution",
              "retailer_sales_to_growers"
            ],
            "omit_transaction_when_missing": true
          }
        ]
      },
      "entity_requirements": [],
      "request_requirements": {
        "properties": [
          {
            "key": "bussiness_plan_achieved",
            "type": "number"
          }
        ]
      },
      "start_date": "2025-09-01",
      "end_date": "2026-08-31",
      "transaction_types": [
        "retailer_purchases_from_distribution",
        "retailer_sales_to_growers"
      ],
      "sku_keys": [
        "keystone_la_nxt_herbicide_bulk_1009512",
        "resicore_xl_herbicide_bulk_1364786"
      ]
    }
  ],
  "errors": [],
  "meta": {
    "api_version": "v1"
  }
}

2026-06-17

Added

A new transaction type (retailer_orders_from_distribution) has been added to represent purchase orders from the retailer.

POST /calculations

Any transactions that fall into this category can now be included in the calculation request and will be used to calculate any programs that have been configured to use them.

{
  "participant_key": "ag_vend_austin_tx_000",
  "request_id": "",
  "properties": [],
  "entities": [
    {
      "id": "41eef1b3-19f2-49f1-8926-2ffbea246a97",
      "properties": [],
      "transactions": [
        {
          "transaction_id": "order-38790872-item-100681154",
          "transaction_type": "retailer_orders_from_distribution",
          "sku_key": "baythroid_xl_insecticide_1_gal_5960389",
          "uom_key": "gal",
          "quantity": 8.0,
          "amount": 1252.96,
          "invoice_date": "2022-09-01",
          "properties": [],
          "purchaser": {}
        }
       ]
    }
  ],
  "relationships": []
}

2026-06-12

Added

A new field has been added to the programs/offers object: properties. This field boils up any properties used in the given offer or program, similar to transaction_types or sku_keys.

GET /programs

        {
            "key": "bayer.2026.retailer.national.summit_target.default",
            "label": "2025 - 2026 Bayer → Retailer → National → Summit Target → Default",
            "summary": "The Bayer Summit Target program offers retailers up to 2% for meeting their business plan supporting the sale of Bayer products",
            "description": "\n    Retailers who meet at least 75% of their 2026 business plan can earn up to 2% on the Bayer Summit qualifying products.\n    ",
            "attributes": [],
            "time_frame": "2026",
            "channel": "retailer",
            "audience": "national",
            "program_name": "summit_target",
            "key_dates": [],
            "start_date": "2025-09-01",
            "end_date": "2026-08-31",
            "sku_keys": [],
            "time_periods": [],
            "transaction_types": [ ],
            "properties": [],
            "program_supplier_key": "bayer",
            "version": "2026-06-11T14:27:53Z",
            "qualifications": [],
            "qualifier": "",
            "external_ids": [],
            "group_by": [],
            "verifications": [],
            "offers": [
                {
                    "key": "bayer.2026.retailer.national.summit_target.default.broad_acre_fungicides",
                    "label": "2025 - 2026 Bayer → Retailer → National → Summit Target → Default → Broad Acre Fungicides",
                    "attributes": [],
                    "sku_keys": [],
                    "time_periods": [
                        {
                            "key": "incentive_period",
                            "label": "Earning time period",
                            "start_date": "2025-09-01",
                            "start_date_label": "Purchase start",
                            "end_date": "2026-08-31",
                            "end_date_label": "Purchase deadline"
                        }
                    ],
                    "transaction_types": [
                        "retailer_sales_to_growers"
                    ],
                    "properties": [
                        {
                            "key": "business_plan_achieved",
                            "type": "number",
                            "level": "request"
                        }
                    ],
                    "calculator_key": "percent_of_amount",
                    "qualifications": [
                        {
                            "type": "property",
                            "key": "minimum_business_plan_achieved",
                            "label": "Minimum business plan achieved",
                            "operator": "greater_than_or_equal_to",
                            "value": 75.0,
                            "attributes": [],
                            "property": {
                                "key": "business_plan_achieved",
                                "type": "number",
                                "level": "request"
                            }
                        }
                    ],
                    "qualifier": "minimum_business_plan_achieved",
                    "strategy_key": "stepped",
                    "incentive": {
                        "filters": [
                            {
                                "period_key": "incentive_period",
                                "sku_keys": [],
                                "transaction_type": "retailer_sales_to_growers",
                                "transaction_price": null
                            }
                        ],
                        "threshold_definition": {
                            "type": "property",
                            "property": {
                                "key": "business_plan_achieved",
                                "type": "number",
                                "level": "request"
                            }
                        },
                        "rates": []
                    }
                }

2026-06-09

Added

program_key is now included on every row in both potential_earnings and qualification_results. Clients can use this field to filter results by program or aggregate incentive_amount at the program level without reverse-mapping through offer_key.

POST /calculations

potential_earnings now includes program_key after offer_key:

"potential_earnings": [
  {
    "program_key": "corteva.2026.retailer.national.corn_early_fill.default",
    "offer_key": "corteva.2026.retailer.national.corn_early_fill.default.base",
    "offer_label": "...",
    ...
  }
]

qualification_results now includes program_key after offer_key:

"qualification_results": [
  {
    "program_key": "corteva.2026.retailer.national.corn_early_fill.default",
    "offer_key": "corteva.2026.retailer.national.corn_early_fill.default.rate_lock",
    "qualification_key": "...",
    ...
  }
]

2026-06-04

Added

A new field has been added to the group_by object in programs: omit_transaction_when_missing. This is defaulted to True and indicates that the transactions that do not have the required group_by info for a program calculation will be omitted from calculating for that program instead of the request erroring. When this field is set to False, the validation will be stricter and requests will fail with an error like:

  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "detail": "incomplete 'group_by' info: transactions of type 'retailer_sales_to_growers' are missing 'purchaser.id': [148]"
    }
  ],

GET /programs

This field will be present in the group_by definition and can be used to programmatically know when the group_by is absolutely required to be present for all relevant transactions.

        {
            "key": "bradley.2026.retailer.national.foo.default",
            "label": "2025 - 2026 Bradley → Retailer → National → Foo → Default",
            "summary": "...",
            "description": "...",
            "attributes": [...],
            "time_frame": "2026",
            "channel": "retailer",
            "audience": "national",
            "program_name": "foo",
            "key_dates": [],
            "start_date": "2025-09-01",
            "end_date": "2026-08-31",
            "sku_keys": [],
            "time_periods": [],
            "transaction_types": [],
            "program_supplier_key": "bradley",
            "version": "2026-06-04T14:15:55Z",
            "qualifications": [],
            "qualifier": null,
            "external_ids": [],
            "group_by": [
                {
                    "transaction_type": "retailer_sales_to_growers",
                    "field": "purchaser",
                    "key": "id",
                    "type": "string",
                    "omit_transaction_when_missing": true
                }
            ],
            "verifications": [],
            "offers": [...]
          }

2026-03-26

Added

A new qualification of type brand_count has been added. This supports qualifications that require the transactions to have a specific count of unique brands.

GET /programs

This qualification will have a unique structure that explicitly states the brands involved in this qualification and if any sku_keys were excluded from the qualification. The filters indicate the various attributes that the transactions will be filtered on, this is the same pattern as used by other qualification filters.

{
    "type": "brand_count",
    "key": "purchase_minimum_brand_count_qualification",
    "label": "Purchase at least 3 FMC brands",
    "operator": "greater_than_or_equal_to",
    "value": 3,
    "filters": [
        {
            "period_key": "current_season",
            "sku_keys": [
                "adastrio_fungicide_120_gal_99900002",
                "adastrio_fungicide_2.5_gal_99900001",
                                ...
            ],
            "transaction_type": "retailer_sales_to_growers"
        }
    ],
    "brand_keys": [
        "adastrio_fungicide",
        "anthem_maxx_herbicide"
                        ...
    ],
    "excluded_sku_keys": [],
    "attributes": []
}

There are no changes to any other endpoints from this feature addition.

2026-03-24

Added

The concept of rolling transactions up to a specific attribute of the transaction for calculations has been added, it will be called group_by. The configuration will add this attribute when applicable to a program and it will be associated with a transaction_type. For Example: When a program needs all its sales to growers to be grouped by the grower's id, the configuration will use group_by for it.

GET /programs

{
      "key": "basf.2026.retailer.local.seed_treatment_soybean_pair_up.ag_vend_austin_tx_000",
      "label": "2025 - 2026 Basf → Retailer → Local → Seed Treatment Soybean Pair Up → AgVend Austin Tx 000",
      "attributes": [],
      "time_frame": "2026",
      ...
      "group_by": [
        {
          "transaction_type": "retailer_sales_to_growers",
          "field": "purchaser",
          "key": "id",
          "type": "string"
        }
      ],
      "verifications": [],
      "offers": [...]
     }

This group_by indicates that all transactions of type retailer_sales_to_growers for basf for 2026 will need a purchaser.id in order to calculate. Even though only one program may use this grouping, if the engine encounters a retailer_sales_to_growers transaction with a sku that is relevant to this program but does not have the purchaser.id data, the request will error with:

{
  "data": [],
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "detail": "incomplete 'group_by' info: transactions of type 'retailer_sales_to_growers' are missing 'purchaser.id': [01JAD80XDZWGFZDN8WWJJHVDFQ]"
    }
  ],
  "meta": {
    "api_version": "v1"
  }
}

There are no changes to the POST /calculations output.

2026-03-02

Added

POST /calculations

Some programs targeting grower sales (retailer_sales_to_growers) require that transactions to be grouped by grower. In order to achieve that, the incoming requests to POST /calculations endpoint needs to accommodate purchaser(grower) data which will be done via an additional attribute:

          "purchaser": {
            "id": "895788"
          }

Including the purchaser.id is very similar to the inclusion of seller.key. All retailer_sales_to_growers transactions should have the purchaser object populated with the grower's id for accurate calculations. The calculation engine will determine when a program/offer needs to use the purchaser.id as directed by the configuration. There is no downside to adding the purchaser.id on all retailer_sales_to_growers transactions.

{
  "participant_key": "ag_vend_austin_tx_000",
  "entities": [
    {
      "id": "350FEN",
      "properties": [],
      "transactions": [
        {
          "transaction_id": "01JAD80XDZM296AGN3T33ZWMJF",
          "transaction_type": "retailer_sales_to_growers",
          "invoice_date": "2022-09-16",
          "sku_key": "agri_shield_insecticide_2.5_gal_53551",
          "quantity": 2007.0,
          "uom_key": "gal",
          "amount": 10254,
          "purchaser": {
            "id": "895788"
          },
          "properties": []
        }
      ]
    }
  ],
  "relationships": [],
  "properties": []
}

2026-02-25

Added

A new strategy named stacked has been added. Programs configured with this strategy will have strategy_key = stacked.

GET /programs

This endpoint will output offers with stacked strategy with a new structure for incentive like shown below. Unlike standard strategy, stacked does not support incentives: [...], instead it has an object incentive: {} The incentive object has two high level keys: sku_sets[]: This defines all sets of skus used by the sku_set_keys in stacks. This has all details about the period_key, transaction_type and the acre conversion rate for the sku as well as the pay rate of the sku. stacks[]: This has a key and sku_set_keys. The key for the stack that is used for the calculation is returned as incentive_rate_key in the potential_earnings

{
  "data": [
    {
      "key": "basf.2026.retailer.local.seed_treatment_soybean_pair_up.ag_vend_austin_tx_000",
      "label": "2025 - 2026 Basf → Retailer → Local → Seed Treatment Soybean Pair Up → AgVend Austin Tx 000",
      "summary": "The BASF Seed Treatment Soybean Pair Up Program provides full season incentive support for purchasing BASF participating brands.",
      "description": "Earn varying percent incentives once you attain 75% of prior year sales by participating brands.",
      "attributes": [
        {
          "type": "program_sheet",
          "value": "",
          "label": "2026_BASF_Retailer_Program_Potential_Earnings.pdf"
        },
        {
          "type": "program_request_id",
          "value": "59",
          "label": "AgVend Request Id"
        }
      ],
      "time_frame": "2026",
      "key_dates": [],
      "start_date": "2025-10-01",
      "end_date": "2026-09-30",
      "sku_keys": [],
      "time_periods": [],
      "transaction_types": [],
      "program_supplier_key": "basf",
      "version": "2026-02-24T18:41:15Z",
      "qualifications": [],
      "qualifier": null,
      "external_ids": [
        {
          "type": "string",
          "key": "program_request_id",
          "value": "59"
        }
      ],
      "verifications": [],
      "offers": [
        {
          "key": "basf.2026.retailer.local.seed_treatment_soybean_pair_up.ag_vend_austin_tx_000.ilevo",
          "label": "2025 - 2026 BASF → Retailer → Local → Seed Treatment Soybean Pair Up → AgVend Austin Tx 000 → ILEVO",
          "attributes": [],
          "sku_keys": [
            "ilevo_seed_treatment_15_gal_59023128",
            "ilevo_seed_treatment_2.5_gal_59023127",
            "xitavo_soybean_seed_unit"
          ],
          "time_periods": [
            {
              "key": "incentive_period",
              "label": "Earning time period",
              "start_date": "2025-10-01",
              "start_date_label": "Purchase start",
              "end_date": "2026-09-30",
              "end_date_label": "Purchase deadline"
            }
          ],
          "transaction_types": ["retailer_sales_to_growers"],
          "calculator_key": "dollars_per_coverage_unit",
          "qualifications": [],
          "qualifier": null,
          "strategy_key": "stacked",
          "incentive": {
            "sku_sets": [
              {
                "key": "seed",
                "period_key": "incentive_period",
                "transaction_type": "retailer_sales_to_growers",
                "conversion": {
                  "coverage_unit": "acre",
                  "rates": [
                    {
                      "sku_key": "xitavo_soybean_seed_unit",
                      "rate": 1.0,
                      "from": "unit"
                    }
                  ]
                },
                "rates": [
                  {
                    "sku_key": "xitavo_soybean_seed_unit",
                    "rate": 0.0,
                    "measure": "dollars"
                  }
                ]
              },
              {
                "key": "ilevo_seed_treatment",
                "period_key": "incentive_period",
                "transaction_type": "retailer_sales_to_growers",
                "conversion": {
                  "coverage_unit": "acre",
                  "rates": [
                    {
                      "sku_key": "ilevo_seed_treatment_15_gal_59023128",
                      "rate": 0.00921875,
                      "from": "gal"
                    },
                    {
                      "sku_key": "ilevo_seed_treatment_2.5_gal_59023127",
                      "rate": 0.00921875,
                      "from": "gal"
                    }
                  ]
                },
                "rates": [
                  {
                    "sku_key": "ilevo_seed_treatment_15_gal_59023128",
                    "rate": 0.75,
                    "measure": "dollars"
                  },
                  {
                    "sku_key": "ilevo_seed_treatment_2.5_gal_59023127",
                    "rate": 0.75,
                    "measure": "dollars"
                  }
                ]
              }
            ],
            "stacks": [
              {
                "key": "seed_and_ilevo_seed_treatment",
                "label": null,
                "sku_set_keys": ["seed", "ilevo_seed_treatment"]
              }
            ]
          }
        },
        {
          "key": "basf.2026.retailer.local.seed_treatment_soybean_pair_up.ag_vend_austin_tx_000.vault_ip_plus",
          "label": "2025 - 2026 BASF → Retailer → Local → Seed Treatment Soybean Pair Up → AgVend Austin Tx 000 → Vault Ip Plus",
          "attributes": [],
          "sku_keys": [
            "vault_ip_plus_seed_treatment_100_unit_59017726",
            "vault_ip_plus_seed_treatment_200_unit_59017860",
            "xitavo_soybean_seed_unit"
          ],
          "time_periods": [
            {
              "key": "incentive_period",
              "label": "Earning time period",
              "start_date": "2025-10-01",
              "start_date_label": "Purchase start",
              "end_date": "2026-09-30",
              "end_date_label": "Purchase deadline"
            }
          ],
          "transaction_types": ["retailer_sales_to_growers"],
          "calculator_key": "dollars_per_coverage_unit",
          "qualifications": [],
          "qualifier": null,
          "strategy_key": "stacked",
          "incentive": {
            "sku_sets": [
              {
                "key": "seed",
                "period_key": "incentive_period",
                "transaction_type": "retailer_sales_to_growers",
                "conversion": {
                  "coverage_unit": "acre",
                  "rates": [
                    {
                      "sku_key": "xitavo_soybean_seed_unit",
                      "rate": 1.0,
                      "from": "unit"
                    }
                  ]
                },
                "rates": [
                  {
                    "sku_key": "xitavo_soybean_seed_unit",
                    "rate": 0.0,
                    "measure": "dollars"
                  }
                ]
              },
              {
                "key": "vault_ip_plus_seed_treatment",
                "period_key": "incentive_period",
                "transaction_type": "retailer_sales_to_growers",
                "conversion": {
                  "coverage_unit": "acre",
                  "rates": [
                    {
                      "sku_key": "vault_ip_plus_seed_treatment_100_unit_59017726",
                      "rate": 0.51,
                      "from": "unit"
                    },
                    {
                      "sku_key": "vault_ip_plus_seed_treatment_200_unit_59017860",
                      "rate": 0.51,
                      "from": "unit"
                    }
                  ]
                },
                "rates": [
                  {
                    "sku_key": "vault_ip_plus_seed_treatment_100_unit_59017726",
                    "rate": 0.75,
                    "measure": "dollars"
                  },
                  {
                    "sku_key": "vault_ip_plus_seed_treatment_200_unit_59017860",
                    "rate": 0.75,
                    "measure": "dollars"
                  }
                ]
              }
            ],
            "stacks": [
              {
                "key": "seed_and_vault_ip_plus_seed_treatment",
                "label": null,
                "sku_set_keys": ["seed", "vault_ip_plus_seed_treatment"]
              }
            ]
          }
        }
      ]
    }
  ],
  "errors": []
}

POST /calculations

This endpoint has a small update to the potential_earnings structure, the field named incentive_rate_key is a non nullable string. So far a transaction could only earn once per offer but going forward a transaction can earn multiple times in an offer as long as the incentive_rate_key is unique. Effectively, potential_earnings have a primary key of transaction_id, offer_key and incentive_rate_key

This is to ensure we provide results at the smallest level, i.e. we output how much a transaction earned per stack in a given offer. (stacks[].key is the incentive_rate_key for stacked).

{
  "data": [
    {
      "participant_key": "ag_vend_austin_tx_000",
      "potential_earnings": [
        {
          "offer_key": "basf.2026.retailer.local.seed_treatment_soybean_pair_up.ag_vend_austin_tx_000.ilevo",
          "offer_label": "2025 - 2026 BASF → Retailer → Local → Seed Treatment Soybean Pair Up → AgVend Austin Tx 000 → ILEVO",
          "offer_calculator": "dollars_per_coverage_unit",
          "sku_key": "ilevo_seed_treatment_15_gal_59023128",
          "incentive_rate_key": "seed_and_ilevo_seed_treatment",
          "incentive_rate_measure": "dollars",
          "incentive_rate_value": 0.75,
          "offer_sku_pay_rate": 0.75,
          "transaction_id": "01F8ZMVJKB5XNPQ6TRDYW4EH9G",
          "transaction_type": "retailer_sales_to_growers",
          "invoice_date": "2025-10-16",
          "provided_quantity": 10.0,
          "provided_uom_key": "gal",
          "provided_amount": 4700.0,
          "incentivized_quantity": 10.0,
          "incentivized_amount": 4700.0,
          "incentive_amount": 813.56,
          "incentive_contribution_percent": 1.0,
          "incentive_effective_rate": 0.173,
          "properties": []
        },
        {
          "offer_key": "basf.2026.retailer.local.seed_treatment_soybean_pair_up.ag_vend_austin_tx_000.vault_ip_plus",
          "offer_label": "2025 - 2026 BASF → Retailer → Local → Seed Treatment Soybean Pair Up → AgVend Austin Tx 000 → Vault Ip Plus",
          "offer_calculator": "dollars_per_coverage_unit",
          "sku_key": "vault_ip_plus_seed_treatment_100_unit_59017726",
          "incentive_rate_key": "seed_and_vault_ip_plus_seed_treatment",
          "incentive_rate_measure": "dollars",
          "incentive_rate_value": 0.75,
          "offer_sku_pay_rate": 0.75,
          "transaction_id": "01GRT7B2MZXSVNF0YJKHWP2A4C",
          "transaction_type": "retailer_sales_to_growers",
          "invoice_date": "2025-10-16",
          "provided_quantity": 1000.0,
          "provided_uom_key": "unit",
          "provided_amount": 45000.0,
          "incentivized_quantity": 765.0,
          "incentivized_amount": 45000.0,
          "incentive_amount": 1125.0,
          "incentive_contribution_percent": 1.0,
          "incentive_effective_rate": 0.025,
          "properties": []
        }
      ],
      "qualification_results": []
    }
  ],
  "errors": []
}

2026-02-12

Added

All endpoints will now include the current application version as a response header (X-Calc-Version). It is our recommendation that you capture this version (along with request/response JSON) when making requests. This will allow us to more readily track down bug if/when provided.

Versions are essentially time-stamps in the form of: 2026-02-12--17-51-52Z

2026-01-27

Added

Our documentation now includes a Coming Soon page. This will be updated regularly to describe features that we are working on. It will typically include things like examples of JSON input/output from our engine. The example should be considered drafts and are subject to change. The intent is for you to be able to plan for changes to your system, mock-up design changes, or provoke asking our team questions on the new feature.

2026-01-26

Added

A new strategy named stepped has been added. Programs configured with this strategy will have a strategy_key = stepped.

GET /programs

This endpoint will output offers with stepped strategy with a new structure for incentive like shown below. Unlike standard strategy, stepped does not support incentives: [...], instead it has an object incentive: {} The incentive object has three high level keys:

  • filters[]: This defines the transactions that will be earning in the given offer by using period_key, sku_keys and transaction_type
  • threshold_definition: This defines the criteria that determines which rate is applicable for given request. The structure for this object changes depending on its type; aggregated_amount or aggregated_quantity will have the same attributes and is used to calculate the threshold from given transaction whereas property type indicates that the value to determine rate will be provided in the request as a property.
  • rates[]: This defines the scale of the stepped offer and the value resulting from threshold_definition is compared with the threshold to apply given rate value. The key for the rate that is used for the calculation is returned as incentive_rate_key in the potential_earnings
{
  "offers": [
    {
      "key": "offer_a",
      "label": "2025 - 2026 Offer A",
      "attributes": [],
      "sku_keys": ["sku_a", "sku_b", "sku_c", "sku_d"],
      "time_periods": [
        {
          "key": "incentive_period",
          "label": "Earning time period",
          "start_date": "2025-10-01",
          "start_date_label": "Purchase start",
          "end_date": "2025-11-15",
          "end_date_label": "Purchase deadline"
        }
      ],
      "transaction_types": ["retailer_purchases_from_distribution"],
      "calculator_key": "percent_of_amount",
      "qualifications": [],
      "qualifier": null,
      "strategy_key": "stepped",
      "incentive": {
        "filters": [
          {
            "period_key": "incentive_period",
            "sku_keys": ["sku_a", "sku_b"],
            "transaction_type": "retailer_purchases_from_distribution"
          }
        ],
        "threshold_definition": {
          "type": "aggregated_amount",
          "filters": [
            {
              "period_key": "incentive_period",
              "sku_keys": ["sku_c", "sku_d"],
              "transaction_type": "retailer_purchases_from_distribution"
            }
          ]
        },
        "rates": [
          {
            "key": "15_percent_greater_than_or_equal_to_2000",
            "label": null,
            "threshold": 2000.0,
            "value": 15.0,
            "measure": "percent"
          },
          {
            "key": "10_percent_greater_than_or_equal_to_1000",
            "label": null,
            "threshold": 1000.0,
            "value": 10.0,
            "measure": "percent"
          }
        ]
      }
    },
    {
      "key": "offer_b",
      "label": "2025 - 2026 Offer B",
      "attributes": [],
      "sku_keys": ["sku_a", "sku_b"],
      "time_periods": [
        {
          "key": "incentive_period",
          "label": "Earning time period",
          "start_date": "2025-10-01",
          "start_date_label": "Purchase start",
          "end_date": "2025-11-15",
          "end_date_label": "Purchase deadline"
        }
      ],
      "transaction_types": ["retailer_purchases_from_distribution"],
      "calculator_key": "percent_of_amount",
      "qualifications": [],
      "qualifier": null,
      "strategy_key": "stepped",
      "incentive": {
        "filters": [
          {
            "period_key": "incentive_period",
            "sku_keys": ["sku_c", "sku_d"],
            "transaction_type": "retailer_purchases_from_distribution"
          }
        ],
        "threshold_definition": {
          "type": "property",
          "property": {
            "key": "business_plan_achieved",
            "type": "number",
            "level": "request"
          }
        },
        "rates": [
          {
            "key": "1.88_percent_greater_than_or_equal_to_75",
            "label": null,
            "threshold": 75.0,
            "value": 1.88,
            "measure": "percent"
          },
          {
            "key": "1.9_percent_greater_than_or_equal_to_85",
            "label": null,
            "threshold": 85.0,
            "value": 1.9,
            "measure": "percent"
          },
          {
            "key": "1.92_percent_greater_than_or_equal_to_96",
            "label": null,
            "threshold": 96.0,
            "value": 1.92,
            "measure": "percent"
          },
          {
            "key": "1.94_percent_greater_than_or_equal_to_97",
            "label": null,
            "threshold": 97.0,
            "value": 1.94,
            "measure": "percent"
          },
          {
            "key": "1.96_percent_greater_than_or_equal_to_98",
            "label": null,
            "threshold": 98.0,
            "value": 1.96,
            "measure": "percent"
          },
          {
            "key": "1.98_percent_greater_than_or_equal_to_99",
            "label": null,
            "threshold": 99.0,
            "value": 1.98,
            "measure": "percent"
          },
          {
            "key": "2_percent_greater_than_or_equal_to_100",
            "label": null,
            "threshold": 100.0,
            "value": 2.0,
            "measure": "percent"
          }
        ]
      }
    }
  ]
}

POST /calculations

This endpoint has a small addition to the potential_earnings structure, a field named incentive_rate_key which is an optional string. For standard offers it is the incentive[].key whereas for stepped it is the rate[].key, this helps the requestor know which rate or incentive is applied for the incentive calculation of given offer.

{
  "data": [
    {
      "participant_key": "ag_vend_austin_tx_000",
      "potential_earnings": [
        {
          "offer_key": "offer_a",
          "offer_label": "2025 - 2026 Offer A",
          "offer_calculator": "percent_of_amount",
          "sku_key": "sku_a",
          "incentive_rate_key": "15_percent_greater_than_or_equal_to_2000",
          "incentive_rate_measure": "percent",
          "incentive_rate_value": 15.0,
          "offer_sku_pay_rate": 0.15,
          "transaction_id": "01JAD80XDZGZNTYDRV4H56221W",
          "transaction_type": "retailer_purchases_from_distribution",
          "invoice_date": "2025-10-24",
          "provided_quantity": 1570.0,
          "provided_uom_key": "gal",
          "provided_amount": 86350.0,
          "incentivized_quantity": 1570.0,
          "incentivized_amount": 78500.0,
          "incentive_amount": 11775.0,
          "incentive_contribution_percent": 0.146,
          "incentive_effective_rate": 0.15,
          "properties": []
        }
      ]
    }
  ]
}

2025-12-29

Added

POST /calculations now supports evaluating qualifications based on a property value:

Example property in qualification request

  • Currently request level properties are supported
  • Properties can be of type boolean or number
{
  "participant_key": "ag_vend_austin_tx_000",
  "properties": [
    {
      "key": "foo_property",
      "type": "boolean",
      "value": true
    },
    {
      "key": "bar_property",
      "type": "number",
      "value": 95
    }
  ],
  "entities": [...],
  "relationships": [...]
}

Example qualification results

{
  "data": [
    {
      "participant_key": "ag_vend_austin_tx_000",
      "potential_earnings": [...],
      "qualification_results": [
        {
          "offer_key": "corteva.2026.retailer.local.local_offer.cpi_hastings_ne_073.base",
          "qualification_key": "foo_property_qualification",
          "met": true,
          "waived": false,
          "target": 0.0,
          "operator": "equal_to",
          "actual": 0.0,
          "difference": 0.0
        },
        {
          "offer_key": "corteva.2026.retailer.local.local_offer.cpi_hastings_ne_073.base",
          "qualification_key": "bar_property_qualification",
          "met": true,
          "waived": false,
          "target": 90.0,
          "operator": "greater_than_or_equal_to",
          "actual": 95.0,
          "difference": 5.0
        }
      ]
    }
  ],
  "errors": []
}

2025-12-02

Added

POST /calculations now (optionally) accepts a seller attribute on transaction. The seller attribute should be included when a calculation request is made for a program_supplier_type of distributor.


POST /calculations now (optionally) accepts a seller attribute on transaction. The seller attribute should be included when a calculation request is made for a program_supplier_type of distributor.

Example Request

{
  "participant_key": "agtegra",
  "entities": [
    {
      "id": "350FEN",
      "properties": [],
      "transactions": [
        {
          "transaction_id": "01JAD80XDZM296AGN3T33ZWMJF",
          "transaction_type": "retailer_purchases_from_distribution",
          "invoice_date": "2022-09-16",
          "sku_key": "keystone_la_nxt_herbicide_bulk_1009512",
          "quantity": 2000007.0,
          "uom_key": "gal",
          "amount": 1025444,
          "seller": {
            "key": "winfield"
          },
          "properties": []
        }
      ]
    }
  ],
  "relationships": [],
  "properties": []
}

Example Request

{
  "participant_key": "agtegra",
  "entities": [
    {
      "id": "350FEN",
      "properties": [],
      "transactions": [
        {
          "transaction_id": "01JAD80XDZM296AGN3T33ZWMJF",
          "transaction_type": "retailer_purchases_from_distribution",
          "invoice_date": "2022-09-16",
          "sku_key": "keystone_la_nxt_herbicide_bulk_1009512",
          "quantity": 2000007.0,
          "uom_key": "gal",
          "amount": 1025444,
          "seller": {
            "key": "winfield"
          },
          "properties": []
        }
      ]
    }
  ],
  "relationships": [],
  "properties": []
}

2025-11-24

Changed

GET /enrollments will now include a program_supplier_type which will be either:

  • basic_manufacturer
  • distributor

When the type is distributor, this is an indication that seller should be included on transactions.


GET /enrollments will now include a program_supplier_type which will be either:

  • basic_manufacturer
  • distributor

When the type is distributor, this is an indication that seller should be included on transactions.

2025-11-05

Changed

BREAKING CHANGE POST /calculations now requires the program_supplier_key parameter. This parameter was previously optional but was already being submitted in most if not all requests.


BREAKING CHANGE POST /calculations now requires the program_supplier_key parameter. This parameter was previously optional but was already being submitted in most if not all requests.

2025-11-04

Changed

GET /skus no longer requires the manufacturer_key parameter. This is especially helpful in the context of distributor programs which can span multiple product suppliers.


GET /skus no longer requires the manufacturer_key parameter. This is especially helpful in the context of distributor programs which can span multiple product suppliers.

2025-09-30

Added

GET /programs now includes qualification attributes.

      "attributes": [
        {
          "type": "program_sheet",
          "value": "2025-2026 Corteva Retail Offer Book_Digital.pdf",
          "label": ""
        },
        {
          "type": "program_request_id",
          "value": "37",
          "label": "AgVend Request Id"
        },
        {
          "type": "program_request_id",
          "value": "45",
          "label": "AgVend Request Id"
        }
      ],

GET /programs now includes qualification attributes.

      "attributes": [
        {
          "type": "program_sheet",
          "value": "2025-2026 Corteva Retail Offer Book_Digital.pdf",
          "label": ""
        },
        {
          "type": "program_request_id",
          "value": "37",
          "label": "AgVend Request Id"
        },
        {
          "type": "program_request_id",
          "value": "45",
          "label": "AgVend Request Id"
        }
      ],

2025-09-24

Added

GET /programs now includes a version attribute. Version is a String in the format of a ISO-8601 using Zulu time short-hand (Z) for UTC.


GET /programs now includes a version attribute. Version is a String in the format of a ISO-8601 using Zulu time short-hand (Z) for UTC.

2025-09-22

Fixed

  • Increased POST body request size limit. The previous (default) limit was causing unexpected errors when larger requests to POST /calculations were submitted.
  • POST /calculations will now fail with a 422 when a request includes (exact) duplicate transactions

  • Increased POST body request size limit. The previous (default) limit was causing unexpected errors when larger requests to POST /calculations were submitted.
  • POST /calculations will now fail with a 422 when a request includes (exact) duplicate transactions

2025-06-20

Added

POST /calculations now includes the ability to waive qualifications. When a qualification is waived, it is assumed as true when evaluating the qualifier.

The qualification waiver is passed in as a property at the highest level of the request with key:waive and type: waive_qualifications which enforces the value to be an array of an object containing program_key, offer_key - optional and qualification_key.

{
  "participant_key": "foo",
  "entities": [...],
  "relationships": [...].
  "properties": [
     {
      "key": "waive",
      "type": "waive_qualifications",
      "value": [
        {
          "program_key": "corteva.2024.national.retail_stocking",
          "offer_key": "corteva.2024.national.retail_stocking.biologicals.base",
          "qualification_key": "initial_period_minimum_qualification"
        },
        {
          "program_key": "abc",
          "qualification_key": "participated_in_training"
        }
      ]
    }
   ]
}

This request will result in an output like this:

  "potential_earnings": [
        {
          "offer_key": "corteva.2024.national.retail_stocking.biologicals.base",
          "offer_label": "2023 - 2024 Corteva → National → Retail Stocking → Biologicals → Base ",
          "offer_calculator": "percent_of_amount",
          "sku_key": "utrisha_n_biostimulant_12.5_lb_1409466",
          "incentive_rate_measure": "percent",
          "incentive_rate_value": 5.0,
          "offer_sku_pay_rate": 0.05,
          "transaction_id": "01JAD80XDZ3EYJSQF8J8P7GFR4",
          "transaction_type": "retailer_purchases_from_distribution",
          "invoice_date": "2024-03-07",
          "provided_quantity": 30.0,
          "provided_uom_key": "lb",
          "provided_amount": 109272.6015625,
          "incentivized_quantity": 30.0,
          "incentivized_amount": 1134.0,
          "incentive_amount": 56.7,
          "incentive_contribution_percent": 1.0,
          "incentive_effective_rate": 0.05,
          "properties": []
        },
        ...
      ],
      "qualification_results": [
        {
          "offer_key": "corteva.2024.national.retail_stocking.biologicals.base",
          "qualification_key": "initial_period_minimum_qualification",
          "met": false,
          "waived": true,
          "target": 20000.0,
          "operator": "greater_than_or_equal_to",
          "actual": 1134.0
        },
        {
          "offer_key": "corteva.2024.local.agtegra.retail_advantage.biocontrol",
          "qualification_key": "purchase_minimum_amount_qualification",
          "met": true,
          "waived": false,
          "target": 100000.0,
          "operator": "greater_than_or_equal_to",
          "actual": 4990495.51
        }
        ...
      ]

One of the primary use cases of this feature is to waive qualifications that are deemed "assume completed". These are typically qualifications for non-transaction based activity (e.g. "attended a training"). These qualification will have an additional attribute indicating that they should be waived. You will see this attribute in the GET /programs output on either program or offer qualifications:

{
  "qualifications": [
    {
      "type": "property",
      "key": "attended_training_qualification",
      "label": "Attended Training Qualification",
      "operator": "equal_to",
      "value": true,
      "attributes": [
        {
          "type": "waive_qualifications",
          "value": "assume_complete",
          "label": "Safe to mark as assumed complete - not transaction-driven"
        }
      ],
      "property": {
        "key": "attended_training",
        "type": "boolean",
        "level": "request"
      }
    }
  ]
}

POST /calculations now includes the ability to waive qualifications. When a qualification is waived, it is assumed as true when evaluating the qualifier.

The qualification waiver is passed in as a property at the highest level of the request with key:waive and type: waive_qualifications which enforces the value to be an array of an object containing program_key, offer_key - optional and qualification_key.

{
  "participant_key": "foo",
  "entities": [...],
  "relationships": [...].
  "properties": [
     {
      "key": "waive",
      "type": "waive_qualifications",
      "value": [
        {
          "program_key": "corteva.2024.national.retail_stocking",
          "offer_key": "corteva.2024.national.retail_stocking.biologicals.base",
          "qualification_key": "initial_period_minimum_qualification"
        },
        {
          "program_key": "abc",
          "qualification_key": "participated_in_training"
        }
      ]
    }
   ]
}

This request will result in an output like this:

  "potential_earnings": [
        {
          "offer_key": "corteva.2024.national.retail_stocking.biologicals.base",
          "offer_label": "2023 - 2024 Corteva → National → Retail Stocking → Biologicals → Base ",
          "offer_calculator": "percent_of_amount",
          "sku_key": "utrisha_n_biostimulant_12.5_lb_1409466",
          "incentive_rate_measure": "percent",
          "incentive_rate_value": 5.0,
          "offer_sku_pay_rate": 0.05,
          "transaction_id": "01JAD80XDZ3EYJSQF8J8P7GFR4",
          "transaction_type": "retailer_purchases_from_distribution",
          "invoice_date": "2024-03-07",
          "provided_quantity": 30.0,
          "provided_uom_key": "lb",
          "provided_amount": 109272.6015625,
          "incentivized_quantity": 30.0,
          "incentivized_amount": 1134.0,
          "incentive_amount": 56.7,
          "incentive_contribution_percent": 1.0,
          "incentive_effective_rate": 0.05,
          "properties": []
        },
        ...
      ],
      "qualification_results": [
        {
          "offer_key": "corteva.2024.national.retail_stocking.biologicals.base",
          "qualification_key": "initial_period_minimum_qualification",
          "met": false,
          "waived": true,
          "target": 20000.0,
          "operator": "greater_than_or_equal_to",
          "actual": 1134.0
        },
        {
          "offer_key": "corteva.2024.local.agtegra.retail_advantage.biocontrol",
          "qualification_key": "purchase_minimum_amount_qualification",
          "met": true,
          "waived": false,
          "target": 100000.0,
          "operator": "greater_than_or_equal_to",
          "actual": 4990495.51
        }
        ...
      ]

2025-06-11

Added

GET /enrollments?time_frame=<foo> endpoint has been added. It provides the program suppliers related to a participant in a given time frame.

{
  "data": [
    {
      "program_supplier_key": "corteva"
    },
    {
      "program_supplier_key": "syngenta"
    },
    {
      "program_supplier_key": "bayer"
    }
  ],
  "errors": []
}

Note: This is an object versus a simple array to leave room for any additional information that may be required for an enrollee


GET /enrollments?time_frame=<foo> endpoint has been added. It provides the program suppliers related to a participant in a given time frame.

{
  "data": [
    {
      "program_supplier_key": "corteva"
    },
    {
      "program_supplier_key": "syngenta"
    },
    {
      "program_supplier_key": "bayer"
    }
  ],
  "errors": []
}

Note: This is an object versus a simple array to leave room for any additional information that may be required for an enrollee

2025-06-07

Added

GET /programs now includes external id's when configured. The's id's can be used to link up to requests/programs defined in your system.

{
  ...
  "external_ids": [
      {
          "key": "program_request_id",
          "value": "123"
      }
    ],
  ...
}

GET /programs now includes external id's when configured. The's id's can be used to link up to requests/programs defined in your system.

{
  ...
  "external_ids": [
      {
          "key": "program_request_id",
          "value": "123"
      }
    ],
  ...
}

2025-05-30

Changed

GET /programs now includes a (fake, hard-code) value for program version.

"version": "2025-01-01--01"

GET /programs now includes a (fake, hard-code) value for program version.

"version": "2025-01-01--01"

2025-05-16

Changed

GET /skus now includes the following attributes on the Sku structure:

  • brand_key
  • brand_label
  • product_key
  • product_label

GET /skus now includes the following attributes on the Sku structure:

  • brand_key
  • brand_label
  • product_key
  • product_label