How to Migrate from Version-1 APIs

aWhere's major technology focus is the continued development of a world-class API platform that delivers Agriculture Intelligence to all players in the value chain. Over the last couple of years, our platform has evolved along with the rest of the API industry, and we recently released a new generation APIs that have a standards-based and flexible design. This will mean your application will have faster and easier access to new data, agronomic models, and technology assets to continually deliver additional value with minimum integration effort.

To ensure our clients get the most out of platform and to ensure the reliability of our data products, from time to time we have to remove older APIs from service. We have recently had two older versions of the APIs in production, known as "Deprecated" (or V-Zero) and the "Version-1" APIs. This guide outlines how to migrate from the Version-1 APIs to the new platform. If you happen to be using our oldest APIs, there is a separate guide for you.

How to Identify Version-1 Services

You can know you're using Version-1 services if:

  • For Authentication, use Basic Authentication with a username and password
  • You access weather and agronomic data from one of these endpoints:
    • /api/weather
    • /v1/weather
  • Or you use data.awhere.com as the hostname.

Difference Between Version-1 and Next-Generation APIs

Version 1 Next-Gen
Weather observations, forecasts, and agronomics bundled into one endpoint. Separate endpoints for each category of data (lightweight micro-service design).
Specify which weather attributes you want All attributes included by default, but you can filter out what you don't need
Selected locations by geolocation Register locations with a field ID. Optionally, store additional information about fields and plantings for more efficient agronomics and model calculations.
Forecast only available in 6- or 24-hour summary blocks Forecast available in 1, 2, 3, 4, 6, 8, 12, or 24-hour blocks
Getting accumulation totals required returning all days in a range, creating large payloads Now possible to request only the accumulation totals, in addition to daily accumulations
Limited historical comparisons for accumulations (3- and 10-year only) Historical averages can be requested for any weather and agronomic value across any range of years.
You had to generate long-term averages yourself from daily weather data Historical averages can be requested for any weather and agronomic value across any range of years.
Batch requests for weather was inefficient and limited New batch job system can accommodate any number of requests and processes asynchronously.

The rest of this guide describes some common use cases and how to accomplish them in the new platform.

Hostname

Deprecated Hostname

The old APIs use a URL beginning with

https://data.awhere.com/api/weather

Migration

Moving forward, the our APIs have a URL starting with

https://api.awhere.com

plus the endpoint, for example,

https://api.awhere.com/v2/weather/fields/{fieldId}/observations

Authentication

Deprecated Approach

The Version-1 APIs usually used HTTP Basic Authentication. This required creating a base64-hash of a username and password, and sending it in an Authorization header:

GET /api/weather
Authorization: Basic j2fj902fjasdifj2040j01js0fja==

Migration

Our new APIs now leverage OAuth2 tokens for authentication. This standard offers a lot of flexibility and improved security use cases over Basic authentication.

This approach has two steps:

  1. Request a token using your API key and Secret (which for you, is your username and password).
  2. Include the token in the Authorization header on all other API requests.

This approach is detailed in the latest version of the documentation. The current sample code for C# and PHP also includes an example for this method.

Managing Field Locations

In the new APIs, you'll need to create field locations in the system prior to requesting data. With each field location, you create an ID of your choosing, and then reference that field by the ID when requesting data (weather, agronomics, etc). You can use almost anything you want for the field ID (alphanumeric).

To create a field, you'll send a POST request to /v2/fields. The request body looks like this:

{
    "id": "field1",
    "name":"My First Field",
    "farmId":"farm1",
    "acres":100,
    "centerPoint":{
        "latitude":39.8282,
        "longitude":-98.5795
        }
}

API Documentation for Creating Fields

Get Daily Weather for a Field Location

Version 1

The older API required you to request the specific weather attributes you wanted to include, all using query string parameters. This example retrieves the temperatures and precipitation for October 1–10, 2015:

GET /v1/weather?latitude=39.8282&longitude=-98.5795&startDate=2015-10-01&endDate=2015-10-10&attribute=minTemperature&attribute=maxTemperature&attribute=precip
Next-Gen

The new APIs have a simpler interface, and all weather attributes are included by default. To get similar data to the above API, you would use the API call shown next. Remember you would first need to create the field location, but after that can get all field data by field ID.

GET /v2/weather/fields/field1/observations/2015-10-01,2015-10-10

The major differences are that you don't need to specify the geolocation every time, and that the dates are built right into the URI. If you only want a single day of weather data, you can use just one date:

GET /v2/weather/fields/field1/observations/2015-10-10

And if you simply want the last week's of weather, you can leave off the dates entire to get the last seven days by default:

GET /v2/weather/fields/field1/observations

If you want to restrict the response to only specific properties, then you can use the properties query string parameter to ask only for the data you want:

GET /v2/weather/fields/field1/observations/2015-10-01,2015-10-10?properties=temperatures,precipitation

Finally, note that the payload format has changed in the new APIs. The new APIs use parent and child properties to provide better context and future expandability. For example, whereas we used to return the max temperature in a top-level property like so:

{
    "requestId": 0,
    "latitude": 39.7096116,
    "longitude": -105.1045942,
    "date": "2015-07-01T00:00:00",
    "dailyAttributes": {
         "maxTemperature": 32.9,
         "minTemperature": 14.4,
         "precip": 0.20616888999939
    }
}

In the new API, the format is formatted as:

{
  "date":"2015-07-01",
  "temperatures":{
     "max":32.9
     "min":14.4,
     "units":"C"
   }
}

The table below identifies the name of the attribute/property from the Version-1 APIs, and the corresponding location of that data in the new Observations APIs. Note that because of parent-child properties in the new API, we're using dot notation to show where in the new response payload you'll find that data. Some of the attributes from the Version 1 API have been moved to the Agronomics APIs, and so they aren't listed here, but read on to the rest of the use cases to learn more.

Deprecated Attribute New Attribute Path Description
minTemperature temperatures.min Lowest recorded air temperature during the day
maxTemperature temperatures.max Highest recorded air temperature during the day
precip precipitation.amount Total daily precipitation
solar solar.amount Summation of total solar energy
minHumidity humidity.min Lowest relative humidity during the day
maxHumidity humidity.max Highest relative humidity during the day
mornWind wind.morningMax Morning's highest wind speed
maxWind wind.dayMax Day's highest wind speed

Weather Daily Observations API Documentation

Transparently Migrate Forecast Data

Version 1

In the older APIs, forecast data was combined with observations and was limited in temporal resolution, allowing only either 6-hour blocks or daily summaries. Forecast data was also all-or-nothing, there was no option to choose with attributes you wanted to see from the forecast. This API would return eight forecast days starting from October 10, with each day having 6-hour summary blocks:

GET /v1/weather?latitude=39.8282&longitude=-98.5795&startDate=2015-10-01&attribute=conditions&interval=4
Next-Gen

In the new platform, forecasts live in their own API and you have a lot more flexibility with them. For example, this API call will return 8 forecast days starting from today:

GET /v2/weather/fields/field1/forecasts

If you only want the forecast for a specific date (must be in the future), add that date to the end of the URI. You can also specify a range of dates:

GET /v2/weather/fields/field1/forecasts/2015-10-01
GET /v2/weather/fields/field1/forecasts/2015-10-01,2015-10-03

By default, the API will return an hourly forecast, but you can combine that into 2, 3, 4, 6, 8, 12, or 24-hour summary blocks. To replicate the Version-1 example above, this API call would return 6-hour blocks:

GET/v2/weather/fields/field1/forecasts?blocksize=6

And like the new Observations API, you can choose which properties you want to include with the properties query string parameter. If you only want the forecasted temperature, you can use this:

GET /v2/weather/fields/field1/forecasts?properties=temperatures

Finally, note that the payload format has changed in the new APIs. The new APIs use parent and child properties to provide better context and future expandability. For example, whereas we used to return forecast like so:

"conditions": [
      {
        "startTime": "2015-10-21T00:00:00",
        "endTime": "2015-10-21T23:59:59.999",
        "condCode": "A21",
        "condText": "Cloudy, Light Rain, Light Wind/Calm",
        "precipPercent": 98.22916666666667,
        "sunPercent": 2.739583303531011,
        "precip": 7.638886701315641,
        "cloudPercent": 97.2604169845581,
        "wind": 1.9227394238114357,
        "maxTemperature": 20.350000381469727,
        "minTemperature": 6.966670036315918,
        "solar": 697.3311836719513,
        "meanRelativeHumidity": 82.76669136683147
      }
    ]

In the new API, the format is formatted as:

{
  "startTime": "2015-10-21T00:00:00+00:00",
  "endTime": "2015-10-21T23:59:59+00:00",
  "conditionsCode": "521",
  "conditionsText": "Cloudy, Light Rain, Light Wind/Calm",
  "temperatures": {
    "max": 12.433310508728027,
    "min": 7.299999713897705,
    "units": "C"
  },
  "precipitation": {
    "chance": 6.666666661699613,
    "amount": 0.005555666983127594,
    "units": "mm"
  },
  "sky": {
    "cloudCover": 92.31597232818604,
    "sunshine": 7.684027906507254
  },
  "solar": {
    "amount": 3383.0093383789063,
    "units": "Wh/m^2"
  },
  "relativeHumidity": {
    "average": 35.00625960032145,
    "max": null
  },
  "wind": {
    "average": 0.8600191188355287,
    "max": null,
    "units": "m/sec"
  }
}

Weather Forecast API Documentation

Get GDDs for a Field Location

Version-1

The older API combined most weather and agronomic attirbutes into one endpoint. To get the agronomics you would need to specify those parameters in the URI like so:

GET /v1/weather?latitude=39.8282&longitude=-98.5795&startDate=2015-10-01&attribute=gdd
Next-Gen

The new APIs have an API dedicated to calculated agronomic values, which includes GDD, PET, P/PET, and Accumulations. The corresponding API call to the above example is:

GET /v2/agronomics/fields/field1/agronomicvalues/2015-10-01

Like the weather APIs, all properties are included by default, but you can weed out the ones you don't need with the properties query string parameter. Review the documentation for the options.

Date Ranges

The Agronomic Values API can retrieve these calculated values for a specific day or a range of specified days. Extending the previous example, this call would return a week's worth of values:

GET /v2/agronomics/fields/field1/agronomicvalues/2015-10-01,2015-10-07

The new APIs, though, can also manage date selection in the background. Just like you create a field location to record information about the physical field, you can use the Plantings API to record data about the crop activity planted in that field. When you store the planting date, for example, the Agronomic Values API can retrieve it automatically so you don't have to worry about specifying dates. When used like this, the API returns data for everything from the planting date through today:

GET /v2/agronomics/fields/field1/agronomicvalues

Choosing an Equation

The new APIs continue to support multiple GDD equations depending on your use case. The new default GDD equation is the "Standard" equation, which runs a simple GDD calculation with no adjustments to the input values:

[ (Max Temp + Min Temp) / 2 ] — Base Temp

Important: Version 1's GDD calculation used a different equation as the default, what we now refer to as min-temp-constant. So if your older API call for GDDs was:

GET /v1/weather?latitude=39.8282&longitude=-98.5795&startDate=2015-10-01&attribute=gdd

In the new API you should use the following parameters:

GET /v2/agronomics/fields/field1/agronomicvalues?gddMethod=min-temp-constant

The general functionality of the GDD equations and base or boundary temperatures remains similar to version 1, though the names of the parameters have changed. Review this section of the documentation on GDD equations for more details.

Agronomic Values API Documentation   Plantings API Documentation

Get Accumulated GDD or Precipitation

Version-1

The older API combined most weather and agronomic attirbutes into one endpoint. To get accumulated precipitation or GDDs you would need to specify those parameters in the URI like so:

GET /v1/weather?latitude=39.8282&longitude=-98.5795&startDate=2015-10-01&endDate=2015-10-15&attribute=accGdd&attribute=accPrecip

Additionally, the only way to get just a total accumulation was to request the entire range of days, and then look only at the last day. For a season's worth of data, this was a lot of extra data for a single value.

Next-Gen

The new APIs have an API dedicated to calculated agronomic values, which includes GDD, PET, P/PET, plus accumulated GDD, Precip, PET, and P/PET. The corresponding API call to the above example is:

GET /v2/agronomics/fields/field1/agronomicvalues/2015-10-01,2015-10-15

One of the biggest differences in the response payload is that we now include an object containing only the total accumulations for the selected range, in addition to the daily data that increments over each day of data in the response:

{
"location":":{
   "latitude":{latitude},
   "longitude":{longitude},
   "fieldId":"{fieldId}",
   },
"accumulations":{ 
   "gdd":{accumulatedGDD},
   "precipitation":":{
       "amount":{accumulatedPrecipitation},
       "units":"{accPrecipUnits}"
       },
   "pet":{
       "amount":{accumulatedPET},
       "units":"{accPetUnits}"
       },
   "ppet":{accumulatedPPET}
   },
"dailyValues":[{
   "date":"{date}",
   "gdd":{gdd},
   "pet":{
       "amount":{pet},
       "units":"{petUnits}"
       },
   "ppet":{pPet},
   "accumulatedGdd":{rollingAccumulatedGDD}, 
   "accumulatedPrecipitation":":{
       "amount":{rollingAccumulatedPrecip},
       "units":"{rollingAccPrecipUnits}"
       },
   "accumulatedPet":{
       "amount":{rollingAccumulatedPET},
       "units":"{rollingAccPetUnits}"
       },
   "accumulatedPpet":{rollingAccumulatedPPET},
   "_links":{ 
       "self":{"href":"{dailyValueSelfHref}"},
       "curies":[{
           "name":"awhere",
           "href":"http://awhere.com/rels/{rel}",
           "templated":true
           }],
       "awhere:field":{"href":"{fieldHref} "},
       "awhere:planting":{"href":"{plantingHref}"}
       }
   },{ 
      ...etc...
     }
   ]
}

Like the weather APIs, all properties are included by default, but you can weed out the ones you don't need with the properties query string parameter. Review the documentation for the options. Of particular note is one of the options for properties selection is to get only the total accumulations, and exclude all the daily data, which you may not need or want.

GET /v2/agronomics/fields/field1/agronomicvalues/2015-10-01,2015-10-15?properties=accumulations

Review the documentation for more options on filtering just the data you want.

As described in the previous section, this API can use the Plantings API to retrieve the planting date for the field. For accumulation requests, it will return the accumulations since the planting date through today. You can also start accumulating from an earlier date, using the accumulationStartDate property:

GET /v2/agronomics/fields/field1/agronomicvalues/2015-10-01,2015-10-15?accumulationStartDate=2015-07-15
GET /v2/agronomics/fields/field1/agronomicvalues?accumulationStartDate=2015-07-15

Agronomic Values API Documentation   Plantings API Documentation

Compare Accumulated GDD or Precipitation to Long-Term Averages

Version-1

The older API combined most weather and agronomic attirbutes into one endpoint. Long term averages for accumulated precipitation, GDD, and PET were provided as single static data points, either as 3-year or 10-year. To get comparison periods with the older API, the request would look like:

GET /v1/weather?latitude=39.8282&longitude=-98.5795&startDate=2015-10-01&endDate=2015-10-15&attribute=accGdd3YearAverage&attribute=accGddLongTermAverage&attribute=accPrecip3YearAverage&attribute=accPrecipLongTermAverage

Additionally, the only way to get just a total accumulation was to request the entire range of days, and then look only at the last day. For a season's worth of data, this was a lot of extra data for a single value.

Next-Gen

There are two ways to get comparison periods in the new APIs. To get just the prior year comparison, simply make another Agronomic Values request with the dates from last year. But to calculate multi-year averages, we've created a more powerful and flexible Agronomic Norms API. To get a three-year average for all of the Agronomic Values (both daily and accumulations), you can use a request like the one below. This example would get the averages from July from 2011-2014:

GET /v2/agronomics/fields/field1/agronomicnorms/07-01,07-31/years/2011,2014

As described in the previous section, this API can use the Plantings API to retrieve the planting date for the field. You can then choose to exclude the month-and-day portion and just include the years:

GET /v2/agronomics/fields/field1/agronomicnorms/years/2011,2014

If you exclude the years, the API will default to a 10-year average. You must specify at least three years to average across.

Like the Agronomic Values API for accumulations, this API can return just the average total accumulations in addition to or instead of the daily averages.

Agronomic Values API Documentation   Plantings API Documentation

Get Long-Term Averages of Temperature or Precipitation

Version-1

In the older APIs, the only way to get long-term averages of meteorological attributes was to pull multiple individual years of data and then calculate the daily averages yourself.

Next-Gen

In the new APIs, we now have an API that can calculate the long-term averages for all of our weather data points across any number of years (minimum three). For example, to get the averages for every day in July from across 2010-2015, you would use an API call like this:

GET /v2/weather/fields/field1/norms/07-01,07-31/years/2010,2015

If you leave off the years, you will get a 10-year average by default. This API also returns the standard deviation for the values used to calculate the mean.

Weather Norms API Documentation

Get Temperatures in Fahrenheit and Precipitation in Inches

Version-1

The older APIs include a query string parameter that returned temperature units in Fahrenheit temperatures, to make it easier to display temperatures in US-based applications. The old endpoint used the temperatureUnits parameter:

GET /v1/weather?latitude=39.8282&longitude=-98.5795&startDate=2015-10-01&endDate=2015-10-10&attribute=minTemperature&attribute=maxTemperature&temperatureUnits=fahrenheit
Next-Gen

The new APIs still return data in metric units by default (e.g., Celsius, millimeters, kph, etc), but now you can choose to return all numeric values in units that are commonly used in the USA (Fahrenheit, inches, mph, etc). Any API that has this option will include a units property with the response. To use this option, use the units query string parameter with a value of usa:

GET /v2/weather/fields/field1/observations?units=usa

Request Data Many Locations at Once (Batch Jobs)

Version-1

The older APIs did have a limited batch job system where you could POST many locations and configurations to get them back all at once. The system was synchronous and limited in the number of locations it could manage at once.

Next-Gen

The new APIs feature an all-new batch job system that can run any number of API calls for you at once, allowing you to queue up a large daily pull of data, for example. It's an asynchronous process, so you'll need to check back periodically to see if the job is done, but once it is the system will provide all the results in a single response.

Batch Jobs Documentation