How to Migrate from Deprecated 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 "V1" APIs. For any clients still on our very first generation of APIs, this guide will detail the changes necessary to ensure you are using the most reliable technology we have in service. If you are using the "V1" APIs, then there is a separate guide for you.

How to Identify Deprecated Services

You can know you're using deprecated services if:

  • For Authentication, you access /api/weather/Login/Index and save a cookie value
  • You access either of these endpoints for weather data:
    • /api/weather/season
    • /api/weather/daily

Hostname

Deprecated Hostname

The old APIs use a URL beginning with

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

Migration

Moving forward, the our APIs will 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 deprecated APIs use a cookie-based authentication method. This requires a POST to

/api/weather/Login/Index

with a username and password, and then parsing the HTTP response to find the Set-Cookie header and save that. On subsequent requests, the cookie is included as a header. Note that in recent months, the code that processes this method has begun to fall in disrepair and can cause trouble when retrieving weather data.

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.

Daily Weather Service Transition

This details how to transition away from /api/weather/daily.

Deprecated Approach

The deprecated APIs require a JSON-formatted payload be sent as a query string parameter in the URL. For example:

GET https://data.awhere.com/api/weather/daily?json_request=[{"lat":-1.5089, "lon":37.2947,"start":"01-12-2013"}]

The json_request value is an array of objects, and each object is a different location & start date. This allows for a batch approach to reduce the number of API calls required for many fields at once. Each object has a set of available properties for customizing the request, such as lat, lon, start, etc.

Migration: Single Requests by GET

A RESTful API design prefers using GET to retrieve a single location's data.

With the new APIs, you'll need to first create a field location that includes the latitude and longitude of the field, plus other relevant data you may want to store to speed up future agronomic and modeling calculations. When you create a field, you'll assign it an ID that you'll use to request data in most API calls.

For example, the deprecated example above requests the weather for January 1, 2013 at a specific geolocation. In the new APIs, you'll first create the field with the Create Field API:

POST /v2/fields

{
    "id": "field-1",
    "name":"My First Field",
    "farmId":"farm-1",
    "acres":80,
    "centerPoint":{
        "latitude":-1.5089,
        "longitude":37.2947,
        }
}

And then you can request the observed weather for that field on January 1, 2013:

GET /v2/weather/fields/field-1/observations/2013-01-13

The new APIs also support getting many days of data in a single API call. This example would return 14 days worth of weather observations for the identified field:

GET /v2/weather/fields/field-1/observations/2013-01-01,2013-01-14

Migration: Batch Requests

The deprecated approach allowed for requesting many locations or days in a single request, but doing that by a GET is inefficient. Instead, we've create a brand-new batch job system that allows you to instruct the platform to run any number of individual requests for you in sequence. So if you have 100 fields and you want the weather for January 13 for all of them, you'd create a job that essentially tells the platform to run all of these API calls for you:

GET /v2/weather/fields/field-1/observations/2013-01-13
GET /v2/weather/fields/field-2/observations/2013-01-13
GET /v2/weather/fields/field-3/observations/2013-01-13
GET /v2/weather/fields/field-4/observations/2013-01-13
GET /v2/weather/fields/field-5/observations/2013-01-13
GET /v2/weather/fields/field-6/observations/2013-01-13
... etc ...

Almost any of our APIs can be run in a batch. Read the Batch Jobs documentation for more.

Requesting Weather Attributes

In the older generation APIs, you were required to request the specific weather attributes you wanted for a given day. In the new platform, all relevant data attributes are returned by default. You can filter properties out for efficiency, but there is no longer a need to specifically request the attributes you want. Additionally, 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:

[{"daily-weather":[
  { "date":"2013-01-13",
    "max-temp":20 }
]}]
The API now returns something like:
{
  "date":"2013-01-13",
  "temperatures":{
     "max":20,
     "min":17,
     "units":"C"
   }
}

Weather and Agronomics are Split Into Two APIs

In the older versions of our APIs, we combined observed weather, forecasts, and agronomic values all into one API. In the new platform, we use a lightweight microservice design that reduces the complexity and improves efficiency.

The table below identifies the name of the attribute/property from the Deprecated APIs, and the corresponding location of that data in the new 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.

Deprecated Attribute New API New Attribute Path Description
min-temp Observations temperatures.min Lowest recorded air temperature during the day
max-temp Observations temperatures.max Highest recorded air temperature during the day
prec Observations precipitation.amount Total daily precipitation
acc-precip Agronomic Values accumulatedPrecipitation.amount Total accumulated precipitation since startDate
solar-rad Observations solar.amount Summation of total solar energy
min-hum Observations humidity.min Lowest relative humidity during the day
max-hum Observations humidity.max Highest relative humidity during the day
morn-wind Observations wind.morningMax Morning's highest wind speed
max-wind Observations wind.dayMax Day's highest wind speed
gdd Agronomic Values gdd Growing degree days, # of heat units achieved during the day.
acc-gdd Agronomic Values accumulatedGdd Total accumulated GDDs since startDate

Season Service Transition

This details how to transition away from /api/weather/season.

The original Season service provided averages and accumulations of key attributes over the course of a date range and the 10 year average for that date range. The new APIs are much more flexible; accumulations and agronomic values are now condensed into a single API that makes it simpler to get totals, and averages can be calculated for any observed weather or agronomic value.

Getting Accumulations

To get accumulated GDDs and accumulated precipitation over a time range, use this request to the new Agronomic Values API (this shows a request for 2 weeks of data from July):

https://api.awhere.com/v2/agronomics/fields/field-1/agronomicvalues/2015-07-01,2015-07-14

The response from the API will include:

  • An accumulations object that gives the total accumulated GDD, precipitation, PET, and P/PET for the whole range of days
  • A dailyValues array with an object for each day in the range, and the accumulation grows from the first object to the next (this make charting easier).

Here's an example 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}"}
        }
    },{ 
       ...
      }
    ],
 "_links":{
    "self":{"href":"{selfLink}"},
    "curies":[{     
        "name":"awhere",
        "href":"http://awhere.com/rels/{rel}",
        "templated":true
        }],
    "awhere:field":{"href":"{fieldHref}"}
 }
}

Getting Comparison Period Averages

Like the deprecated API, the new version includes the option to get the historical average of accumulations. The new version, though, is much more flexible and you can get averages for any range of days over any number of years. As an example, the request for averages from May 1 through May 31 from across 2010-2015, you use the Agronomic Norms API like so:

GET /v2/agronomics/fields/field-1/agronomicnorms/05-01,05-31/years/2010,2015

In the new version, any data point we return in the Agronomic Values API can be averaged in the norms API, including GDD, PET, P/PET, and accumulated GDD, Preciptiation, PET, and P/PET.

We have a similar Norms API for weather attributes that can return the long term normals for any of those weather data points, including temperatures, daily precipitation, wind, solar, and humidity.