NAV
shell go http

Introduction

This is the Leaf Documentation.

API Reference

This is the Leaf API Reference.

Authorization Signature

The client has an api key and api secret. See /login on how to get these.

General Format

The auth is done via the Authorization HTTP header.

The expected format of this header is:

VERSION KEY=VAL, KEY2=VAL2, KEY3=VAL3

curl -H 'Authorization: VERSION KEY=VAL, KEY2=VAL2, KEY3=VAL3' https://api.leaf.ag/auth/v1/check-signature
req, _ := http.NewRequest("GET", "/check-signature", nil)
req.Header.Set("Authorization", "VERSION KEY=val, KEY2=VAL2, KEY3=VAL3")
GET /check-signature HTTP/1.1
Host: api.leaf.ag
Authorization: VERSION KEY=VAL, KEY2=VAL2, KEY3=VAL3

Expected header format.

Sequence Diagram

alt text diagram

AGSIG0

AGSIG0 is going to be used for service to service auth.

AGSIG1

Format

curl -H 'Authorization: AGSIG1 key=$API_KEY, signature=$signature, ts=$timetamp, nonce=$nonce' \
     https://api.leaf.ag/auth/v1/check-signature?id=1&guid=2
req, _ := http.NewRequest("GET", "/check-signature?id=1&guid=2", nil)
req.Header.Set("Authorization", fmt.Sprintf("AGSIG1 key=%s, signature=%s, ts=%d, nonce=%s", apiKey, signature, timestamp, nonce))
GET /check-signature?id=1&guid=2 HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<api key>, signature=<request signature>, ts=<timestamp>, nonce=<nonce>

AGSIG1 Format.

The format for AGSIG1 is the following:

AGSIG1 key=<client api key>, signature=<request signature>, ts=<request timestamp (nano)>, nonce=<random string>

Signature

The signature is expected to be hmac / sha256 with the client’s api secret, encoded in hexadecimal.

The signatureString is the concatenation of the following fields: (in that exact order)

Example

package main

import (
        "crypto/hmac"
        "crypto/sha256"
        "encoding/hex"
)

func main() {
        str := "AGSIG1GET/pullid=1&guid=214460642579972822224722613af3bf1dfbb0e177e2edbd0412"
        hash := hmac.New(sha256.New, []byte("bde"))
        _, _ = hash.Write([]byte(str))
        println(hex.EncodeToString(hash.Sum(nil)))
        // output: b7ce50891744978ec926b369f0e164bf6a5efa5f7ebe0273aaba7c07f0a4d416
}

AGSIG1 Signature Example (Go). Playground

import jsSHA from "jssha";
let shaObj = new jsSHA("SHA-256", "TEXT");
shaObj.setHMACKey("bde", "TEXT");
shaObj.update("AGSIG1GET/pullid=1&guid=214460642579972822224722613af3bf1dfbb0e177e2edbd0412");
console.log(shaObj.getHMAC("HEX"));
// output: b7ce50891744978ec926b369f0e164bf6a5efa5f7ebe0273aaba7c07f0a4d416

AGSIG1 Signature Example (Javascript)

curl -H 'Authorization: AGSIG1 key=abc, signature=b7ce50891744978ec926b369f0e164bf6a5efa5f7ebe0273aaba7c07f0a4d416, ts=1446064257997282222, nonce=4722613af3bf1dfbb0e177e2edbd0412' \
     https://api.leaf.ag/auth/v1/check-signature?id=1&guid=2
req, _ := http.NewRequest("GET", "/check-signature?id=1&guid=2", nil)
req.Header.Set("Authorization", "AGSIG1 key=abc, signature=b7ce50891744978ec926b369f0e164bf6a5efa5f7ebe0273aaba7c07f0a4d416, ts=1446064257997282222, nonce=4722613af3bf1dfbb0e177e2edbd0412")
GET /check-signature?id=1&guid=2 HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=abc, signature=b7ce50891744978ec926b369f0e164bf6a5efa5f7ebe0273aaba7c07f0a4d416, ts=1446064257997282222, nonce=4722613af3bf1dfbb0e177e2edbd0412

AGSIG1 Request example.

API keys for client from auth /login: - API_KEY=abc - API_SECRET=bde

Signature string:

AGSIG1GET/pullid=1&guid=214460642579972822224722613af3bf1dfbb0e177e2edbd0412

Signature hashed with user’s secret (bde):

b7ce50891744978ec926b369f0e164bf6a5efa5f7ebe0273aaba7c07f0a4d416

AGSIG2

AGSIG2 will add support for body and extra headers to be part of the signature.

Authorization Endpoints

All requests to the auth endpoints must be prefixed by /auth/v1.

Request and response bodies are JSON-encoded.

Register

POST /register HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
  "email":        "email@domain.com",
  "first_name":   "Bob",
  "last_name":    "Odenkirk",
  "password":     "password",
  "company_name": "Company, inc",
  "private_key":  "abcdef"
}
HTTP/1.1 201 CREATED
Connection: close
curl "https://api.leaf.ag/auth/v1/register" \
  -X POST \
  -d '{
          "email":        "email@domain.com",
          "first_name":   "Bob",
          "last_name":    "Odenkirk",
          "password":     "password",
          "company_name": "Company, inc",
          "private_key":  "abcdef"
      }'
type RegisterRequest struct {
    CompanyName string   `json:"company_name"`
    Email       string   `json:"email"`
    FirstName   string   `json:"first_name"`
    LastName   string    `json:"last_name"`
    Password    string   `json:"password"`
    PrivateKey  string   `json:"private_key"`
}

Register request.

Register a new user in the Leaf system.

When provided with a valid email address, a password, and the correct private_key a client is presented with a 201.

HTTP Request

POST /register

Parameter Type Default Description
email string The user’s email
first_name string The user’s first name
last_name string The user’s last name
password string The user’s password
company_name string The user’s company
private_key string The leaf private key (ask Guillaume or Jason)

HTTP Response

Login

POST /login HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
  "email":        "email@domain.com",
  "password":     "password"
}
curl "https://api.leaf.ag/auth/v1/login"
  -X POST
  -d '{
          "email":    "email@domain.com",
          "password": "password"
      }'
type AuthRequest struct {
    Email    string `json:"email"`
    Password string `json:"password"`
}

Login request.

HTTP/1.1 202 ACCEPTED
Content-Type: application/json

{
   "api_key":"47a88ee3a11c0163e3ca7485a9de950a",
   "api_secret":"13e6c0ab4ed938b2cef1905b2f73b7f8",
   "user":{
    "id":"91476417-45f9-4f2c-9cbf-397d0bd06314",
    "timezone":"MST",
    "company_id":2,
    "email":"email@domain.com",
    "role":"manager",
    "created_at":"2016-02-25T19:10:27.283485Z",
    "updated_at":"2016-02-25T19:10:27.283485Z"
   }
}
{
   "api_key":"47a88ee3a11c0163e3ca7485a9de950a",
   "api_secret":"13e6c0ab4ed938b2cef1905b2f73b7f8",
   "user":{
    "id":"91476417-45f9-4f2c-9cbf-397d0bd06314",
    "timezone":"MST",
    "company_id":2,
    "email":"email@domain.com",
    "role":"manager",
    "created_at":"2016-02-25T19:10:27.283485Z",
    "updated_at":"2016-02-25T19:10:27.283485Z"
   }
}
type AuthResponse struct {
    APIKey    string      `json:"api_key"`
    APISecret string      `json:"api_secret"`
    User      *users.User `json:"user"`
}

Login response.

Login as a registered user of the Leaf system.

When provided with a registered email and the correct corresponding password the client is presented with a 202 and a json response with the api key and api secret as api_key and api_secret in the payload. It is the client’s repsonsibility to store the key/secret pair to sign future requests. Note that email is case-insensitive.

HTTP Request

POST /login

Parameter Type Default Description
email string The user’s email
password string The user’s password

HTTP Response

Parameter Type Description
api_key string The user’s api key (public).
api_secret string The user’s api secret (private).
user user Logged in user object. Including the timezone.

Logout

POST /logout HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
gurl -X POST -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/auth/v1/logout"

Logout request.

HTTP/1.1 200 OK
Content-Type: application/json

Logout response.

Logout the current user.

HTTP Request

POST /logout

HTTP Response

Check-Signature

GET /check-signature HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
HTTP/1.1 200 OK
Connection: close
# Get $API_KEY and $API_SECRET from /login
gurl -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/auth/v1/check-signature"
import (
        "github.com/agrarianlabs/service/lib/signer"
        "github.com/agrarianlabs/service/lib/signer/agsig1"
)

//...

client, _ := signer.NewClient("http://api.leaf.ag/auth/v1", apiKey, apiSecret, agsig1.Version)
resp, _ := client.DoRequest("GET", "/check-signature", "", nil, nil)

Check Signature request.

Checks that the signature in the Authorization header is valid.

HTTP Request

GET /check-signature

HTTP Response

Confirm

POST /confirm HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
    "email": "user@domain.com",
    "password": "my_new_pa$$word",
    "company_name": "my_company_name",
    "token": "21c979b214169b4370bc8075c2162f83"
}
curl -v -X POST \
-d '{
        "email": "user@domain.com",
        "password": "my_new_pa$$word",
        "company_name": "my_company_name",
        "token": "21c979b214169b4370bc8075c2162f83"
    }' \
https://api.leaf.ag/auth/v1/confirm

Confirm an invitation to join a company on Leaf.

Request Body

Field Type Required Notes
email string yes A valid RFC 5322 email address
password string yes The user’s new password
company_name string yes The name of the company the user wishes to join
token string yes A token used to validate the user’s request

Status Codes

Invite

POST /invite HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
    "email": "user@domain.com"
}
curl -v -X POST \
-d '{
        "email": "user@domain.com"
    }' \
https://api.leaf.ag/auth/v1/invite

Resend an invitation email.

Request Body

Field Type Required Notes
email string yes The email of the user whose invitation you wish to resend.

Status Codes

Health

GET /health HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 200 OK
Connection: close
curl -v "https://api.leaf.ag/auth/v1/health"

Health request.

Checks the health of this service.

HTTP Request

GET /health

HTTP Response

Heartbeats

Submit Heartbeats

gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '[{
    "user_id":             "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
    "managementzone_id":   "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380b22",
    "device_id":           "0000-0000-0000-0000",
    "lat":                 30.25,
    "long":                97.75,
    "heading":             1.2,
    "speed":               33.5,
    "horizontal_accuracy": 10.0,
    "vertical_accuracy":   0.034,
    "gps_timestamp":       1447625945,
    "timetamp":            1447625946,
    "beacons": [
       {
         "proximity_uuid": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
         "major": 1,
         "minor": 3,
         "distance": 11.2
       }
    ],
    "paired_beacons": [
       {
         "proximity_uuid": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22",
         "major":    1,
         "minor":    3,
         "distance": 11.2
       }
    ]}]' \
  "https://api.leaf.ag/heartbeats/v1/heartbeat"
POST /heartbeat HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

[{
    "user_id":             "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
    "managementzone_id":   "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380b22",
    "device_id":           "0000-0000-0000-0000",
    "lat":                 30.25,
    "long":                97.75,
    "heading":             1.2,
    "speed":               33.5,
    "horizontal_accuracy": 10.0,
    "vertical_accuracy":   0.034,
    "gps_timestamp":       1447625945,
    "timetamp":            1447625946,
    "beacons": [
       {
         "proximity_uuid": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
         "major": 1,
         "minor": 3,
         "distance": 11.2
       }
    ],
    "paired_beacons": [
       {
         "proximity_uuid": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22",
         "major":    1,
         "minor":    3,
         "distance": 11.2
       }
    ]
}]
HTTP/1.1 200 OK
Connection: close

Submit Heartbeats request.

Create heartbeats in the system.

All requests sent to the service will be recorded regardless if the POST payload contains the expect post parameters.

HTTP Request

POST /heartbeat

Parameters

Heartbeats are required to be sent in batch. (json list of heartbeat objects)

Parameter Type Description
device_id string The device id. For iOS, it will be the serial number.
user_id string The operator/user’s uuid.
managementzone_id string The managementzone’s uuid.
lat float64 Latitude Location. The units of lat is degrees.
long float64 Longitude Location. The units of long is degrees.
heading float64 Heading of the device. The units of heading is degrees.
speed float64 Speed of the device. The units of speed is meters/second.
horizontal_accuracy float64 Horizontal accuracy (in feet) of the GPS measurement.
vertical_accuracy float64 Vertical accuracy (in feet) of the GPS measurement.
gps_timestamp int UTC timestamp when the GPS data was observed.
timestamp int UTC timestamp when the client sent the heartbeats.
beacons []beacon Nearby beacon list.
paired_beacons []beacon Paired beacon list.
Beacon
Parameter Type Description
proximity_uuid string Beacon proximity uuid.
major int Beacon Major version.
minor int Beacon Minor version.
distance float64 Beacon distance from device. The units of distance is meters.

Health

curl "https://api.leaf.ag/heartbeats/v1/health"

Checks the health of this service.

HTTP Request

GET /health

Users

All users endpoints must be prefixed with /resources/v1.

Eventually, when breaking changes are deployed we will create new versions and update this document accordingly.

All requests and responses must be JSON-encoded.

Add Users

POST /users HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
    "email":                          "user@domain.com",
    "role":                           "manager",
    "prefix_name":                    "Sir",
    "first_name":                     "David",
    "middle_name":                    "John",
    "last_name":                      "Cross",
    "suffix_name":                    "Jr.",
    "phone_number":                   "(602) 867-7193",
    "employee_id":                    "283746345",
    "emergency_contact_name":         "Mama Cross",
    "emergency_contact_phone":        "(602) 555-5555",
    "emergency_contact_relationship": "mother",
    "tags": [
        "tag1",
        "tag2"
    ]
}
HTTP/1.1 201 CREATED
Connection: Close
gurl \
  -X POST \
  -d '{
    "email":                          "user@domain.com",
    "role":                           "manager",
    "prefix_name":                    "Sir",
    "first_name":                     "David",
    "middle_name":                    "John",
    "last_name":                      "Cross",
    "suffix_name":                    "Jr.",
    "phone_number":                   "(602) 867-7193",
    "employee_id":                    "283746345",
    "emergency_contact_name":         "Mama Cross",
    "emergency_contact_phone":        "(602) 555-5555",
    "emergency_contact_relationship": "mother",
    "tags": [
        "tag1",
        "tag2"
    ]
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/users"

Add a new users for a company.

Request Body

Field Type Required Notes
role string yes “manager” or “operator”
email string only if role is “manager” A valid RFC 5322 email address
prefix_name string no
first_name string yes
middle_name string no
last_name string yes
suffix_name string no
phone_number string no
employee_id string no
emergency_contact_name string no
emergency_contact_phone string no
emergency_contact_relationship string no
description string no
hire_date RFC 3339 timestamp no
tags []string no

Status Codes

Response Body

JSON-encoded string containing the ID of the new users.

Example: "8EF57207-9D29-4C4F-8954-FCEFFED272A7"

Get Users

GET /users/8EF57207-9D29-4C4F-8954-FCEFFED272A7 HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json
HTTP/1.1 200 OK
Connection: Close

{
    "id":                             "8EF57207-9D29-4C4F-8954-FCEFFED272A7",
    "company_id":                     5,
    "company_name":                   "GloboChem",
    "email":                          "user@domain.com",
    "role":                           "manager",
    "prefix_name":                    "Sir",
    "first_name":                     "David",
    "middle_name":                    "John",
    "last_name":                      "Cross",
    "suffix_name":                    "Jr.",
    "phone_number":                   "(602) 867-7193",
    "employee_id":                    "283746345",
    "emergency_contact_name":         "Mama Cross",
    "emergency_contact_phone":        "(602) 555-5555",
    "emergency_contact_relationship": "mother",
    "tags": [
        "tag1",
        "tag2"
    ],
    "latest_location":{
        "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
        "long":51.5034070,
        "lat":-0.1275920,
        "heading":1,
        "speed":19.4,
        "created_at":"2016-03-04T18:44:41.914068Z"
    }
}
gurl \
  -X GET \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/users/8EF57207-9D29-4C4F-8954-FCEFFED272A7"

{
        "id":                             "8EF57207-9D29-4C4F-8954-FCEFFED272A7",
    "company_id":                     5,
    "company_name":                   "GloboChem",
    "email":                          "user@domain.com",
    "role":                           "manager",
    "prefix_name":                    "Sir",
    "first_name":                     "David",
    "middle_name":                    "John",
    "last_name":                      "Cross",
    "suffix_name":                    "Jr.",
    "phone_number":                   "(602) 867-7193",
    "employee_id":                    "283746345",
    "emergency_contact_name":         "Mama Cross",
    "emergency_contact_phone":        "(602) 555-5555",
    "emergency_contact_relationship": "mother",
    "tags": [
        "tag1",
        "tag2"
    ],
    "latest_location":{
        "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
        "long":51.5034070,
        "lat":-0.1275920,
        "heading":1,
        "speed":19.4,
        "created_at":"2016-03-04T18:44:41.914068Z"
    }
}

Get a users’s profile.

Status Codes

Response Body

Field Type Required Description
id string
company_id string
company_name string
email string no
prefix_name string no
first_name string no
middle_name string no
last_name string no
suffix_name string no
phone_number string no
employee_id string no
emergency_contact_name string no
emergency_contact_phone string no
emergency_contact_relationship string no
description string no
hire_date RFC 3339 timestamp no
tags []string no
latest_location object no see details in example.

List Users

GET /users HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 200 OK
Content-Type: application/json
Connection: Close

[
    {
        "id":"fc25e422-75fe-44e5-af38-e1d14ee3d7c0",
        "company_id":1,
        "email":"leaftest@example.com",
        "role":"manager",
        "created_at":"2016-01-28T20:21:59.950723Z",
        "updated_at":"2016-01-28T20:21:59.950723Z",
        "latest_location":{
            "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
            "long":51.5034070,
            "lat":-0.1275920,
            "heading":1,
            "speed":19.2,
            "created_at":"2016-03-04T18:44:41.914068Z"
        }
    },
    {
        "id":"cc0ad904-1eb4-4597-8206-d59d34b6a689",
        "company_id":1,
        "role":"operator",
        "prefix_name":"Sir",
            "first_name":"David",
            "middle_name":"John",
            "last_name":"Cross",
            "suffix_name":"Jr.",
        "phone_number":"(602) 867-7193",
        "employee_id":"abc123",
        "emergency_contact_name":"Van Hammersly",
        "emergency_contact_phone":"(602) 992-4135",
        "emergency_contact_relationship":"Mr Show Character",
        "description":"Entitilitus sufferer",
        "hire_date":"2015-12-19T05:15:45Z",
        "created_at":"2016-01-28T20:22:31.894883Z",
        "updated_at":"2016-01-28T20:22:31.894883Z"
    },
    {
        "id":"9d8b4db1-3e2e-4fe0-a9a6-50343d8dfc58",
        "company_id":1,
        "role":"operator",
        "first_name":"Pitpat",
        "created_at":"2016-01-28T20:22:32.055668Z",
        "updated_at":"2016-01-28T20:22:32.060941Z"
    },
    {
        "id":"2fcfe7e3-c65e-419a-8b8e-66d051b69061",
        "company_id":1,
        "role":"operator",
        "description":"National Talk Backwards for Entitilitus Day",
        "created_at":"2016-01-28T20:22:32.154424Z",
        "updated_at":"2016-01-28T20:22:32.165249Z",
        "latest_location":{
            "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
            "long":59.5034070,
            "lat":-10.1275920,
            "heading":1,
            "speed":14.2,
            "created_at":"2016-03-04T18:44:41.914068Z"
        }

    },
    {
        "id":"f43b23b2-a56f-4b1e-b082-897910569786",
        "company_id":1,
        "role":"manager",
        "created_at":"2016-01-28T20:22:32.389624Z",
        "updated_at":"2016-01-28T20:22:32.408093Z"
    }
]
gurl \
  -X GET \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/users"

[
    {
        "id":"fc25e422-75fe-44e5-af38-e1d14ee3d7c0",
        "company_id":1,
        "email":"leaftest@example.com",
        "role":"manager",
        "created_at":"2016-01-28T20:21:59.950723Z",
        "updated_at":"2016-01-28T20:21:59.950723Z",
        "latest_location":{
            "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
            "long":51.5034070,
            "lat":-0.1275920,
            "heading":1,
            "speed":19.2,
            "created_at":"2016-03-04T18:44:41.914068Z"
        }
    },
    {
        "id":"cc0ad904-1eb4-4597-8206-d59d34b6a689",
        "company_id":1,
        "role":"operator",
        "prefix_name":"Sir",
            "first_name":"David",
            "middle_name":"John",
            "last_name":"Cross",
            "suffix_name":"Jr.",
        "phone_number":"(602) 867-7193",
        "employee_id":"abc123",
        "emergency_contact_name":"Van Hammersly",
        "emergency_contact_phone":"(602) 992-4135",
        "emergency_contact_relationship":"Mr Show Character",
        "description":"Entitilitus sufferer",
        "hire_date":"2015-12-19T05:15:45Z",
        "created_at":"2016-01-28T20:22:31.894883Z",
        "updated_at":"2016-01-28T20:22:31.894883Z"
    },
    {
        "id":"9d8b4db1-3e2e-4fe0-a9a6-50343d8dfc58",
        "company_id":1,
        "role":"operator",
        "first_name":"Pitpat",
        "created_at":"2016-01-28T20:22:32.055668Z",
        "updated_at":"2016-01-28T20:22:32.060941Z"
    },
    {
        "id":"2fcfe7e3-c65e-419a-8b8e-66d051b69061",
        "company_id":1,
        "role":"operator",
        "description":"National Talk Backwards for Entitilitus Day",
        "created_at":"2016-01-28T20:22:32.154424Z",
        "updated_at":"2016-01-28T20:22:32.165249Z"
        "latest_location":{
            "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
            "long":59.5034070,
            "lat":-10.1275920,
            "heading":1,
            "speed":14.2,
            "created_at":"2016-03-04T18:44:41.914068Z"
        }
    },
    {
        "id":"f43b23b2-a56f-4b1e-b082-897910569786",
        "company_id":1,
        "role":"manager",
        "created_at":"2016-01-28T20:22:32.389624Z",
        "updated_at":"2016-01-28T20:22:32.408093Z"
    }
]

List users for a company.

Status Codes

Response Body

Field Type Required Description
id string
company_id string
company_name string
email string
prefix_name string no
first_name string no
middle_name string no
last_name string no
suffix_name string no
phone_number string no
employee_id string no
emergency_contact_name string no
emergency_contact_phone string no
emergency_contact_relationship string no
description string no
hire_date RFC 3339 timestamp no
latest_location object no see details in example.

Edit users

PUT /users/8EF57207-9D29-4C4F-8954-FCEFFED272A7 HTTP/1.1
Host: api.leaf.ag

{
    "email": "ronnie.dobbs@globochem.com"
}
HTTP/1.1 200 OK
Content-Type: application/json
Connection: Close
gurl \
  -X PUT \
  -key $API_KEY \
  -secret $API_SECRET \
  -d '{"email":"ronnie.dobbs@globochem.com"}'
  "https://api.leaf.ag/resources/v1/users/8EF57207-9D29-4C4F-8954-FCEFFED272A7"

Edit a users’s profile.

Request Body

Field Type Required Notes
role string no “manager” or “operator”
email string only if role is “manager” A valid RFC 5322 email address
prefix_name string no
first_name string yes
middle_name string no
last_name string yes
suffix_name string no
phone_number string no
employee_id string no
emergency_contact_name string no
emergency_contact_phone string no
emergency_contact_relationship string no
description string no
hire_date RFC 3339 timestamp no
tags []string no

Response Body

Equipment

All equipment endpoints must be prefixed with /resources/v1.

Eventually, when breaking changes are deployed we will create new versions and update this document accordingly.

All requests and responses must be JSON-encoded.

Add Equipment

Add a new equipment in the Leaf system.

The available categories of equipment are selfpropelled, implement, truck and misc.

POST /equipment HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
    "category": "selfpropelled",
    "name": "mySprayer",
    "type": "sprayer",
    "physical_width": 12.34,
    "physical_width_units": "feet",
    "pass_width": 12.45,
    "pass_width_units": "feet",
    "make": "make",
    "model": "model",
    "year": 2016,
    "purpose": "Harvesting",
    "machine_hours": 1000
}
HTTP/1.1 201 CREATED
Connection: Close

# Adding a selfpropelled equipment.

gurl \
  -X POST \
  -d '{
    "category": "selfpropelled",
    "name": "myTractor",
    "type": "tractor",
    "make": "make",
    "model": "model",
    "year": 2016,
    "beacon": {
          "serial": "4A05",
          "proximity_uuid":"A911267C-9A96-4B88-B66A-060821AD75E3",
          "major":1,
          "minor":1,
          "distance":0
     }
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/equipment"

# Adding an implement.

gurl \
  -X POST \
  -d '{
    "category": "implement",
    "name": "myImplement",
    "physical_width": 1.0,
    "physical_width_units": "feet",
    "pass_width": 1.0,
    "pass_width_units": "feet",
    "purpose": "Harvesting"
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/equipment"

# Adding a truck.

gurl \
  -X POST \
  -d '{
    "category": "truck",
    "name": "myTruck",
    "tags": ["tag1", "tag2"]
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/equipment"

# Adding a misc.

gurl \
  -X POST \
  -d '{
    "category": "misc",
    "name": "MyMisc",
    "type": "notselfpropelled",
    "fields": [
          {"name":"field1", "value":"value1"},
          {"name":"field2", "value":"123"}
    ]
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/equipment

HTTP Request

POST /equipment

Post parameters

Parameter Type Required Description
category string Yes The equipment’s category. The available categories are selfpropelled, implement, truck and misc.
name string Yes The equipment’s name.
type string No The equipment’s type.
make string No The equipment’s make.
model string No The equipment’s model.
year int No The equipment’s year.
physical_width float64 No The equipment’s physical width.
physical_width_units string No The equipment’s physical width units, the value is “feet”.
pass_width float64 No The equipment’s pass width.
pass_width_units string No The equipment’s pass width units, the value is “feet”.
beacon object No The equipment’s beacon. See shell example about how to use beacon.
vin_sn string No The equipment’s VIN/SN.
purpose string No The equipment’s purpose.
brand string No The equipment’s brand.
description string No The equipment’s description.
cost float64 No The equipment’s cost.
mileage int No The equipment’s mileage.
machine_hours int No The equipment’s machine hours.
tags []string No The equipment’s tags, optional for all categories of equipment.
fields []Field No The equipment’s optional fields, optional for all categories of equipment. See shell example about how to use Fields

HTTP Response

Response Body

JSON-encoded string containing the ID of the new equipment.

Example: "8EF57207-9D29-4C4F-8954-FCEFFED272A7"

Category field

No. Type
1 selfpropelled
2 implement
3 truck
4 misc

Type field

No. Type Description
1 sprayer available for selfpropelled category
2 swather available for selfpropelled category
3 combine available for selfpropelled category
4 chopper available for selfpropelled category
5 tractor available for selfpropelled category
6 selfpropelled available for misc category
7 notselfpropelled available for misc category

Purpose field

No. Value
1 harvesting
2 spreading
3 spraying
4 planting
5 tilling
6 transporting
7 cultivating
8 seeding

List Equipment

List existed equipment of the Leaf system by company ID.

GET /equipment HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "id":"b4b30b79-28db-4de9-835c-7849fa25f834",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myMisc2",
        "category":"misc",
        "type":"notselfpropelled",
        "vin_sn":"vin",
        "make":"make",
        "model":"model",
        "purpose":"Harvesting",
        "created_at":"2016-01-28T20:09:50.917443Z",
        "updated_at":"2016-01-28T20:09:50.917443Z"
    },
    {
        "id":"09e544d6-cd9b-4a65-9c24-a94d32daaa8e",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myMisc1",
        "category":"misc",
        "type":"selfpropelled",
        "make":"make",
        "model":"model",
        "purpose":"Harvesting",
        "created_at":"2016-01-28T20:09:43.824828Z",
        "updated_at":"2016-01-28T20:09:43.824828Z"
    },
    {
        "id":"c19a1da6-6d60-4b41-a69a-37dea7f6b76f",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myTruck",
        "category":"truck",
        "vin_sn":"vin",
        "make":"make",
        "model":"model",
        "year":2016,
        "mileage": 1000,
        "created_at":"2016-01-28T20:09:35.412842Z",
        "updated_at":"2016-01-28T20:09:35.412842Z"
    },
    {
        "id":"27874e3d-6135-4041-84e8-7a3e1ec492d6",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myImplement",
        "category":"implement",
        "vin_sn":"sn",
        "make":"make",
        "model":"model",
        "purpose":"Harvesting",
        "pass_width":12.45,
        "pass_width_units":"feet",
        "physical_width":12.34,
        "physical_width_units":"feet",
        "cost":100000,
        "year":2016,
        "description":"this is a selfpropelled equipment",
        "beacon":{
            "serial": "4A05",
            "proximity_uuid":"5554faa0-1234-4ffd-883a-2d9baadbf873",
            "major":11,
            "minor":11,
            "distance":0
        },
        "latest_location": {
            "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
            "long": 97.75,
            "lat": 30.25,
            "heading": 1.2,
            "speed": 33.5,
            "created_at": "2016-03-04T19:53:05.996918Z"
        },
        "tags":["tag1","tag2"],
        "created_at":"2016-01-28T20:09:20.132192Z",
        "updated_at":"2016-01-28T20:09:20.132192Z"
    },
    {
        "id":"b35b1d4f-79ae-4502-b2fc-83e9c65fe266",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myTractor",
        "category":"selfpropelled",
        "type":"tractor",
        "make":"make",
        "model":"model",
        "year":2016,
        "tags":["tag1","tag2"],
        "created_at":"2016-01-28T20:09:13.626533Z",
        "updated_at":"2016-01-28T20:09:13.626533Z"
    },
    {
        "id":"e510a1b4-034e-4359-a9a2-b754694193e7",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"mySprayer",
        "category":"selfpropelled",
        "type":"sprayer",
        "vin_sn":"vin sn",
        "brand":"my brand",
        "make":"make",
        "model":"model",
        "purpose":"Harvesting",
        "pass_width":12.45,
        "pass_width_units":"feet",
        "physical_width":12.34,
        "physical_width_units":"feet",
        "cost":100000,
        "year":2016,
        "description":"this is a selfpropelled equipment",
        "beacon":{
            "serial": "4A05",
            "proximity_uuid":"5554faa0-1234-4ffd-883a-2d9baadbf874",
            "major":13,
            "minor":13,
            "distance":0
        },
        "latest_location": {
            "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
            "long":65.75,
            "lat": 30.25,
            "heading": 1.2,
            "speed": 33.5,
            "created_at": "2016-03-04T19:53:05.996918Z"
        },
        "machine_hours":1000,
        "tags":["tag1","tag2"],
        "created_at":"2016-01-28T20:09:06.256025Z",
        "updated_at":"2016-01-28T20:09:06.256025Z"
    }
]

The request:

gurl \
  -X GET \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/equipment"

The response:

[
    {
        "id":"b4b30b79-28db-4de9-835c-7849fa25f834",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myMisc2",
        "category":"misc",
        "type":"notselfpropelled",
        "vin_sn":"vin",
        "make":"make",
        "model":"model",
        "purpose":"Harvesting",
        "created_at":"2016-01-28T20:09:50.917443Z",
        "updated_at":"2016-01-28T20:09:50.917443Z"
    },
    {
        "id":"09e544d6-cd9b-4a65-9c24-a94d32daaa8e",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myMisc1",
        "category":"misc",
        "type":"selfpropelled",
        "make":"make",
        "model":"model",
        "purpose":"Harvesting",
        "created_at":"2016-01-28T20:09:43.824828Z",
        "updated_at":"2016-01-28T20:09:43.824828Z"
    },
    {
        "id":"c19a1da6-6d60-4b41-a69a-37dea7f6b76f",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myTruck",
        "category":"truck",
        "vin_sn":"vin",
        "make":"make",
        "model":"model",
        "year":2016,
        "mileage":1000,
        "created_at":"2016-01-28T20:09:35.412842Z",
        "updated_at":"2016-01-28T20:09:35.412842Z"
    },
    {
        "id":"27874e3d-6135-4041-84e8-7a3e1ec492d6",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myImplement",
        "category":"implement",
        "vin_sn":"sn",
        "make":"make",
        "model":"model",
        "purpose":"Harvesting",
        "pass_width":12.45,
        "pass_width_units":"feet",
        "physical_width":12.34,
        "physical_width_units":"feet",
        "cost":100000,
        "year":2016,
        "description":"this is a selfpropelled equipment",
        "beacon":{
            "serial": "4A05",
            "proximity_uuid":"5554faa0-1234-4ffd-883a-2d9baadbf873",
            "major":11,
            "minor":11,
            "distance":0
        },
        "latest_location": {
            "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
            "long": 97.75,
            "lat": 30.25,
            "heading": 1.2,
            "speed": 33.5,
            "created_at": "2016-03-04T19:53:05.996918Z"
        },
        "tags":["tag1","tag2"],
        "created_at":"2016-01-28T20:09:20.132192Z",
        "updated_at":"2016-01-28T20:09:20.132192Z"
    },
    {
        "id":"b35b1d4f-79ae-4502-b2fc-83e9c65fe266",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"myTractor",
        "category":"selfpropelled",
        "type":"tractor",
        "make":"make",
        "model":"model",
        "year":2016,
        "tags":["tag1","tag2"],
        "created_at":"2016-01-28T20:09:13.626533Z",
        "updated_at":"2016-01-28T20:09:13.626533Z"
    },
    {
        "id":"e510a1b4-034e-4359-a9a2-b754694193e7",
        "user_id":"d2fb0f59-1d3c-40d2-9cb8-bcf2dcf41e3e",
        "company_id":1,
        "name":"mySprayer",
        "category":"selfpropelled",
        "type":"sprayer",
        "vin_sn":"vin sn",
        "brand":"my brand",
        "make":"make",
        "model":"model",
        "purpose":"Harvesting",
        "pass_width":12.45,
        "pass_width_units":"feet",
        "physical_width":12.34,
        "physical_width_units":"feet",
        "cost":100000,
        "year":2016,
        "description":"this is a selfpropelled equipment",
        "beacon":{
            "serial": "4BC6",
            "proximity_uuid":"5554faa0-1234-4ffd-883a-2d9baadbf873",
            "major":11,
            "minor":11,
            "distance":0
        },
        "latest_location": {
            "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
            "long":65.75,
            "lat": 30.25,
            "heading": 1.2,
            "speed": 33.5,
            "created_at": "2016-03-04T19:53:05.996918Z"
        },
        "machine_hours":1000,
        "tags":["tag1","tag2"],
        "created_at":"2016-01-28T20:09:06.256025Z",
        "updated_at":"2016-01-28T20:09:06.256025Z"
    }
]

HTTP Request

GET /equipment

HTTP Response

Get Equipment

Get the detailed equipment by equipment ID.

GET /equipment/d24725b1-d021-4622-ac7a-10134689a4c1 HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 200 OK
Content-Type: application/json

{
    "id": "d24725b1-d021-4622-ac7a-10134689a4c1",
    "category": "selfpropelled",
    "name": "mySprayer",
    "type": "sprayer",
    "width": 12.34,
    "units": 56.0,
    "brand": "brand",
    "make": "make",
    "model": "model",
    "purpose": "Harvesting",
    "machine_hours":1000,
    "beacon":{
        "serial": "4A05",
        "proximity_uuid":"5554faa0-1234-4ffd-883a-2d9baadbf873",
        "major":11,
        "minor":11,
        "distance":0
    },
    "latest_location": {
        "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
        "long":65.75,
        "lat": 30.25,
        "heading": 1.2,
        "speed": 33.5,
        "created_at": "2016-03-04T19:53:05.996918Z"
    }
}
gurl \
  -X GET \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/equipment/d24725b1-d021-4622-ac7a-10134689a4c1"
{
    "id": "d24725b1-d021-4622-ac7a-10134689a4c1",
    "category": "selfpropelled",
    "name": "mySprayer",
    "type": "sprayer",
    "width": 12.34,
    "units": 56.0,
    "brand": "brand",
    "make": "make",
    "model": "model",
    "purpose": "Harvesting",
    "machine_hours":1000,
    "beacon":{
        "serial": "4A05",
        "proximity_uuid":"5554faa0-1234-4ffd-883a-2d9baadbf873",
        "major":11,
        "minor":11,
        "distance":0
    },
    "latest_location": {
        "device_id":"e82fb2a0-6141-466d-b11e-1f794cbc7b16",
        "long":65.75,
        "lat": 30.25,
        "heading": 1.2,
        "speed": 33.5,
        "created_at": "2016-03-04T19:53:05.996918Z"
    }
}

HTTP Request

GET /equipment/:id

HTTP Response

Edit equipment

Edit equipment by equipment ID

PUT /equipment/d24725b1-d021-4622-ac7a-10134689a4c1 HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
    "name": "mySprayer_update",
    "width": 12.345,
    "units": 56.789,
    "brand": "brand_update",
    "make": "make_update",
    "model": "model_update"
}
HTTP/1.1 202 Accepted
Connection: Close
gurl \
  -X PUT \
  -d '{
    "name": "mySprayer_update",
    "width": 12.345,
    "units": 56.789,
    "brand": "brand_update",
    "make": "make_update",
    "model": "model_update"
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/equipment/d24725b1-d021-4622-ac7a-10134689a4c1"

HTTP Request

PUT /equipment/:id

HTTP Response

Delete equipment

Delete equipment by equipment ID

DELETE /equipment/d24725b1-d021-4622-ac7a-10134689a4c1 HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 204 NOCONTENT
Connection: Close

The request of deleting an equipment:

gurl \
  -X DELETE \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/equipment/d24725b1-d021-4622-ac7a-10134689a4c1"

HTTP Request

DELETE /equipment/:id

HTTP Response

List Catalog

Listing a catalog of all categories, types and purposes for equipment.

GET /equipment_catalog HTTP/1.1
HOST: api.leaf.ag
HTTP/1.1 200 OK
Content-Type: application/json

{
    "misc": [
                {
                "type": "selfpropelled",
                    "purposes": [
                            "Harvesting",
                            "Spreading",
                            "Spraying",
                                "Planting",
                                "Tilling",
                                "Transporting",
                                "Cultivating",
                                "Seeding"
                    ]
                },
                {
                "type": "notselfpropelled"
                }
    ]
}

The request:

gurl \
  -X GET \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/equipment_catalog

The response:

{
    ...
    "misc": [
              {
                "type": "selfpropelled",
                "purposes": [
                  "Harvesting",
                  "Spreading",
                  "Spraying",
                  "Planting",
                  "Tilling",
                  "Transporting",
                  "Cultivating",
                  "Seeding"
                ]
              }, {
                "type": "notselfpropelled"
              }
    ]
}

HTTP Request

GET /equipment_catalog

HTTP Response

ManagementZones

All managementzone endpoints must be prefixed with /resources/v1

Eventually, when breaking changes are deployed we will create new versions and update this document accordingly.

All requests and responses must be JSON-encoded.

Another point that clients need to remember is that all coordinates are specified as [lng, lat].

This is the way that the default coordinate system of GeoJSON and PostGIS work.

For the coordinations of polygon in all endpoints, we require it to be an array of coordinate arrays. For polygons with multiple rings, the first must be the exterior ring and any others must be interior rings or holes.

Here we have two examples about how to provide coordinates for polygon.

alt text

The boundary of polygon is [[[5,2],[4,8],[9,10],[13,5],[10,1]]]

alt text

The exterior ring is [[5,2],[4,8],[9,10],[13,5],[10,1]]

The interior ring is [[6,5],[7,7],[10,5],[8,3]]

The boundary of polygon is [ [[5,2],[4,8],[9,10],[13,5],[10,1]], [[6,5],[7,7],[10,5],[8,3]] ]

For the coordinations, we require them to be a pair of longitude and latitude. It is a standard GIS formating for POSTGIS. You can find more infomation about How POSTGIS handle GIS data here.

Add ManagementZone

The available categories of managementzone are farm, field, keylocation.

The request of POST a farm:

POST /managementzones HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
    "category": "farm",
    "name": "myFarm",
    "area": 1000.0,
    "area_units": "acres",
    "tags": ["tag1", "tag2"]
}

The request of POST a field:

POST /managementzones HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
        "category":"field",
        "name":"peach field",
        "area":100.0,
        "area_units":"acres",
        "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
        "boundary_type": "polygon",
        "soil_type": "clay",
        "irrigation_type": "pivot",
        "lease_length": 4,
        "lease_date": "2016-01-02T15:04:05-07:00",
        "owned_date": "2016-01-02T15:04:05-07:00",
        "farm_id": "fbc1a684-da0e-42c8-a888-027fe820a729",
        "tags": ["tag1", "tag2"]
}

The request of POST a keylocation:

POST /managementzones HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
        "category":"keylocation",
        "name":"keylocation",
        "location_type":"shops",
        "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
        "boundary_type":"polygon",
        "farm_ids":["fbc1a684-da0e-42c8-a888-027fe820a729"],
        "field_ids":["aff286ff-a079-4918-b185-e9800de11e51"]
}

The response of POST a management zone:

HTTP/1.1 201 CREATED
Connection: Close

The request of POST a farm:

gurl \
  -X POST \
  -d '{
    "category": "farm",
    "name": "myFarm",
    "area": 1000.0,
    "area_units": "acres"
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones

The request of POST a field:

gurl \
  -X POST \
  -d '{
        "category":"field",
        "name":"peach field",
        "area":100.0,
        "area_units":"acres",
        "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
        "boundary_type": "polygon",
        "soil_type": "clay",
        "irrigation_type": "pivot",
        "lease_length": 4,
        "lease_date": "2016-01-02T15:04:05-07:00",
        "owned_date": "2016-01-02T15:04:05-07:00",
        "farm_id": "fbc1a684-da0e-42c8-a888-027fe820a729",
        "tags": ["tag1", "tag2"]
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones

The request of POST a keylocation:

gurl \
  -X POST \
  -d '{
        "category":"keylocation",
        "name":"keylocation",
        "location_type":"shops",
        "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
        "boundary_type":"polygon",
        "farm_ids":["fbc1a684-da0e-42c8-a888-027fe820a729"],
        "field_ids":["aff286ff-a079-4918-b185-e9800de11e51"]
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones

HTTP Request

POST /managementzones

Post parameters

Parameter Type Required Description
category string Yes The managementzone’s category. The available categories are farm, field, keylocation.
name string Yes The managementzone’s name.
tags []string No The managementzone’s tags.
area string Depends The managementzone’s area. This field is required if catagory is field.
area_units string Depends The managementzone’s area_units. the value is “acres”. This field is required if category is field.
boundary_type string Depends The managementzone’s boundary type. The availble types of boundary are polygon, point, circle. This field is required if category is field or keylocation.
boundary [][][]float64 Depends The managementzone’s polygon coordinates. The units of coordinates is degree. This field is required if boundary_type is polygon and category is field or keylocation.
pivot []float64 Depends The managementzone’s circle pivot coordinates. The units of coordinates is degrees. This field is required if boundary_type is circle and category is field or keylocation.
radius float64 Depends The managementzone’s circle radius. This field is required if boundary_type is circle and category is field or keylocation.
radius_units string Depends The managementzone’s circle radius units. The value is “feet”. This field is required if boundary_type is circle and category is field or keylocation.
point []float64 Depends The managementzone’s point coordinates. The units of coordinates is degrees. This field is required if boundary_type is point and category is field or keylocation.
soil_type string No The managementzone’s soil type. The available types of soil are sandy, sandy loam, loam, clay loam, clay. This field is being used only when category is field.
irrigation_type string No The managementzone’s irrigation type. The available types of irrigation are pivot, flood, drip, none, furrow, wheelline, handline. This field is being used only when category is field.
lease_date date No The managementzone’s lease date. This field is being used only when category is field.
lease_length int No The managementzone’s lease length in years. The value is years. This field is being used only when category is field.
owned_date date No The managementzone’s bought or owned date. This field is being used only when category is field.
farm_id string No The uuid of farm, point to a related farm. This field is being used when category is field.
farm_ids []string No The uuid of farms, point to a group of related farms. This field is begin used when category is keylocation.
field_ids []string No The uuid of field, point to a group of related fields. This field is being used when category is keylocation.
location_type string Depends The managementzone’s location type. This field is required if category is keylocation. The avaible types of location are obstable/hazard, equipment yards, entry points, crop storage, scale, office, shops, pumps, canals, weirs, corrals, livestock, service providers, lagoons, silage pits, water storage.

HTTP Response

Response Body

JSON-encoded string containing the ID of the new management zone.

Example: "8EF57207-9D29-4C4F-8954-FCEFFED272A7"

List ManagementZone

List basic information of all existing management zones of the Leaf system by company ID.

Use “Get MangementZone” to get detailed infomation of a single management zone.

GET /managementzones HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "id": "fbc1a684-da0e-42c8-a888-027fe820a729",
            "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
            "company_id": 1,
            "category": "farm",
            "name": "peach farm",
            "area": 100,
            "area_units": "acres",
            "field_ids": [
                    "b3793211-c2b6-413a-93b9-1563ab1c2cae",
                    "ebeb6896-6b45-452b-b4b3-fefcc67477b9"
            ]
    }
    {
                "id": "ebeb6896-6b45-452b-b4b3-fefcc67477b9",
                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                "company_id": 1,
                "category": "field",
                "name": "peach field",
                "area": 100,
                "area_units": "acres",
                "soil_type": "clay",
                "irrigation_type": "pivot",
                "lease_length": 4,
                "owned_date": "2016-01-02T15:04:05Z",
                "boundary_type": "polygon",
                "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
                "farm_id": "fbc1a684-da0e-42c8-a888-027fe820a729"
        },
    {
                "id": "b3793211-c2b6-413a-93b9-1563ab1c2cae",
                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                "company_id": 1,
                "category": "field",
                "name": "peach field",
                "area": 100,
                "area_units": "acres",
                "soil_type": "clay",
                "irrigation_type": "pivot",
                "lease_length": 4,
                "owned_date": "2016-01-02T15:04:05Z",
                "boundary_type": "polygon",
                "boundary": [[[-121.569857,32.884522],[-121.569946,32.883295],[-121.571533,32.883259],[-121.571508,32.884604]]],
                "farm_id": "fbc1a684-da0e-42c8-a888-027fe820a729"
        },
    {
                "id": "50533bf3-ba38-41b5-b914-f40bc320cf4e",
                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                "company_id": 1,
                "category": "keylocation",
                "name": "keylocation",
                "boundary_type": "polygon",
                "boundary": [[[-131.569857,32.884522],[-131.569946,32.883295],[-131.571533,32.883259],[-131.571508,32.884604]]],
                "field_ids": [
                         "aff286ff-a079-4918-b185-e9800de11e51"
                ],
                "farm_ids": [
                         "fbc1a684-da0e-42c8-a888-027fe820a729"
                ]
    }
]

The request:

gurl \
  -X GET \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones

The response:

[
    {
        "id": "fbc1a684-da0e-42c8-a888-027fe820a729",
            "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
            "company_id": 1,
            "category": "farm",
            "name": "peach farm",
            "area": 100,
            "area_units": "acres",
            "field_ids": [
                    "b3793211-c2b6-413a-93b9-1563ab1c2cae",
                    "ebeb6896-6b45-452b-b4b3-fefcc67477b9"
            ]
    }
    {
                "id": "ebeb6896-6b45-452b-b4b3-fefcc67477b9",
                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                "company_id": 1,
                "category": "field",
                "name": "peach field",
                "area": 100,
                "area_units": "acres",
                "soil_type": "clay",
                "irrigation_type": "pivot",
                "lease_length": 4,
                "owned_date": "2016-01-02T15:04:05Z",
                "boundary_type": "polygon",
                "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
                "farm_id": "fbc1a684-da0e-42c8-a888-027fe820a729"
        },
    {
                "id": "b3793211-c2b6-413a-93b9-1563ab1c2cae",
                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                "company_id": 1,
                "category": "field",
                "name": "peach field",
                "area": 100,
                "area_units": "acres",
                "soil_type": "clay",
                "irrigation_type": "pivot",
                "lease_length": 4,
                "owned_date": "2016-01-02T15:04:05Z",
                "boundary_type": "polygon",
                "boundary": [[[-121.569857,32.884522],[-121.569946,32.883295],[-121.571533,32.883259],[-121.571508,32.884604]]],
                "farm_id": "fbc1a684-da0e-42c8-a888-027fe820a729"
        },
    {
                "id": "50533bf3-ba38-41b5-b914-f40bc320cf4e",
                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                "company_id": 1,
                "category": "keylocation",
                "name": "keylocation",
                "boundary_type": "polygon",
                "boundary": [[[-131.569857,32.884522],[-131.569946,32.883295],[-131.571533,32.883259],[-131.571508,32.884604]]],
                "field_ids": [
                         "aff286ff-a079-4918-b185-e9800de11e51"
                ],
                "farm_ids": [
                         "fbc1a684-da0e-42c8-a888-027fe820a729"
                ]
    }
]

HTTP Request

GET /managementzones

HTTP Response

Response payload

Parameter Type Description
id string The current managementzone’s ID.
user_id string The user’s ID.
company_id integer The company’s ID.
category string The current managementzone’s category. The avaiable categories are farm, field, keylocation.
name string The current managementzone’s name.
area float64 The current managementzone’s area.
area_units string The current managementzone’s area units. The value is “acres”.
boundary_type string The current managementzone’s boundary type. The availble types of boundary are polygon, point, circle. This field is being used when category is field or keylocation.
boundary [][][]float64 The current managementzone’s polygon coordinates. The units of coordinatesis degree. This field is being used when category is field or keylocation and boundary_type is polygon.
pivot []float64 The current managementzone’s pivot coordinates. The units of coordinatesis degree. This field is being used when category is field or keylocation and boundary_type is circle.
radius float64 The current managementzone’s radius. This field is being used when category is field or keylocation and boundary_type is circle.
radius_units string The current managementzone’s radius units. The value is “acres”. This field is being used when category is field or keylocation and boundary_type is circle.
point []float64 The current managementzone’s point coordinates. The units of coordinatesis degree. This field is being used when category is field or keylocation and boundary_type is point.
soil_type string The current managementzone’s soil type. The available types of soil are sandy, sandy loam, loam, clay loam, clay. This field is being used when category is field.
irrigation_type string The current managementzone’s irrigation type. The available types of irrigation are pivot, flood, drip, none, furrow, wheelline, handline. This field is being used when category is field.
lease_date date The current managementzone’s lease date. The managementzone’s lease date. This field is being used when category is field.
lease_length int The current managementzone’s lease length. The valus is years. The managementzone’s lease length in years. This field is being used when category is field.
owned_date date The current managementzone’s owned date. The managementzone’s bought or owned date. This field is being used when category is field.
farm_id string The uuid of farm, point to a related farm. This field is being used when category is field.
farm_ids []string The uuid of farms, point to a group of related farms. This field is begin used when category is keylocation.
field_ids []string The uuid of field, point to a group of related fields. This field is being used when category is keylocation.
location_type string The current managementzone’s location type. This field is required if category is keylocation. The avaible types of location are obstable/hazard, equipment yards, entry points, crop storage, scale, office, shops, pumps, canals, weirs, corrals, livestock, service providers, lagoons, silage pits, water storage.

Get ManagementZone

Get the detailed management zone by management zone ID.

GET /managementzones/d24725b1-d021-4622-ac7a-10134689a4c1 HTTP/1.1
Host: api.leaf.ag

The response of GET a farm.

HTTP/1.1 200 OK
Content-Type: application/json

{
    "id":"74a1795d-b09f-455d-b287-85dd879418ce",
    "user_id":"c2c883b1-6ee5-4d21-a476-42006e85d9f1",
    "company_id":14,
    "category":"farm",
    "name":"peach farm",
    "area":100,
    "area_units":"acres",
    "fields":[
        {
            "mangementzone_id":"eb44ecb2-4e06-4f9a-aaab-5105675b4bed",
            "user_id":"c2c883b1-6ee5-4d21-a476-42006e85d9f1",
            "company_id":14,
            "category":"field",
            "name":"peach field",
            "area":100,
            "area_units":"acres",
            "soil_type":"clay",
            "irrigation_type":"pivot",
            "lease_length":4,
            "lease_date":"2016-01-02T15:04:05Z",
            "owned_date":"2016-01-02T15:04:05Z",
            "boundary_type":"polygon",
            "boundary":[[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
            "farm_id":"74a1795d-b09f-455d-b287-85dd879418ce"
        }
    ],
    "tags":["tag1","tag2"],
    "created_at":"2016-01-25T15:56:17.608299Z",
    "updated_at":"2016-01-25T15:56:17.608299Z"
}

The response of GET a field.

HTTP/1.1 200 OK
Content-Type: application/json

{
       "id": "eb44ecb2-4e06-4f9a-aaab-5105675b4bed",
       "user_id": "c2c883b1-6ee5-4d21-a476-42006e85d9f1",
       "company_id": 14,
       "category": "field",
       "name": "peach field",
       "area": 100,
       "area_units": "acres",
       "soil_type": "clay",
       "irrigation_type": "pivot",
       "lease_length": 4,
       "lease_date": "2016-01-02T15:04:05Z",
       "owned_date": "2016-01-02T15:04:05Z",
       "boundary_type": "polygon",
       "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
       "farm_id": "74a1795d-b09f-455d-b287-85dd879418ce",
       "tags": ["tag1","tag2"]
}

The response of GET a keylocation.

HTTP/1.1 200 OK
Content-Type: application/json

{
    "id": "50533bf3-ba38-41b5-b914-f40bc320cf4e",
        "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
        "company_id": 1,
        "category": "keylocation",
        "name": "keylocation",
        "lease_date": "0001-01-01T00:00:00Z",
        "owned_date": "0001-01-01T00:00:00Z",
        "location_type": "shops",
        "boundary_type": "polygon",
        "boundary": [[[-121.569857,32.884522],[-121.569946,32.883295],[-121.571533,32.883259],[-121.571508,32.884604]]],
        "fields": [
            {
                "id": "aff286ff-a079-4918-b185-e9800de11e51",
                                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                                "company_id": 1,
                                "category": "field",
                                "name": "peach field",
                                "area": 100,
                                "area_units": "acres",
                                "soil_type": "clay",
                                "irrigation_type": "pivot",
                                "lease_length": 4,
                                "lease_date": "2016-01-02T15:04:05Z",
                                "owned_date": "2016-01-02T15:04:05Z",
                                "boundary_type": "polygon",
                                "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
                                "farm_id": "2545123c-fbe5-4e2e-9d25-1d2bd55dc25d"
                }
        ],
        "farms": [
            {
                "id": "fbc1a684-da0e-42c8-a888-027fe820a729",
                                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                                "company_id": 1,
                                "category": "farm",
                                "name": "peach farm",
                                "area": 100,
                                "area_units": "acres"
                }
        ]
}

The request:

gurl \
  -X GET \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones/d24725b1-d021-4622-ac7a-10134689a4c1

The response of GET a farm:

{
    "id":"74a1795d-b09f-455d-b287-85dd879418ce",
    "user_id":"c2c883b1-6ee5-4d21-a476-42006e85d9f1",
    "company_id":14,
    "category":"farm",
    "name":"peach farm",
    "area":100,
    "area_units":"acres",
    "fields":[
        {
            "id":"eb44ecb2-4e06-4f9a-aaab-5105675b4bed",
            "user_id":"c2c883b1-6ee5-4d21-a476-42006e85d9f1",
            "company_id":14,
            "category":"field",
            "name":"peach field",
            "area":100,
            "area_units":"acres",
            "soil_type":"clay",
            "irrigation_type":"pivot",
            "lease_length":4,
            "lease_date":"2016-01-02T15:04:05Z",
            "owned_date":"2016-01-02T15:04:05Z",
            "boundary_type":"polygon",
            "boundary":[[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
            "farm_id":"74a1795d-b09f-455d-b287-85dd879418ce"
        }
    ],
    "tags":["tag1","tag2"],
    "created_at":"2016-01-25T15:56:17.608299Z",
    "updated_at":"2016-01-25T15:56:17.608299Z"
}

The response of GET a field:

{
       "id": "eb44ecb2-4e06-4f9a-aaab-5105675b4bed",
       "user_id": "c2c883b1-6ee5-4d21-a476-42006e85d9f1",
       "company_id": 14,
       "category": "field",
       "name": "peach field",
       "area": 100,
       "area_units": "acres",
       "soil_type": "clay",
       "irrigation_type": "pivot",
       "lease_length": 4,
       "lease_date": "2016-01-02T15:04:05Z",
       "owned_date": "2016-01-02T15:04:05Z",
       "boundary_type": "polygon",
       "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
       "farm_id": "74a1795d-b09f-455d-b287-85dd879418ce",
       "tags": ["tag1","tag2"]
}

The response of GET a keylocation:

{
    "id": "50533bf3-ba38-41b5-b914-f40bc320cf4e",
        "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
        "company_id": 1,
        "category": "keylocation",
        "name": "keylocation",
        "lease_date": "0001-01-01T00:00:00Z",
        "owned_date": "0001-01-01T00:00:00Z",
        "location_type": "shops",
        "boundary_type": "polygon",
        "boundary": [[[-121.569857,32.884522],[-121.569946,32.883295],[-121.571533,32.883259],[-121.571508,32.884604]]],
        "fields": [
            {
                "id": "aff286ff-a079-4918-b185-e9800de11e51",
                                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                                "company_id": 1,
                                "category": "field",
                                "name": "peach field",
                                "area": 100,
                                "area_units": "acres",
                                "soil_type": "clay",
                                "irrigation_type": "pivot",
                                "lease_length": 4,
                                "lease_date": "2016-01-02T15:04:05Z",
                                "owned_date": "2016-01-02T15:04:05Z",
                                "boundary_type": "polygon",
                                "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
                                "farm_id": "2545123c-fbe5-4e2e-9d25-1d2bd55dc25d"
                }
        ],
        "farms": [
            {
                "id": "fbc1a684-da0e-42c8-a888-027fe820a729",
                                "user_id": "7de7190f-571e-453a-90f7-966b3b4b1614",
                                "company_id": 1,
                                "category": "farm",
                                "name": "peach farm",
                                "area": 100,
                                "area_units": "acres"
                }
        ]
}

HTTP Request

GET /managementzones/:id

HTTP Response

Response Payload

Parameter Type Description
id string The current managementzone’s ID.
user_id string The user’s ID.
company_id string The company’s ID.
category string The current managementzone’s category. The available categories are farm, field, keylocation.
name string The current managementzone’s name.
tags []string The current managementzone’s tags.
area string The current managementzone’s area. This field is being used when catagory is farm or field.
area_units string The current managementzone’s area units. The value is “feet”. his field is being used when category is farm or field.
boundary_type string The current managementzone’s boundary type. This field is being used when category is field or keylocation.
boundary [][][]float64 The current managementzone’s polygon coordinates. The units of coordinatesis degree. This field is being used when category is field or keylocation and boundary_type is polygon.
pivot []float64 The current managementzone’s circle pivot coordinates. The units of coordinatesis degree. This field is being used when category is field or keylocation and boundary_type is circle.
radius float64 The current managementzone’s cicle radius. This field is being used when category is field or keylocation and boundary_type is circle.
radius_units string The current managementzone’s circle radius units. This field is being used when category is field or keylocation and boundary_type is circle.
point []float64 The current managementzone’s point coordinates. The units of coordinatesis degree. This field is being used when category is field or keylocation and boundary_type is point.
soil_type string The current managementzone’s soil type. The available types of soil are sandy, sandy loam, loam, clay loam, clay. This field is being used when category is field.
irrigation_type string The current managementzone’s irrigation type. The available types of irrigation are pivot, flood, drip, none, furrow, wheelline, handline. This field is being used when category is field.
lease_date date The current managementzone’s lease date. This field is being used when category is field.
lease_length int The current managementzone’s lease length in years. The value is years. This field is being used when category is field.
owned_date date The current managementzone’s bought or owned date. This field is being used when category is field.
farm_id string The uuid of farm, point to a related farm. This field is being used when category is field.
farm_ids []string The uuid of farms, point to a group of related farms. This field is being used when category is keylocation.
field_ids []string The uuid of fields, point to a group of related fields. This field is being used when category is keylocation.
location_type string The current managementzone’s location type. The avaible types of location are obstable/hazard, equipment yards, entry points, crop storage, scale, office, shops, pumps, canals, weirs, corrals, livestock, service providers, lagoons, silage pits, water storage. This field is being used if category is keylocation.

Edit ManagementZone

Edit management zone by management zone ID

The request of PUT a farm:

PUT /managementzones/d24725b1-d021-4622-ac7a-10134689a4c1 HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
        "category":"farm",
        "name":"peach farm",
        "area":100.0,
        "area_units":"acres",
        "tags": ["tag1", "tag2"]
}

The request of PUT a field:

PUT /managementzones/d24725b1-d021-4622-ac7a-10134689a4c1 HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
        "category":"field",
        "name":"peach field",
        "area":100.0,
        "area_units":"acres",
        "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
        "boundary_type": "polygon",
        "soil_type": "clay",
        "irrigation_type": "pivot",
        "lease_length": 4,
        "lease_date": "2016-01-02T15:04:05-07:00",
        "owned_date": "2016-01-02T15:04:05-07:00",
        "farm_id": "fbc1a684-da0e-42c8-a888-027fe820a729",
        "tags": ["tag1", "tag2"]
}

The request of PUT a keylocation:

PUT /managementzones/d24725b1-d021-4622-ac7a-10134689a4c1 HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
        "category":"keylocation",
        "name":"keylocation",
        "location_type":"shops",
        "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
        "boundary_type":"polygon",
        "farm_ids":["fbc1a684-da0e-42c8-a888-027fe820a729"],
        "field_ids":["aff286ff-a079-4918-b185-e9800de11e51"]
}

The response of PUT a management zone:

HTTP/1.1 202 Accepted
Connection: Close

The request of PUT a farm:

gurl \
  -X PUT \
  -d '{
    "category":"farm",
        "name":"peach farm",
        "area":100.0,
        "area_units":"acres",
        "tags": ["tag1", "tag2"]
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones/d24725b1-d021-4622-ac7a-10134689a4c1

The request of PUT a field:

gurl \
  -X PUT \
  -d '{
        "category":"field",
        "name":"peach field",
        "area":100.0,
        "area_units":"acres",
        "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
        "boundary_type": "polygon",
        "soil_type": "clay",
        "irrigation_type": "pivot",
        "lease_length": 4,
        "lease_date": "2016-01-02T15:04:05-07:00",
        "owned_date": "2016-01-02T15:04:05-07:00",
        "farm_id": "fbc1a684-da0e-42c8-a888-027fe820a729",
        "tags": ["tag1", "tag2"]
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones/d24725b1-d021-4622-ac7a-10134689a4c1

The request of PUT a keylocation:

gurl \
  -X PUT \
  -d '{
        "category":"keylocation",
        "name":"keylocation",
        "location_type":"shops",
        "boundary": [[[-111.569857,32.884522],[-111.569946,32.883295],[-111.571533,32.883259],[-111.571508,32.884604]]],
        "boundary_type":"polygon",
        "farm_ids":["fbc1a684-da0e-42c8-a888-027fe820a729"],
        "field_ids":["aff286ff-a079-4918-b185-e9800de11e51"]
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones/d24725b1-d021-4622-ac7a-10134689a4c1

HTTP Request

PUT /managementzones/:id

PUT parameters

Parameter Type Description
name string The managementzone’s name.
tags []string The managementzone’s tags.
area string The managementzone’s area. This field is required if catagory is field.
area_units string The managementzone’s area_units. The value is “acres”. This field is required if category is field. The available units are acres and hectares.
boundary_type string The managementzone’s boundary type. The availble types of boundary are polygon, point, circle. This field is required if category is field or keylocation.
boundary [][][]float64 The managementzone’s polygon coordinates. The units of coordinatesis degree. This field is required if boundary_type is polygon and category is field or keylocation.
pivot []float64 The managementzone’s circle pivot cordinates. The units of coordinatesis degree. This field is required if boundary_type is circle and category is field or keylocation.
radius float64 The managementzone’s circle radius. This field is required if boundary_type is circle and category is field or keylocation.
radius_units string The managementzone’s circle radius units. The availble types of radius units are meters and feet. This field is required if boundary_type is circle and category is field or keylocation.
point []float64 The managementzone’s point coordinates. The units of coordinatesis degree. This field is required if boundary_type is point and category is field or keylocation.
soil_type string The managementzone’s soil type. The available types of soil are sandy, sandy loam, loam, clay loam, clay. This field is being used only when category is field.
irrigation_type string The managementzone’s irrigation type. The available types of irrigation are pivot, flood, drip, none, furrow, wheelline, handline. This field is being used only when category is field.
lease_date date The managementzone’s lease date. This field is being used only when category is field.
lease_length int The managementzone’s lease length in years. The value is years. This field is being used only when category is field.
owned_date date The managementzone’s bought or owned date. This field is being used only when category is field.
farm_id string The uuid of farm, point to a related farm. This field is being used when category is field.
farm_ids []string The uuid of farms, point to a group of related farms. This field is begin used when category is keylocation.
field_ids []string The uuid of field, point to a group of related fields. This field is being used when category is keylocation.
location_type string The managementzone’s location type. This field is required if category is keylocation. The avaible types of location are obstable/hazard, equipment yards, entry points, crop storage, scale, office, shops, pumps, canals, weirs, corrals, livestock, service providers, lagoons, silage pits, water storage.

HTTP Response

Delete ManagementZone

Delete management zone by management zone ID

DELETE /managementzones/d24725b1-d021-4622-ac7a-10134689a4c1 HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 204 NoContent
Connection: Close
gurl \
  -X DELETE \
  -key $API_KEY \
  -secret $API_SECRET \
  https://api.leaf.ag/resources/v1/managementzones/d24725b1-d021-4622-ac7a-10134689a4c1

HTTP Request

DELETE /managementzones/:id

HTTP Response

Health

Checks the health of this service.

GET /health HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 200 OK
Connection: Close

The request:

gurl \
  -X GET \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/health"

HTTP Request

GET /health

HTTP Response:

Crops

All crops endpoints must be prefixed with /resources/v1.

All requests and responses are JSON-encoded.

Create Crop

gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '{
        "name":            "test crop 2",
        "crop":            "test_crop_2",
        "heat_unit":       "celsius",
        "projected_yield": "mucho",
        "bag_info": {
            "cost":         1.1,
            "seed_density": 2.2,
            "weight":       3.3
        },
        "commodities_index":  "NTW",
        "market_price":       32.2,
        "water_requirements": "a lot",
        "chemicals_used":     "nitrate,water",
        "seed_info": {
            "depth":      21.1,
            "spacing":    42.2,
            "population": 84.4
        },
        "ideal_soil": "ground",
        "vendor":     "john",
        "type":       "feed"
    }' \
  "https://api.leaf.ag/resources/v1/crops"
POST /crops HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

{
        "name":            "test crop 2",
        "crop":            "test_crop_2",
        "heat_unit":       "celsius",
        "projected_yield": "mucho",
        "bag_info": {
            "cost":         1.1,
            "seed_density": 2.2,
            "weight":       3.3
        },
        "commodities_index":  "NTW",
        "market_price":       32.2,
        "water_requirements": "a lot",
        "chemicals_used":     "nitrate,water",
        "seed_info": {
            "depth":      21.1,
            "spacing":    42.2,
            "population": 84.4
        },
        "ideal_soil": "ground",
        "vendor":     "john",
        "type":       "feed"
}
HTTP/1.1 201 CREATED
Connection: Close

Create Crops resource.

Create crops resource in the system.

HTTP Request

POST /crops

Parameters

Crops

Parameter Type Required Notes
name string yes
crop string yes
heat_unit string no
projected_yield string no
bag_info baginfo object no see baginfo object for details
commodities_index string no
market_price float no
water_requirements string no
chemicals_used string no
seed_info seedinfo object no see seedinfo object for details
ideal_soil string no
type string yes

BagInfo

Parameter Type Required Notes
cost float no
seed_density float no
weight float no

SeedInfo

Parameter Type Required Notes
depth float no
spacing float no
population float no

HTTP Response

Notes

All notes endpoints must be prefixed with /resources/v1.

All requests and responses are JSON-encoded.

Create Notes

gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '{
        "target_resource_id":   "75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "target_resource_type": "users",
        "content":              "hello!"
   }' "https://api.leaf.ag/resources/v1/notes"
POST /notes HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

{
        "target_resource_id":   "75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "target_resource_type": "users",
        "content":              "hello!"
}
HTTP/1.1 201 CREATED
Content-Type: application/json
Connection: Close

"2248bf63-b101-4fc8-b372-5042733f714a"

Create Notes resource.

Create Notes resource in the system.

HTTP Request

POST /notes

Parameters

Parameter Type Required Description
id string no Identifier of the note.
content string yes Content of the note.
target_resource_type string yes Type of resource linked to the note.
target_resource_id string yes Resource Identifier linked to the note.
origin_resource_type string no Always “users” for in the notes context.
origin_resource_id string no user_id for the notes context.

HTTP Response

Get Notes

gurl -X GET -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/resources/v1/notes/2248bf63-b101-4fc8-b372-5042733f714a"
GET /notes/2248bf63-b101-4fc8-b372-5042733f714a HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
HTTP/1.1 200 OK
Content-Type: application/json
Connection: Close

{
        "id":                   "2248bf63-b101-4fc8-b372-5042733f714a",
        "target_resource_id":   "75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "target_resource_type": "users",
        "origin_resource_id":   "3de5ba2c-df30-48f0-833b-5ee54bc25c88",
        "origin_resource_type": "users",
        "content":              "hello!"
}

Fetch Notes resource.

Get a Note resource from the system.

HTTP Request

GET /notes/:id

Parameters

Parameter Type Required Description
id string yes Identifier of the note.
content string yes Content of the note.
target_resource_type string yes Type of resource linked to the note.
target_resource_id string yes Resource Identifier linked to the note.
origin_resource_type string yes Always “users” for in the notes context.
origin_resource_id string yes user_id for the notes context.
created_at RFC3339 timestamp yes The time the note was created.
updated_at RFC3339 timestamp no The time the note was last updated.

HTTP Response

Update Notes

gurl -X PUT -key $API_KEY -secret $API_SECRET \
  -d '{
        "target_resource_id":   "75ee5bf5-1f72-46be-938a-b86100000000",
        "target_resource_type": "users",
        "content":              "hello world!"
   }' "https://api.leaf.ag/resources/v1/note/2248bf63-b101-4fc8-b372-5042733f714a"
PUT /notes/2248bf63-b101-4fc8-b372-5042733f714a HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

{
        "target_resource_id":   "75ee5bf5-1f72-46be-938a-b86100000000",
        "target_resource_type": "users",
        "content":              "hello world!"
}
HTTP/1.1 202 ACCEPTED
Connection: Close

Update Notes resource.

Update Notes resource in the system.

HTTP Request

PUT /notes/:id

Parameters

Parameter Type Required Description
content string no Content of the note.
target_resource_type string no Type of resource linked to the note.
target_resource_id string no Resource Identifier linked to the note.
origin_resource_type string N/A It is not possible at the moment to update the origin type.
origin_resource_id string N/A It is not possible at the moment to update the origin id.

HTTP Response

Delete Notes

gurl -X DELETE -key $API_KEY -secret $API_SECRET  "https://api.leaf.ag/resources/v1/notes/75ee5bf5-1f72-46be-938a-b86100000000"
POST /notes/75ee5bf5-1f72-46be-938a-b86100000000 HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json
HTTP/1.1 204 NO CONTENT
Connection: Close

Delete Notes resource.

Delete Notes resource in the system.

HTTP Request

DELETE /notes/:id

HTTP Response

List Notes

# List all notes
gurl -X GET -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/resources/v1/notes"

# List a targeted note (similar to get by id)
gurl -X GET -key $API_KEY -secret $API_SECRET \
  -d '{
        "target_resource_id":   "2248bf63-b101-4fc8-b372-5042733f714a",
        "target_resource_type": "users"
   }' "https://api.leaf.ag/resources/v1/notes"

# List all notes for all equipments.
gurl -X GET -key $API_KEY -secret $API_SECRET \
  -d '{
        "target_resource_type": "equipments"
   }' "https://api.leaf.ag/resources/v1/notes"
GET /notes HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

{
        "target_resource_id":   "75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "target_resource_type": "users"
}
HTTP/1.1 200 OK
Content-Type: application/json
Connection: Close

[{
        "id":                   "2248bf63-b101-4fc8-b372-5042733f714a",
        "target_resource_id":   "75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "target_resource_type": "users",
        "origin_resource_id":   "3de5ba2c-df30-48f0-833b-5ee54bc25c88",
        "origin_resource_type": "users",
        "content":              "hello!"
}]

List Notes resource.

List Notes resource in the system.

NOTE: As we don’t have a filtering system yet, we use the payload on a HTTP GET to filter.

HTTP Request

GET /notes

Parameters

Parameter Type Required Description
id string no Filter on the note identifier (similar to get by id).
target_resource_type string no Filter on the type of resource linked to the note.
target_resource_id string no Filter on the resource Identifier linked to the note.
origin_resource_type string no Filter on the origin resource type. (Always “users” for in the notes context.)
origin_resource_id string no Filter on the origin resource Identifier. (user_id for the notes context.)
created_at RFC3339 timestamp yes The time the note was created.
updated_at RFC3339 timestamp no The time the note was last updated.

HTTP Response

Activity

All activity endpoints must be prefixed with /activities.

All requests and responses are JSON-encoded.

All activities must have a corresponding (real) operation, accessible with the operation’s ID.

Create Activity

gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '{
        "device_id":"75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "type":"farming",
        "start":"2016-06-09T18:44:53Z",
        "end":"2016-06-09T21:37:01Z",
        "managementzone_id":"c6f8374a-4e91-487a-8c3d-696591bf4ffc",
        "operator_id":"76093839-2da0-48ec-96c4-c34ab0867d10",
        "selfpropelled_id":"6c2c879d-efc2-4de6-98b8-986b60b55659",
        "implement_id":"9c5c897d-efc2-4de6-98b8-986b60b55659",
        "purpose":"harvesting",
        "traveled_distance":1.2,
        "operation_id":"8ba0df9d-5598-4b9c-a63c-9f80ef40a776"
      }' https://api.leaf.ag/resources/v1/activities
POST /activities HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

{
        "device_id":"75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "type":"farming",
        "start":"2016-06-09T18:44:53Z",
        "end":"2016-06-09T21:37:01Z",
        "managementzone_id":"c6f8374a-4e91-487a-8c3d-696591bf4ffc",
        "operator_id":"76093839-2da0-48ec-96c4-c34ab0867d10",
        "selfpropelled_id":"6c2c879d-efc2-4de6-98b8-986b60b55659",
        "implement_id":"9c5c897d-efc2-4de6-98b8-986b60b55659",
        "purpose":"harvesting",
        "traveled_distance":1.2,
        "operation_id":"8ba0df9d-5598-4b9c-a63c-9f80ef40a776"
}
HTTP/1.1 201 CREATED
Content-Type: application/json
Connection: Close

"2248bf63-b101-4fc8-b372-5042733f714a"

Create activity resource.

Create activity in the system.

HTTP Request

POST /activities

Parameters

Parameter Type Required Description
device_id uuid no Identifier of the device that sent the heartbeats which triggered the activity.
type string no Type of activity (stationary, farming, travel).
start string yes The start time of the activity (formatted as RFC3339).
end string yes The end time of the activity (formatted as RFC3339).
managementzone_id uuid yes The management zones associated with the activity.
operator_id uuid yes The user ID of the operator that performed the activity.
selfpropelled_id uuid yes The selfpropelled that was involved with the activity.
implement_id uuid yes The equipment that was involved with the activity.
purpose string yes The purpose of the activity (harvesting, planting, etc).
traveled_distance float no The distance traveled in miles during the activity.
operation_id string yes The associated operation id.
algorithm_name string yes we have two algorithm_name avaiable until now (fenster and LeafObserver).
algorithm_version string yes we have one algorithm_version avaiable until now (v0).

HTTP Response

Get Activity

gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/activities/2248bf63-b101-4fc8-b372-5042733f714a
GET /activities/2248bf63-b101-4fc8-b372-5042733f714a HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
HTTP/1.1 200 OK
Content-Type: application/json
Connection: Close

{
        "device_id":"75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "type":"farming",
        "start":"2016-06-09T18:44:53Z",
        "end":"2016-06-09T21:37:01Z",
        "managementzone_id":"c6f8374a-4e91-487a-8c3d-696591bf4ffc",
        "operator_id":"76093839-2da0-48ec-96c4-c34ab0867d10",
        "selfpropelled_id":"6c2c879d-efc2-4de6-98b8-986b60b55659",
        "implement_id":"9c5c897d-efc2-4de6-98b8-986b60b55659"
        "purpose":"harvesting",
        "traveled_distance":1.2,
        "created_at":"2016-06-09T21:45:20Z"
}

Fetch activity resource.

Get an activity from the system.

HTTP Request

GET /activities/:id

Parameters

Parameter Type Required Description
device_id uuid no Identifier of the device that sent the heartbeats which triggered the activity.
type string no Type of activity (stationary, farming, travel).
start string yes The start time of the activity (formatted as RFC3339).
end string yes The end time of the activity (formatted as RFC3339).
managementzone_id uuid yes The management zones associated with the activity.
operator_id uuid yes The user ID of the operator that performed the activity.
selfpropelled_id uuid yes The selfpropelled that was involved with the activity.
implement_id uuid yes The equipment that was involved with the activity.
purpose string yes The purpose of the activity (harvesting, planting, etc).
traveled_distance float no The distance traveled in miles during the activity.
operation_id string yes The associated operation id.
algorithm_name string yes we have two algorithm_name avaiable until now (fenster and LeafObserver).
algorithm_version string yes we have one algorithm_version avaiable until now (v0).

HTTP Response

List Activity

# List all activities
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/activities

# List activities that ended during a two-day period
gurl -X GET -key $API_KEY -secret $API_SECRET -d '{"start":"2016-06-28T16:45:50Z","end":"2016-06-30T16:45:50Z"}' https://api.leaf.ag/resources/v1/activities
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/activities?start_time=2016-06-28T16:45:50Z&end_time=2016-06-30T16:45:50Z
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/activities?start_time=2016-06-28T16:45:50Z&end_time=2016-06-30T16:45:50Z&algorithm_name=historian&algorithm_version=1.7
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/activities?operation_id=8ba0df9d-5598-4b9c-a63c-9f80ef40a776
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/activities?selfpropelled_id=b3176e8c-3bc6-4f4c-8f82-d74bf4d4b7b1
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/activities?implement_id=ced67b14-94bd-48ea-b0c8-a866f3e5e146
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/activities?managementzone_id=80db6847-b70d-4680-9495-a3a9e86c5bda
GET /activities?start=2016-06-10T10:00:00Z&end=2016-06-30T16:45:50Z HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

HTTP/1.1 200 OK
Content-Type: application/json
Connection: Close

[
    {
        "device_id":"75ee5bf5-1f72-46be-938a-b8610bf9bd70",
        "type":"farming",
        "start":"2016-06-09T18:44:53Z",
        "end":"2016-06-09T21:37:01Z",
        "managementzone_id":"c6f8374a-4e91-487a-8c3d-696591bf4ffc",
        "operator_id":"76093839-2da0-48ec-96c4-c34ab0867d10",
        "selfpropelled_id":"6c2c879d-efc2-4de6-98b8-986b60b55659",
        "implement_id":"9c5c897d-efc2-4de6-98b8-986b60b55659"
        "purpose":"harvesting",
        "traveled_distance":1.2,
        "created_at":"2016-06-09T21:45:20Z"
    }
]

List activity.

List activity in the system.

The activity list can be filtered with query parameters.

The accepted parameters are

Parameter Type Required Notes
start_time RFC3339 timestamp no Start time for activities
end_time RFC3339 timestamp no End time for activities
algorithm_name string no Return activities generated by the specified algorithm
algorithm_version string no Return activities generated by the specified algorithm version
operation_id string no Operation ID for activities
selfpropelled_id uuid no Selfpropelled ID for activities
implement_id uuid no Implement ID for activities
managementzone_id uuid no Managementzone ID for activities

HTTP Request

GET /activities

Parameters

Parameter Type Required Description
device_id uuid no Identifier of the device that sent the heartbeats which triggered the activity.
type string no Type of activity (stationary, farming, travel).
start string yes The start time of the activity (formatted as RFC3339).
end string yes The end time of the activity (formatted as RFC3339).
managementzone_id uuid yes The management zones associated with the activity.
operator_id uuid yes The user ID of the operator that performed the activity.
selfpropelled_id uuid yes The selfpropelled that was involved with the activity.
implement_id uuid yes The equipment that was involved with the activity.
purpose string yes The purpose of the activity (harvesting, planting, etc).
traveled_distance float no The distance traveled in miles during the activity.
operation_id string yes The associated operation id.
algorithm_name string yes we have two algorithm_name avaiable until now (fenster and LeafObserver).
algorithm_version string yes we have one algorithm_version avaiable until now (v0).

HTTP Response

Operation

All operation endpoints must be prefixed with /operations.

All requests and responses are JSON-encoded.

Add Operation

Add a new operation in the Leaf system.

POST /operations HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
    "name":"test",
    "purpose":"tilling",
    "managementzone_id":"67f91903-1316-47bc-b020-fa382228f6a5",
    "completed_date":"2016-08-01T00:00:00Z",
    "active_working_time":"02:00:00",
    "total_stationary_time":"00:14:35",
    "acres":10.0,
    "average_speed":10.0,
    "start":"2016-08-01T00:00:00Z",
    "end":"2016-08-01T00:00:00Z",
    "device_id":"67f91903-1316-47bc-b020-fa382228f6a5",
    "selfpropelled_id":"67f91903-1316-47bc-b020-fa382228f6a5",
    "implement_id":"67f91903-1316-47bc-b020-fa382228f6a5",
    "operator_id":"76093839-2da0-48ec-96c4-c34ab0867d10"
}
HTTP/1.1 201 CREATED
Connection: Close

# Add a new operation.

gurl \
  -X POST \
  -d '{
    "name":"test",
    "purpose":"tilling",
    "managementzone_id":"67f91903-1316-47bc-b020-fa382228f6a5",
    "completed_date":"2016-08-01T00:00:00Z",
    "active_working_time":"02:00:00",
    "total_stationary_time":"00:14:35",
    "acres":10.0,
    "average_speed":10.0,
    "start":"2016-08-01T00:00:00Z",
    "end":"2016-08-01T00:00:00Z",
    "device_id":"67f91903-1316-47bc-b020-fa382228f6a5",
    "selfpropelled_id":"67f91903-1316-47bc-b020-fa382228f6a5",
    "implement_id":"67f91903-1316-47bc-b020-fa382228f6a5",
    "operator": { "id": "76093839-2da0-48ec-96c4-c34ab0867d10" }
  }' \
  -key $API_KEY \
  -secret $API_SECRET \
  "https://api.leaf.ag/resources/v1/operations"

HTTP Request

POST /operations

Post parameters

Parameter Type Required Description
device_id uuid no Identifier of the device that sent the heartbeats which the source of forming operations.
name string no Operation name, the value is from equipment type.
purpose string yes Operation purpose, the value is from equipment purpose.
start string yes The start time of the operation. (formatted as RFC3339).
end string yes The end time of the operation (formatted as RFC3339).
completed_date string no The date of operation completed (formatted as RFC3339).
active_working_time string yes The active working duration between operation start and end (formatted as HH:MM:SS).
total_stationary_time string yes The total stationary time between operation start and end (formatted as HH:MM:SS).
managementzone_id uuid yes The management zones associated with the activity.
selfpropelled_id uuid yes The selfproplled equipment that was involved with the operation.
implement_id uuid yes The implement equipment that was involved with the operation.
operator object yes The user that was involved with the activity.
acres float no The farming coverage of the operation.
average_speed float no The average speed of the operation (the unit is forced to be mph).
algorithm_name string yes Operation created by this API will has default ‘leaf’ algorithm name.
algorithm_version string yes Operation created by this API will has default 'v0’ algorithm version.

HTTP Response

Response Body

JSON-encoded string containing the ID of the new operation.

Example: "8EF57207-9D29-4C4F-8954-FCEFFED272A7"

List Operation

# List all operations
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/operations

# List operations that ended during a two-day period
gurl -X GET -key $API_KEY -secret $API_SECRET -d '{"start":2016-06-28T16:45:50Z,"end":2016-06-30T16:45:50Z}' https://api.leaf.ag/resources/v1/operations
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/operations?start_time=2016-06-10T10:00:00Z&end_time=2016-06-30T16:45:50Z
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/operations?start_time=2016-06-28T16:45:50Z&end_time=2016-06-30T16:45:50Z&algorithm_name=historian&algorithm_version=1.7
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/operations?operation_id=8ba0df9d-5598-4b9c-a63c-9f80ef40a776
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/operations?selfpropelled_id=b3176e8c-3bc6-4f4c-8f82-d74bf4d4b7b1
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/operations?implement_id=ced67b14-94bd-48ea-b0c8-a866f3e5e146
gurl -X GET -key $API_KEY -secret $API_SECRET https://api.leaf.ag/resources/v1/operations?managementzone_id=80db6847-b70d-4680-9495-a3a9e86c5bda
GET /operations?start=2016-06-10T10:00:00Z&end=2016-06-30T16:45:50Z HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Connection: Close

[
    {
        "operation_id": "9dcaa92c-1666-47b5-84ab-0a4c43c3cb28",
        "company_id": 2025,
        "name": "tilling",
        "purpose": "tilling",
        "managementzone_id":"1778dafc-6a54-4701-90ec-5182f4286024",
        "completed_date": "2016-07-28T14:32:16Z",
        "active_working_time": "02:00:00",
        "total_stationary_time": "00:14:35",
        "operator": {
            "user_id": "62e4fa90-5f6b-4795-919d-f1b825706a4e",
            "timezone": "MST",
            "first_name": "Donald",
            "last_name": "Narcia",
        },
        "acres": 0.0,
        "average_speed": 0.0,
        "start": "2016-07-28T13:51:00Z",
        "end": "2016-07-28T14:32:02Z",
        "selfpropelled_id": "e8bca0c0-3603-4660-a111-8835c11da3f3",
        "implement_id": "797d18db-c097-40f9-a0db-b0c09b14335e",
        "activities": [
            {
                "activity_id": "16269fbb-8469-4e95-b724-5d1199097692",
                "company_id": 2025,
                "device_id": "6e8b6f54-7f8b-43a1-ac60-08908c25eb26",
                "activity_type": "travel",
                "activity_start": "2016-07-28T13:51:00Z",
                "activity_end": "2016-07-28T13:53:04Z",
                "managementzone_id": "",
                "selfpropelled_id":"e8bca0c0-3603-4660-a111-8835c11da3f3",
                "implement_id": "797d18db-c097-40f9-a0db-b0c09b14335e",
                "operator_id": "62e4fa90-5f6b-4795-919d-f1b825706a4e",
                "operation_id": "9dcaa92c-1666-47b5-84ab-0a4c43c3cb28",
                "purpose": "",
                "traveled_distance": 2.09335033037573,
                "created_at": "2016-07-28T13:56:01.102189Z",
                "updated_at": "2016-07-28 13:56:01.109299"
            },
            {
                "activity_id": "48674860-6e21-46e2-82fa-383cf6dd06ee",
                "company_id": 2025,
                "device_id": "6e8b6f54-7f8b-43a1-ac60-08908c25eb26",
                "activity_type": "farming",
                "activity_start": "2016-07-28T13:51:32Z",
                "activity_end": "2016-07-28T14:38:43Z",
                "managementzone_id": "1778dafc-6a54-4701-90ec-5182f4286024",
                "selfpropelled_id":"e8bca0c0-3603-4660-a111-8835c11da3f3",
                "implement_id": "797d18db-c097-40f9-a0db-b0c09b14335e",
                "operator_id": "62e4fa90-5f6b-4795-919d-f1b825706a4e",
                "operation_id": "9dcaa92c-1666-47b5-84ab-0a4c43c3cb28",
                "purpose": "tilling",
                "traveled_distance": 2.30242706555077,
                "created_at": "2016-07-28T14:41:01.140239Z",
                "updated_at": "2016-07-28T14:51:01.141167Z"
            },
            {
                "activity_id": "94a3e30e-ec1b-47c6-9e5e-fb31c7eedb12",
                "company_id": 2025,
                "device_id": "6e8b6f54-7f8b-43a1-ac60-08908c25eb26",
                "activity_type": "stationary",
                "activity_start": "2016-07-28T13:54:28Z",
                "activity_end": "2016-07-28T13:56:30Z",
                "managementzone_id": "1778dafc-6a54-4701-90ec-5182f4286024",
                "selfpropelled_id":"e8bca0c0-3603-4660-a111-8835c11da3f3",
                "implement_id": "797d18db-c097-40f9-a0db-b0c09b14335e",
                "operator_id": "62e4fa90-5f6b-4795-919d-f1b825706a4e",
                "operation_id": "9dcaa92c-1666-47b5-84ab-0a4c43c3cb28",
                "purpose": "",
                "traveled_distance": 0,
                "created_at": "2016-07-28T14:01:01.114161Z",
                "updated_at": "2016-07-28T14:01:01.118971Z"
            },
            {
                "activity_id": "2f1b4fc0-3fdf-4be4-ba3f-b6744bc6824f",
                "company_id": 2025,
                "device_id": "6e8b6f54-7f8b-43a1-ac60-08908c25eb26",
                "activity_type": "travel",
                "activity_start": "2016-07-28T13:58:36Z",
                "activity_end": "2016-07-28T14:20:29Z",
                "managementzone_id": "1778dafc-6a54-4701-90ec-5182f4286024",
                "selfpropelled_id":"e8bca0c0-3603-4660-a111-8835c11da3f3",
                "implement_id": "797d18db-c097-40f9-a0db-b0c09b14335e",
                "operator_id": "62e4fa90-5f6b-4795-919d-f1b825706a4e",
                "operation_id": "9dcaa92c-1666-47b5-84ab-0a4c43c3cb28",
                "purpose": "",
                "traveled_distance": 1.53554642077883,
                "created_at": "2016-07-28T14:01:01.130118Z",
                "updated_at": "2016-07-28T14:26:01.12477Z"
            },
            {
                "activity_id": "9facf74f-c41b-4379-a455-066904b7d58c",
                "company_id": 2025,
                "device_id": "6e8b6f54-7f8b-43a1-ac60-08908c25eb26",
                "activity_type": "travel",
                "activity_start": "2016-07-28T14:23:33Z",
                "activity_end": "2016-07-28T14:32:16Z",
                "managementzone_id": "1778dafc-6a54-4701-90ec-5182f4286024",
                "selfpropelled_id":"e8bca0c0-3603-4660-a111-8835c11da3f3",
                "implement_id": "797d18db-c097-40f9-a0db-b0c09b14335e",
                "operator_id": "62e4fa90-5f6b-4795-919d-f1b825706a4e",
                "operation_id": "9dcaa92c-1666-47b5-84ab-0a4c43c3cb28",
                "purpose": "",
                "traveled_distance": 0.467075848274908,
                "created_at": "2016-07-28T14:26:01.132218Z",
                "updated_at": "2016-07-28T14:36:01.134205Z"
            }
        ]
    }
]

List operation.

List operation in the system.

The operation list can be filtered with query parameters.

The accepted parameters are

Parameter Type Required Notes
start_time RFC3339 timestamp no Start time for operations.
end_time RFC3339 timestamp no End time for operations.
algorithm string no A list of Pairs of names and version for operation.
devices array of string no Device ID for operations.

The time parameters details

Timezone Offset ( Hours Behind UTC ) Example
CDT 5 2016-09-01T00:00:00-05:00
CST 6 2016-09-01T00:00:00-06:00
MDT 6 2016-09-01T00:00:00-06:00
MST 7 2016-09-01T00:00:00-07:00
PDT 7 2016-09-01T00:00:00-07:00
PST 7 2016-09-01T00:00:00-07:00
EDT 4 2016-09-01T00:00:00-04:00
EST 5 2016-09-01T00:00:00-05:00

HTTP Request

GET /operations

Parameters

Parameter Type Required Description
device_id uuid no Identifier of the device that sent the heartbeats which the source of forming operations.
name string no Operation name, the value is from equipment type.
purpose string yes Operation purpose, the value is from equipment purpose.
start string yes The start time of the operation. (formatted as RFC3339).
end string yes The end time of the operation (formatted as RFC3339).
completed_date string no The date of operation completed (formatted as RFC3339).
active_working_time string yes The active working duration between operation start and end (formatted as HH:MM:SS).
total_stationary_time string yes The total stationary time between operation start and end (formatted as HH:MM:SS).
managementzone_id uuid yes The management zones associated with the activity.
selfpropelled_id uuid yes The selfproplled equipment that was involved with the operation.
implement_id uuid yes The implement equipment that was involved with the operation.
operator object yes The user that was involved with the activity.
acres float no The farming coverage of the operation.
average_speed float no The average speed of the operation (the unit is forced to be mph).
algorithm_name string yes Operation created by this API will has default 'leaf’ algorithm name.
algorithm_version string yes Operation created by this API will has default 'v0’ algorithm version.

HTTP Response

Get Operation

Get the detailed operation by operation ID.

GET /operations/1c4c3614-c749-45d5-b6c3-5bd9a71d8934 HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "1c4c3614-c749-45d5-b6c3-5bd9a71d8934",
  "company_id": 1,
  "name": "test",
  "purpose": "tilling",
  "managementzone_id":"67f91903-1316-47bc-b020-fa382228f6a5",
  "completed_date": "2016-08-01T00:00:00Z",
  "active_working_time": "02:00:00",
  "total_stationary_time": "00:14:35",
  "operator": {
    "id": "5f5ba55a-4b6d-490b-a859-89bc6f9fa42d",
    "timezone": "MST",
    "first_name": "testuser",
    "last_name": "testuser"
  },
  "acres": 10,
  "average_speed": 10,
  "start": "2016-08-01T00:00:00Z",
  "end": "2016-08-01T00:00:00Z",
  "device_id": "67f91903-1316-47bc-b020-fa382228f6a5",
  "selfpropelled_id": "67f91903-1316-47bc-b020-fa382228f6a5",
  "implement_id":"67f91903-1316-47bc-b020-fa382228f6a5",
  "activities": [
    {
      "id": "28221640-ebf7-4e89-b050-8d82c812f939",
      "device_id": "56f91903-1316-47bc-b020-fa382228f6a5",
      "type": "farming",
      "start": "2016-08-01T19:00:00-05:00",
      "end": "2016-08-01T19:00:00-05:00",
      "managementzone_id":"56f91903-1316-47bc-b020-fa382228f6a5",
      "operator_id": "5f5ba55a-4b6d-490b-a859-89bc6f9fa42d",
      "selfpropelled_id":"67f91903-1316-47bc-b020-fa382228f6a5",
      "implement_id": "67f91903-1316-47bc-b020-fa382228f6a5",
      "purpose": "tilling",
      "operation_id": "1c4c3614-c749-45d5-b6c3-5bd9a71d8934",
      "traveled_distance": 200,
      "algorithm_name": "fenster",
      "algorithm_version": "v1"
    }
  ]
}
gurl -X GET -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/resources/v1/operations/1c4c3614-c749-45d5-b6c3-5bd9a71d8934"
{
  "id": "1c4c3614-c749-45d5-b6c3-5bd9a71d8934",
  "company_id": 1,
  "name": "test",
  "purpose": "tilling",
  "managementzone_id":"67f91903-1316-47bc-b020-fa382228f6a5",
  "completed_date": "2016-08-01T00:00:00Z",
  "active_working_time": "02:00:00",
  "total_stationary_time": "00:14:35",
  "operator": {
    "id": "5f5ba55a-4b6d-490b-a859-89bc6f9fa42d",
    "timezone": "MST",
    "first_name": "testuser",
    "last_name": "testuser"
  },
  "acres": 10,
  "average_speed": 10,
  "start": "2016-08-01T00:00:00Z",
  "end": "2016-08-01T00:00:00Z",
  "device_id": "67f91903-1316-47bc-b020-fa382228f6a5",
  "selfpropelled_id": "67f91903-1316-47bc-b020-fa382228f6a5",
  "implement_id":"67f91903-1316-47bc-b020-fa382228f6a5",
  "activities": [
    {
      "id": "28221640-ebf7-4e89-b050-8d82c812f939",
      "device_id": "56f91903-1316-47bc-b020-fa382228f6a5",
      "type": "farming",
      "start": "2016-08-01T19:00:00-05:00",
      "end": "2016-08-01T19:00:00-05:00",
      "managementzone_id":"56f91903-1316-47bc-b020-fa382228f6a5",
      "operator_id": "5f5ba55a-4b6d-490b-a859-89bc6f9fa42d",
      "selfpropelled_id":"67f91903-1316-47bc-b020-fa382228f6a5",
      "implement_id": "67f91903-1316-47bc-b020-fa382228f6a5",
      "purpose": "tilling",
      "operation_id": "1c4c3614-c749-45d5-b6c3-5bd9a71d8934",
      "traveled_distance": 200,
      "algorithm_name": "fenster",
      "algorithm_version": "v1"
    }
  ]
}

HTTP Request

GET /operations/:id

HTTP Response

Edit Operation

Edit operation by operation ID

PUT /operations/1c4c3614-c749-45d5-b6c3-5bd9a71d8934 HTTP/1.1
Host: api.leaf.ag
Content-Type: application/json

{
    "managementzone_id": "67f91903-1316-47bc-b020-fa382228f6a5",
    "completed_date": "2016-08-01T00:00:00Z",
    "active_working_time": "02:00:00",
    "total_stationary_time": "00:12:35",
    "acres": 10.0,
    "average_speed": 10.0,
    "start": "2016-08-01T00:00:00Z",
    "end": "2016-08-01T00:00:00Z",
    "device_id": "67f91903-1316-47bc-b020-fa382228f6a5",
    "selfpropelled_id": "67f91903-1316-47bc-b020-fa382228f6a5",
    "implement_id": "67f91903-1316-47bc-b020-fa382228f6a5",
    "operator": { "id": "cd0c6a46-0435-46cb-abfa-4233586914d4" }
}
HTTP/1.1 202 Accepted
Connection: Close
gurl \
  -X PUT \
  -key $API_KEY \
  -secret $API_SECRET \
  -d '{
    "managementzone_id": "67f91903-1316-47bc-b020-fa382228f6a5",
    "completed_date": "2016-08-01T00:00:00Z",
    "active_working_time": "02:00:00",
    "total_stationary_time": "00:12:35",
    "acres": 10.0,
    "average_speed": 10.0,
    "start": "2016-08-01T00:00:00Z",
    "end": "2016-08-01T00:00:00Z",
    "device_id": "67f91903-1316-47bc-b020-fa382228f6a5",
    "selfpropelled_id": "67f91903-1316-47bc-b020-fa382228f6a5",
    "implement_id": "67f91903-1316-47bc-b020-fa382228f6a5",
    "operator": {"id": "cd0c6a46-0435-46cb-abfa-4233586914d4"}
    }' \
  "https://api.leaf.ag/resources/v1/operations/1c4c3614-c749-45d5-b6c3-5bd9a71d8934"

HTTP Request

PUT /operations/:id

HTTP Response

Delete operation

Delete operation by operation ID

DELETE /operations/1c4c3614-c749-45d5-b6c3-5bd9a71d8934 HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 204 NOCONTENT
Connection: Close

The request of deleting an operation:

gurl -X DELETE "https://api.leaf.ag/resources/v1/operations/1c4c3614-c749-45d5-b6c3-5bd9a71d8934"

HTTP Request

DELETE /operations/:id

HTTP Response

Export

All export endpoints must be prefixed with /resources/v1/export.

All requests and responses are JSON-encoded.

Export Equipment


gurl "https://api.leaf.ag/resources/v1/export/equipment"


GET /export/equipment HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

Export equipment profile from the system.

Export Personnel


gurl "https://api.leaf.ag/resources/v1/export/personnel"


GET /export/personnel HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

Export personnel profile from the system.

Export ManagementZone


gurl "https://api.leaf.ag/resources/v1/export/managementzones"


GET /export/managementzones HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

Export managementzone profile from the system.

Export Operation and Activity


# Export operations with algorithm is leaf.
gurl -X GET -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/resources/v1/export/operations?algorithm=leaf-1.0&simple=true"

# Export operations with algorithms are leaf and historian.
gurl -X GET -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/resources/v1/export/operations?algorithm=leaf-1.0,historian-1.6&simple=true

# Export operations with algorithms are historian, jdlink, opcenter.
gurl -X GET -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/resources/v1/export/operations?algorithm=historian-1.6,jdlink-1.0,opcenter-1.0&simple=true

# Export activities with algorithm is historian.
gurl -X GET -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/resources/v1/export/operations?algorithm=historian-1.7&simple=false

# Export activities with algorithms are historian, jdlink, opcenter.
gurl -X GET -key $API_KEY -secret $API_SECRET "https://api.leaf.ag/resources/v1/export/operations?algorithm=historian-1.7,jdlink-1.0,opcenter-1.0&simple=false


GET /export/operations?algorithm=historian-1.7&simple=true HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

Export activities and operations from the system.

Import Activity


gurl -X POST -d @activities.csv "https://api.leaf.ag/resources/v1/import/activities"


POST /import/activities HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

<payload>

Import activities from CSV file.

Send mail to sales@leaf.ag


curl -X POST -H 'Content-Type: application/json' "https://api.leaf.ag/resources/v1/contact/mail" -d '
{
 "role": "Dealer",
 "name": "Guillaume",
 "email": "guillaume@leaf.ag",
 "phone_number": "6028182624",
 "state": "Texas",
 "job_title": "Crop Manager",
 "organization_name": "French Fry Farm",
 "comments": "blah blah"
}
'


POST /contact/mail HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

<payload>

Send mail to sales@leaf.ag.

Operations Report

All operations report endpoints must be prefixed with /resources/v1.

All requestes and responsed are JSON-encoded.

List Operations Report

# List all operations
gurl https://api.leaf.ag/resources/v1/operations_report

# List operations that ended during a two-day period
gurl -X GET -d '{"start_time":2016-06-28T16:45:50Z,"end_time":2016-06-30T16:45:50Z}' https://api.leaf.ag/resources/v1/operations_reports
gurl https://api.leaf.ag/resources/v1/operations_reports?start_time=2016-06-10T10:00:00Z&end_time=2016-06-30T16:45:50Z
[
  {
    "report_operation_id": "0886b2ce-ed82-5aa4-a72c-dcd89583a759",
    "company_id": 1,
    "company_name": "NAPI",
    "company_timezone": "America/Phoenix",
    "leaf_operation_id": "9da42d10-5dbb-4ebc-b117-78302f8c7719",
    "unallocated_jdlink_operation_id": "",
    "device_id": "37ad2999-8b46-4529-b685-6a7634e8b193",
    "operation_name": "Disked",
    "purpose": "tilling",
    "start_time": "2017-04-05T18:04:17-05:00",
    "end_time": "2017-04-05T18:51:52-05:00",
    "duration": 0.7930555555555555,
    "algorithm_name": "historian",
    "algorithm_version": "1.7",
    "did_user_crud": false,
    "farming_duration": 0.7930555555555555,
    "stationary_duration": 0,
    "travel_active_duration": 0,
    "travel_stationary_duration": 0,
    "missing_duration": 0,
    "farming_distance_travelled": 5.195478030153149,
    "travel_distance_travelled": 0,
    "farming_covered_acres": 20.15215720786676,
    "farming_gross_acres": 20.15215720786676,
    "operator_id": "0c35670e-3545-4730-b231-1662d5a0f0e6",
    "operator_name": "Ervin Kee",
    "operator_role": "operator",
    "selfpropelled_id": "7d9c7a58-3efa-4f6f-96bf-053f16ed1df6",
    "selfpropelled_name": "24-271",
    "selfpropelled_category": "selfpropelled",
    "selfpropelled_purpose": "driving",
    "selfpropelled_type": "tractor",
    "selfpropelled_make": "John Deere",
    "selfpropelled_model": "9520R",
    "selfpropelled_year": 0,
    "selfpropelled_vin_sn": "1RW9520RCFP016985",
    "selfpropelled_brand": "",
    "selfpropelled_serial": "",
    "selfpropelled_pass_width": 0,
    "selfpropelled_pass_width_units": "",
    "selfpropelled_physical_width": 0,
    "selfpropelled_physical_width_units": "",
    "selfpropelled_beacon_serial": "Sv5h",
    "selfpropelled_beacon_major": 54292,
    "selfpropelled_beacon_minor": 62005,
    "implement_id": "dab31ba0-3257-4cd5-9fb9-34b8f68d8f99",
    "implement_name": "9-118",
    "implement_category": "implement",
    "implement_purpose": "tilling",
    "implement_type": "disk",
    "implement_make": "",
    "implement_model": "337 Disk",
    "implement_year": 0,
    "implement_vin_sn": "",
    "implement_brand": "",
    "implement_serial": "",
    "implement_pass_width": 32,
    "implement_pass_width_units": "feet",
    "implement_physical_width": 32,
    "implement_physical_width_units": "feet",
    "implement_beacon_serial": "o3Ay",
    "implement_beacon_major": 54979,
    "implement_beacon_minor": 28024,
    "managementzone_id": "21706f7a-13b9-44a8-b469-2f71031d5128",
    "managementzone_field_name": null,
    "managementzone_field_actual_acres": null,
    "managementzone_field_description": null,
    "related_farm_id": "",
    "related_farm_name": null,
    "jd_selfpropelled_id": "280655",
    "jd_selfpropelled_name": "24-271, JD 9520R",
    "jdl_working_machine_utilization": null,
    "jdl_idle_machine_utilization": null,
    "jdl_transport_machine_utilization": null,
    "jdl_working_fuel_consumed": null,
    "jdl_idle_fuel_consumed": null,
    "jdl_transport_fuel_consumed": null,
    "jdl_total_fuel_consumed": null,
    "jdl_working_avg_engine_load": null,
    "jdl_idle_avg_engine_load": null,
    "jdl_transport_avg_engine_load": null,
    "jdl_working_avg_ground_speed": null,
    "jdl_idle_avg_ground_speed": null,
    "jdl_transport_avg_ground_speed": null,
    "jd_operation_id": null,
    "jdo_duration": null,
    "jdo_operative_duration": null,
    "jdo_allocated_percentage": null,
    "jdo_operation_type": null,
    "jdo_crop_name": null,
    "jdo_variety_name": null,
    "jdo_product_name": null,
    "jdo_target_acres": null,
    "jdo_result_acres": null,
    "jdo_result_pass_acres": null,
    "jdo_operative_result_acres": null,
    "jdo_operative_result_pass_acres": null,
    "jdo_distance_travelled": null,
    "jdo_operative_distance_travelled": null,
    "jdo_target_material_value": null,
    "jdo_result_material_value": null,
    "jdo_material_unit": null,
    "jdo_yield_value": null,
    "jdo_yield_unit": null,
    "jdo_wet_mass_value": null,
    "jdo_wet_mass_unit": null,
    "jdo_avg_moisture": null,
    "jdo_avg_target_rate_value": null,
    "jdo_avg_target_rate_unit": null,
    "jdo_avg_applied_rate_value": null,
    "jdo_avg_applied_rate_unit": null,
    "jdo_avg_control_rate_value": null,
    "jdo_avg_control_rate_unit": null,
    "jdo_swath_width": null,
    "created_at": "2016-07-28T14:23:33Z",
    "updated_at": "2016-07-28T14:23:33Z",
    "deleted_at": null
  }
]
GET /operations_report?start=2016-06-10T10:00:00Z&end=2016-06-30T16:45:50Z HTTP/1.1
Host: api.leaf.ag
Authorization: AGSIG1 key=<user api key>, signature=<request signature>, ts=<request timestamp>, nonce=<uniq nonce>
Content-Type: application/json

HTTP/1.1 200 OK
Content-Type: application/json
Connection: Close

[
  {
    "report_operation_id": "0886b2ce-ed82-5aa4-a72c-dcd89583a759",
    "company_id": 1,
    "company_name": "NAPI",
    "company_timezone": "America/Phoenix",
    "leaf_operation_id": "9da42d10-5dbb-4ebc-b117-78302f8c7719",
    "unallocated_jdlink_operation_id": "",
    "device_id": "37ad2999-8b46-4529-b685-6a7634e8b193",
    "operation_name": "Disked",
    "purpose": "tilling",
    "start_time": "2017-04-05T18:04:17-05:00",
    "end_time": "2017-04-05T18:51:52-05:00",
    "duration": 0.7930555555555555,
    "algorithm_name": "historian",
    "algorithm_version": "1.7",
    "did_user_crud": false,
    "farming_duration": 0.7930555555555555,
    "stationary_duration": 0,
    "travel_active_duration": 0,
    "travel_stationary_duration": 0,
    "missing_duration": 0,
    "farming_distance_travelled": 5.195478030153149,
    "travel_distance_travelled": 0,
    "farming_covered_acres": 20.15215720786676,
    "farming_gross_acres": 20.15215720786676,
    "operator_id": "0c35670e-3545-4730-b231-1662d5a0f0e6",
    "operator_name": "Ervin Kee",
    "operator_role": "operator",
    "selfpropelled_id": "7d9c7a58-3efa-4f6f-96bf-053f16ed1df6",
    "selfpropelled_name": "24-271",
    "selfpropelled_category": "selfpropelled",
    "selfpropelled_purpose": "driving",
    "selfpropelled_type": "tractor",
    "selfpropelled_make": "John Deere",
    "selfpropelled_model": "9520R",
    "selfpropelled_year": 0,
    "selfpropelled_vin_sn": "1RW9520RCFP016985",
    "selfpropelled_brand": "",
    "selfpropelled_serial": "",
    "selfpropelled_pass_width": 0,
    "selfpropelled_pass_width_units": "",
    "selfpropelled_physical_width": 0,
    "selfpropelled_physical_width_units": "",
    "selfpropelled_beacon_serial": "Sv5h",
    "selfpropelled_beacon_major": 54292,
    "selfpropelled_beacon_minor": 62005,
    "implement_id": "dab31ba0-3257-4cd5-9fb9-34b8f68d8f99",
    "implement_name": "9-118",
    "implement_category": "implement",
    "implement_purpose": "tilling",
    "implement_type": "disk",
    "implement_make": "",
    "implement_model": "337 Disk",
    "implement_year": 0,
    "implement_vin_sn": "",
    "implement_brand": "",
    "implement_serial": "",
    "implement_pass_width": 32,
    "implement_pass_width_units": "feet",
    "implement_physical_width": 32,
    "implement_physical_width_units": "feet",
    "implement_beacon_serial": "o3Ay",
    "implement_beacon_major": 54979,
    "implement_beacon_minor": 28024,
    "managementzone_id": "21706f7a-13b9-44a8-b469-2f71031d5128",
    "managementzone_field_name": null,
    "managementzone_field_actual_acres": null,
    "managementzone_field_description": null,
    "related_farm_id": "",
    "related_farm_name": null,
    "jd_selfpropelled_id": "280655",
    "jd_selfpropelled_name": "24-271, JD 9520R",
    "jdl_working_machine_utilization": null,
    "jdl_idle_machine_utilization": null,
    "jdl_transport_machine_utilization": null,
    "jdl_working_fuel_consumed": null,
    "jdl_idle_fuel_consumed": null,
    "jdl_transport_fuel_consumed": null,
    "jdl_total_fuel_consumed": null,
    "jdl_working_avg_engine_load": null,
    "jdl_idle_avg_engine_load": null,
    "jdl_transport_avg_engine_load": null,
    "jdl_working_avg_ground_speed": null,
    "jdl_idle_avg_ground_speed": null,
    "jdl_transport_avg_ground_speed": null,
    "jd_operation_id": null,
    "jdo_duration": null,
    "jdo_operative_duration": null,
    "jdo_allocated_percentage": null,
    "jdo_operation_type": null,
    "jdo_crop_name": null,
    "jdo_variety_name": null,
    "jdo_product_name": null,
    "jdo_target_acres": null,
    "jdo_result_acres": null,
    "jdo_result_pass_acres": null,
    "jdo_operative_result_acres": null,
    "jdo_operative_result_pass_acres": null,
    "jdo_distance_travelled": null,
    "jdo_operative_distance_travelled": null,
    "jdo_target_material_value": null,
    "jdo_result_material_value": null,
    "jdo_material_unit": null,
    "jdo_yield_value": null,
    "jdo_yield_unit": null,
    "jdo_wet_mass_value": null,
    "jdo_wet_mass_unit": null,
    "jdo_avg_moisture": null,
    "jdo_avg_target_rate_value": null,
    "jdo_avg_target_rate_unit": null,
    "jdo_avg_applied_rate_value": null,
    "jdo_avg_applied_rate_unit": null,
    "jdo_avg_control_rate_value": null,
    "jdo_avg_control_rate_unit": null,
    "jdo_swath_width": null,
    "created_at": "2016-07-28T14:23:33Z",
    "updated_at": "2016-07-28T14:23:33Z",
    "deleted_at": null
  }
]

List operation_reports.

List operation reports in the system.

The operations report list can be filtered with query parameters.

The accepted parameters are:

Parameter Type Required Notes
start_time RFC3339 timestamp no Start time for operations.
end_time RFC3339 timestamp no End time for operations.

HTTP Request

GET /operations_reports

Parameters

Parameter Type Units Description
company_id int Leaf Company ID.
company_name string Leaf Company Name.
company_timezone string Company Timezone.
report_operation_id UUID Operations Report specific ID for operation.
operation_id UUID Leaf Operation ID.
unallocated_jdlink_operation_id UUID Unallocated Operation ID generated from JDLink data.
device_id UUID Unique device identifier.
operation_name string Operations Name. Inferred from equipment.
purpose string Operation Purpose. Inferred from equipment.
start_time RFC3339 Time local tz Time of the operation start. In company’s time zone.
end_time RFC3339 Time local tz Time of the operation end. In company’s time zone.
duration float hours Duration of the operation.
algorithm_name string Algorithm of the operation. “historian” when there is leaf data, “jdlink” or “jdopcenter” otherwise.
algorithm_version string Version of the algorithm when “historian”.
did_user_crud bool Flag whether or not the entry has been manually edited by a user.
farming_duration float hours Duration of the “farming” activities during the operation.
stationary_duration float hours Duration of the “farming” activities during the operation.
travel_active_duration float hours Duration of the “travel_active” activities during the operation.
travel_stationary_duration float hours Duration of the “travel_stationery” activities during the operation.
missing_duration float hours Duration of the “missing” and “travel_missing” activities during the operation.
farming_distance_travelled float miles Distance travelled duration for the “farming” activities for the operation.
travel_distance_travelled float miles Distance travelled duration for the “travel” activities for the operation.
farming_covered_acres float acres Covered Acres (based on pass_width) for “farming” activities for the operation.
farming_gross_acres float acres Covered Acres (based on physical_width) for “farming” activities for the operation.
operator_id UUUD ID of the Leaf user operating the equipment.
operator_name string Name of the user operating the equipment.
operator_role string Role of the user operating the equipment. (Ex. “operator”, “manager”).
selfpropelled_id UUID ID of the operated selfpropelled on the Leaf side.
selfpropelled_name string Name of the SP.
selfpropelled_category string Category of the SP.
selfpropelled_purpose string Purpose of the SP.
selfpropelled_type string Type of the SP.
selfpropelled_make string Make of the SP.
selfpropelled_model string Model of the SP.
selfpropelled_year int Year of the SP.
selfpropelled_vin_sn string VIN of the SP.
selfpropelled_brand string Brand of the SP.
selfpropelled_serial string Serial of the SP.
selfpropelled_pass_width float variable Pass Width of the SP.
selfpropelled_pass_width_units string Units for the SP’s pass width. Should always be “feet”.
selfpropelled_physical_width float variable Physical (“gross”) width of the SP.
selfpropelled_physical_width_units string Units for the SP’s physical wifth. Should always be “feet.”
selfpropelled_beacon_serial string Serial number of the beacon linked to the SP.
selfpropelled_beacon_major int Beacon Major number linked to the SP.
selfpropelled_beacon_minor int Beacon Minor number linked to the SP.
implement_id UUID ID of the operated implement on the Leaf side.
implement_name string Name of the Implement.
implement_category string Category of the Implement.
implement_purpose string Purpose of the Implement.
implement_type string Type of the Implement.
implement_make string Make of the Implement.
implement_model string Model of the Implement.
implement_year int Year of the Implement.
implement_vin_sn string VIN of the Implement.
implement_brand string Brand of the Implement.
implement_serial string Serial of the Implement.
implement_pass_width float variable Pass Width of the Implement.
implement_pass_width_units string Units for the Implement’s pass width. Should always be “feet”.
implement_physical_width float variable Physical (“gross”) width of the Implement.
implement_physical_width_units string Units for the Implement’s physical wifth. Should always be “feet.”
implement_beacon_serial string Serial number of the beacon linked to the Implement.
implement_beacon_major int Beacon Major number linked to the Implement.
implement_beacon_minor int Beacon Minor number linked to the Implement.
managementzone_id UUID ID of the Leaf MZ where the operation took place.
managementzone_field_name string Name of the Leaf MZ.
managementzone_field_actual_acres float acres Area of the Leaf MZ.
managementzone_field_description string Description of the Leaf MZ.
related_farm_id UUID ID of the Leaf Farm on which the operated MZ belong.
related_farm_name string Name of the Farm for the operated MZ.
jd_selfpropelled_id string ID of the John Deere self propelled equipment operated for the operation.
jd_selfpropelled_name string Name of the JD equipment.
jdl_working_machine_utilization float minutes “working” Machine Utilization from JDLink for the operation.
jdl_idle_machine_utilization float minutes “idle” Machine Utilization from JDLink for the operation.
jdl_transport_machine_utilization float minutes “transport” Machine Utilization from JDLink for the operation.
jdl_working_fuel_consumed float gallons “working” Fuel Consumed from JDLink for the operation.
jdl_idle_fuel_consumed float gallons “idle” Fuel Consumed from JDLink for the operation.
jdl_transport_fuel_consumed float gallons “transport” Fuel Consumed from JDLink for the operation.
jdl_total_fuel_consumed float gallons Total (sum of “working”, “idle” and “transport”) Fueld Consumed from JDLink for the operation.
jdl_working_avg_engine_load float % “working” average engine load from JDLink for the operation.
jdl_idle_avg_engine_load float % “idle” average engine load from JDLink for the operation.
jdl_transport_avg_engine_load float % “transport” average engine load from JDLink for the operation.
jdl_working_avg_ground_speed float mph “working” average ground speed from JDLink for the operation.
jdl_idle_avg_ground_speed float mph “idle” average ground speed from JDLink for the operation.
jdl_transport_avg_ground_speed float mph “transport” average ground speed from JDLink for the operation.
jd_operation_id string base64 ID of the Operation on the John Deere side.
jdo_duration float hours Duration of the operation from JD Ops Center.
jdo_operative_duration float hours Duration when values exist for VRYIELDVOL for (harvest), or AppliedRate for (application and planting).
jdo_allocated_percentage float % Percentage of the John Deere Ops Center operation’s time range allcoated to leaf operation.
jdo_operation_type string Type of operation reported by JD Ops Center. Ex: “seeding”, “application” or “harvest”.
jdo_crop_name string Name of the crop reported by JD Ops Center for the operation. Ex: “CORN_SILAGE”, “OATS”, “CORN_WET”, “COTTON”, “SORGHUM”, “WHEAT_DURUM”, “BARLEY”.
jdo_variety_name string Variety of the crop reported by JD Ops Center for the operation. Ex: “FM 2007GLT - 220,000”, “PHY 841”, “DKC-53-45”, “PHY 444 WRF - 230,00”,“PHY 841”, “DKC62-08RIB”
jdo_product_name string Product reported by JD Ops Center for the operation. Ex: “1”, “32-0-0”, “QUADRIS”, “UAN Solution 32-0-0”, “Acid Fert.”.
jdo_target_acres float acres Operator entered target area to be covered for the operation.
jdo_result_acres float acres Actual area covered for the operation based on Swath width and Distance travelled.
jdo_result_pass_acres float acres Actual area covered for the operation based on Pass width and Distance travelled.
jdo_operative_result_acres float acres Operative area covered for the operation based on Swath width when values exist for VRYIELDVOL for (harvest), or AppliedRate for (application and planting).
jdo_operative_result_pass_acres float acres Operative area covered for the operation based on Pass width when values exist for VRYIELDVOL for (harvest), or AppliedRate for (application and planting).
jdo_distance_travelled float feet Sum of the distances reported by John Deere for the operation.
jdo_operative_distance_travelled float feet Sum of the distances reported by John Deere for the operation when values exist for VRYIELDVOL for (harvest), or AppliedRate for (application and planting).
jdo_target_material_value float variable Operator entered target material to be used for the operation.
jdo_result_material_value float variable Actual material used for the operation based on Swath width, distance travelled and average applied rate.
jdo_material_unit string Units for jdo_result_material_value and jdo_target_material_value. Ex: “gal”, “seeds”.
jdo_yield_value float variable Yield of the operation based on VrYieldVol, Swath width and distance travelled.
jdo_yield_unit string Units for jdo_yield_value.
jdo_wet_mass_value float variable Wet mass of the operation based on Swath width and distance travelled.
jdo_wet_mass_unit string Units for jdo_wet_mass_value. Ex: “ton”, “lb”.
jdo_avg_moisture float % Percentage of moisture for the operation time range.
jdo_avg_target_rate_value float variable Average target rate entered by the operator based on the operation time range.
jdo_avg_target_rate_unit string Units for jdo_avg_target_rate_value. Ex: “seeds1ac-1”, “gal1ac-1”, “lb1ac-1”.
jdo_avg_applied_rate_value float variable Average applied rate based on duration.
jdo_avg_applied_rate_unit string Units for jdo_avg_applied_rate_value. Ex: “seeds1ac-1”, “gal1ac-1”, “lb1ac-1”.
jdo_avg_control_rate_value float variable Average control rate based on duration.
jdo_avg_control_rate_unit string Units for jdo_avg_control_rate_value. Ex: “seeds1ac-1”, “gal1ac-1”, “lb1ac-1”.
jdo_swath_width float feet Swath width reported by John Deere for the equipment operated during the operation.

HTTP Response

Get Operation Report

Get the detailed operation report by report operation ID.

GET /operations_report/1c4c3614-c749-45d5-b6c3-5bd9a71d8934 HTTP/1.1
Host: api.leaf.ag
HTTP/1.1 200 OK
Content-Type: application/json

{
  "report_operation_id": "0886b2ce-ed82-5aa4-a72c-dcd89583a759",
  "company_id": 1,
  "company_name": "NAPI",
  "company_timezone": "America/Phoenix",
  "leaf_operation_id": "9da42d10-5dbb-4ebc-b117-78302f8c7719",
  "unallocated_jdlink_operation_id": "",
  "device_id": "37ad2999-8b46-4529-b685-6a7634e8b193",
  "operation_name": "Disked",
  "purpose": "tilling",
  "start_time": "2017-04-05T18:04:17-05:00",
  "end_time": "2017-04-05T18:51:52-05:00",
  "duration": 0.7930555555555555,
  "algorithm_name": "historian",
  "algorithm_version": "1.7",
  "did_user_crud": false,
  "farming_duration": 0.7930555555555555,
  "stationary_duration": 0,
  "travel_active_duration": 0,
  "travel_stationary_duration": 0,
  "missing_duration": 0,
  "farming_distance_travelled": 5.195478030153149,
  "travel_distance_travelled": 0,
  "farming_covered_acres": 20.15215720786676,
  "farming_gross_acres": 20.15215720786676,
  "operator_id": "0c35670e-3545-4730-b231-1662d5a0f0e6",
  "operator_name": "Ervin Kee",
  "operator_role": "operator",
  "selfpropelled_id": "7d9c7a58-3efa-4f6f-96bf-053f16ed1df6",
  "selfpropelled_name": "24-271",
  "selfpropelled_category": "selfpropelled",
  "selfpropelled_purpose": "driving",
  "selfpropelled_type": "tractor",
  "selfpropelled_make": "John Deere",
  "selfpropelled_model": "9520R",
  "selfpropelled_year": 0,
  "selfpropelled_vin_sn": "1RW9520RCFP016985",
  "selfpropelled_brand": "",
  "selfpropelled_serial": "",
  "selfpropelled_pass_width": 0,
  "selfpropelled_pass_width_units": "",
  "selfpropelled_physical_width": 0,
  "selfpropelled_physical_width_units": "",
  "selfpropelled_beacon_serial": "Sv5h",
  "selfpropelled_beacon_major": 54292,
  "selfpropelled_beacon_minor": 62005,
  "implement_id": "dab31ba0-3257-4cd5-9fb9-34b8f68d8f99",
  "implement_name": "9-118",
  "implement_category": "implement",
  "implement_purpose": "tilling",
  "implement_type": "disk",
  "implement_make": "",
  "implement_model": "337 Disk",
  "implement_year": 0,
  "implement_vin_sn": "",
  "implement_brand": "",
  "implement_serial": "",
  "implement_pass_width": 32,
  "implement_pass_width_units": "feet",
  "implement_physical_width": 32,
  "implement_physical_width_units": "feet",
  "implement_beacon_serial": "o3Ay",
  "implement_beacon_major": 54979,
  "implement_beacon_minor": 28024,
  "managementzone_id": "21706f7a-13b9-44a8-b469-2f71031d5128",
  "managementzone_field_name": null,
  "managementzone_field_actual_acres": null,
  "managementzone_field_description": null,
  "related_farm_id": "",
  "related_farm_name": null,
  "jd_selfpropelled_id": "280655",
  "jd_selfpropelled_name": "24-271, JD 9520R",
  "jdl_working_machine_utilization": null,
  "jdl_idle_machine_utilization": null,
  "jdl_transport_machine_utilization": null,
  "jdl_working_fuel_consumed": null,
  "jdl_idle_fuel_consumed": null,
  "jdl_transport_fuel_consumed": null,
  "jdl_total_fuel_consumed": null,
  "jdl_working_avg_engine_load": null,
  "jdl_idle_avg_engine_load": null,
  "jdl_transport_avg_engine_load": null,
  "jdl_working_avg_ground_speed": null,
  "jdl_idle_avg_ground_speed": null,
  "jdl_transport_avg_ground_speed": null,
  "jd_operation_id": null,
  "jdo_duration": null,
  "jdo_operative_duration": null,
  "jdo_allocated_percentage": null,
  "jdo_operation_type": null,
  "jdo_crop_name": null,
  "jdo_variety_name": null,
  "jdo_product_name": null,
  "jdo_target_acres": null,
  "jdo_result_acres": null,
  "jdo_result_pass_acres": null,
  "jdo_operative_result_acres": null,
  "jdo_operative_result_pass_acres": null,
  "jdo_distance_travelled": null,
  "jdo_operative_distance_travelled": null,
  "jdo_target_material_value": null,
  "jdo_result_material_value": null,
  "jdo_material_unit": null,
  "jdo_yield_value": null,
  "jdo_yield_unit": null,
  "jdo_wet_mass_value": null,
  "jdo_wet_mass_unit": null,
  "jdo_avg_moisture": null,
  "jdo_avg_target_rate_value": null,
  "jdo_avg_target_rate_unit": null,
  "jdo_avg_applied_rate_value": null,
  "jdo_avg_applied_rate_unit": null,
  "jdo_avg_control_rate_value": null,
  "jdo_avg_control_rate_unit": null,
  "jdo_swath_width": null,
  "created_at": "2016-07-28T14:23:33Z",
  "updated_at": "2016-07-28T14:23:33Z",
  "deleted_at": null
}
gurl "https://api.leaf.ag/resources/v1/operations_report/1c4c3614-c749-45d5-b6c3-5bd9a71d8934"
{
  "report_operation_id": "0886b2ce-ed82-5aa4-a72c-dcd89583a759",
  "company_id": 1,
  "company_name": "NAPI",
  "company_timezone": "America/Phoenix",
  "leaf_operation_id": "9da42d10-5dbb-4ebc-b117-78302f8c7719",
  "unallocated_jdlink_operation_id": "",
  "device_id": "37ad2999-8b46-4529-b685-6a7634e8b193",
  "operation_name": "Disked",
  "purpose": "tilling",
  "start_time": "2017-04-05T18:04:17-05:00",
  "end_time": "2017-04-05T18:51:52-05:00",
  "duration": 0.7930555555555555,
  "algorithm_name": "historian",
  "algorithm_version": "1.7",
  "did_user_crud": false,
  "farming_duration": 0.7930555555555555,
  "stationary_duration": 0,
  "travel_active_duration": 0,
  "travel_stationary_duration": 0,
  "missing_duration": 0,
  "farming_distance_travelled": 5.195478030153149,
  "travel_distance_travelled": 0,
  "farming_covered_acres": 20.15215720786676,
  "farming_gross_acres": 20.15215720786676,
  "operator_id": "0c35670e-3545-4730-b231-1662d5a0f0e6",
  "operator_name": "Ervin Kee",
  "operator_role": "operator",
  "selfpropelled_id": "7d9c7a58-3efa-4f6f-96bf-053f16ed1df6",
  "selfpropelled_name": "24-271",
  "selfpropelled_category": "selfpropelled",
  "selfpropelled_purpose": "driving",
  "selfpropelled_type": "tractor",
  "selfpropelled_make": "John Deere",
  "selfpropelled_model": "9520R",
  "selfpropelled_year": 0,
  "selfpropelled_vin_sn": "1RW9520RCFP016985",
  "selfpropelled_brand": "",
  "selfpropelled_serial": "",
  "selfpropelled_pass_width": 0,
  "selfpropelled_pass_width_units": "",
  "selfpropelled_physical_width": 0,
  "selfpropelled_physical_width_units": "",
  "selfpropelled_beacon_serial": "Sv5h",
  "selfpropelled_beacon_major": 54292,
  "selfpropelled_beacon_minor": 62005,
  "implement_id": "dab31ba0-3257-4cd5-9fb9-34b8f68d8f99",
  "implement_name": "9-118",
  "implement_category": "implement",
  "implement_purpose": "tilling",
  "implement_type": "disk",
  "implement_make": "",
  "implement_model": "337 Disk",
  "implement_year": 0,
  "implement_vin_sn": "",
  "implement_brand": "",
  "implement_serial": "",
  "implement_pass_width": 32,
  "implement_pass_width_units": "feet",
  "implement_physical_width": 32,
  "implement_physical_width_units": "feet",
  "implement_beacon_serial": "o3Ay",
  "implement_beacon_major": 54979,
  "implement_beacon_minor": 28024,
  "managementzone_id": "21706f7a-13b9-44a8-b469-2f71031d5128",
  "managementzone_field_name": null,
  "managementzone_field_actual_acres": null,
  "managementzone_field_description": null,
  "related_farm_id": "",
  "related_farm_name": null,
  "jd_selfpropelled_id": "280655",
  "jd_selfpropelled_name": "24-271, JD 9520R",
  "jdl_working_machine_utilization": null,
  "jdl_idle_machine_utilization": null,
  "jdl_transport_machine_utilization": null,
  "jdl_working_fuel_consumed": null,
  "jdl_idle_fuel_consumed": null,
  "jdl_transport_fuel_consumed": null,
  "jdl_total_fuel_consumed": null,
  "jdl_working_avg_engine_load": null,
  "jdl_idle_avg_engine_load": null,
  "jdl_transport_avg_engine_load": null,
  "jdl_working_avg_ground_speed": null,
  "jdl_idle_avg_ground_speed": null,
  "jdl_transport_avg_ground_speed": null,
  "jd_operation_id": null,
  "jdo_duration": null,
  "jdo_operative_duration": null,
  "jdo_allocated_percentage": null,
  "jdo_operation_type": null,
  "jdo_crop_name": null,
  "jdo_variety_name": null,
  "jdo_product_name": null,
  "jdo_target_acres": null,
  "jdo_result_acres": null,
  "jdo_result_pass_acres": null,
  "jdo_operative_result_acres": null,
  "jdo_operative_result_pass_acres": null,
  "jdo_distance_travelled": null,
  "jdo_operative_distance_travelled": null,
  "jdo_target_material_value": null,
  "jdo_result_material_value": null,
  "jdo_material_unit": null,
  "jdo_yield_value": null,
  "jdo_yield_unit": null,
  "jdo_wet_mass_value": null,
  "jdo_wet_mass_unit": null,
  "jdo_avg_moisture": null,
  "jdo_avg_target_rate_value": null,
  "jdo_avg_target_rate_unit": null,
  "jdo_avg_applied_rate_value": null,
  "jdo_avg_applied_rate_unit": null,
  "jdo_avg_control_rate_value": null,
  "jdo_avg_control_rate_unit": null,
  "jdo_swath_width": null,
  "created_at": "2016-07-28T14:23:33Z",
  "updated_at": "2016-07-28T14:23:33Z",
  "deleted_at": null
}

HTTP Request

GET /operations_report/:id

HTTP Response

Streams

Streams is a service dedicated to streaming events.

The service exposes two types of endpoints: WebSocket and HTTP.

Clients who wish to use realtime streaming will use the WebSocket endpoints, whereas clients who wish to use polling will choose HTTP.

Authentication

Subscribe using Websocket with http header auth (regular mode)
gurl -X GET -key $API_KEY -secret $API_SECRET wss://qa-api.leaf.ag/streams/v1/ws/activity

HTTP Request

GET /ws/activity

HTTP Response

JSON stream of Event. (See Event Payload section)

Get an auth token
token=$(gurl -X GET -key $API_KEY -secret $API_SECRET https://qa-api.leaf.ag/streams/v1/token | jq -r .)
echo $token

HTTP Request

GET /token

HTTP Response

Payload: json encoded string representation of the new token.

Subscribe using Websocket with token based auth
token=$(gurl -X GET -key $API_KEY -secret $API_SECRET https://qa-api.leaf.ag/streams/v1/token | jq -r .)
gurl -X GET wss://api.leaf.ag/streams/v1/ws/token/activity/$token

In order to subscribe to a websocket stream without setting the Authorization http header, you need to first retrieve a token and use it when connecting to the websocket endpoint.

HTTP Request

GET /ws/token/activity/:token

HTTP Response

JSON stream of Event. See Event Response

Create Events

gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '[
    {
      "event_type": "operator_login",
      "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
      "device_id": "1f4fd6e8-c38e-495d-a084-508a4ff3626b",
      "event_time": "2016-04-25T18:02:02Z",
      "latitude": -83.2284,
      "longitude": 47.3394,
      "heading": 1.2,
      "speed": 33.5
    },
    {
      "event_type": "operator_logout",
      "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
      "device_id": "1f4fd6e8-c38e-495d-a084-508a4ff3626b",
      "event_time": "2016-04-25T18:05:43Z",
      "latitude": -83.2284,
      "longitude": 43.5336,
      "heading": 137.23307,
      "speed": 7.3289
    },
    {
      "event_type": "pairing",
      "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
      "managementzone_id": "8b212ec1-0acf-47e9-8144-c05e34f8c558",
      "latitude": -28.202939,
      "longitude": 33.2389,
      "heading": 137.23307,
      "speed": 7.3289,
      "beacons": [
        {
          "proximity_uuid": "800e1e57-cae4-4ab2-9e8f-af4e138d7964",
          "major": 4637,
          "minor": 8776,
          "distance": 9.32284
        },
        {
          "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
          "major": 2876,
          "minor": 9077,
          "distance": 1.2948576
        }
      ],
      "paired_beacons": [
        {
          "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
          "major": 2876,
          "minor": 9077,
          "distance": 1.2948576
        }
      ],
      "event_time": "2016-04-27T18:11:24Z"
    },
    {
      "event_type": "managementzone_enter",
      "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
      "device_id": "1f4fd6e8-c38e-495d-a084-508a4ff3626b",
      "managementzone_id": "8b212ec1-0acf-47e9-8144-c05e34f8c558",
      "heading": 137.23307,
      "speed": 7.3289,
      "beacons": [
        {
          "proximity_uuid": "800e1e57-cae4-4ab2-9e8f-af4e138d7964",
          "major": 4637,
          "minor": 8776,
          "distance": 9.32284
        },
        {
          "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
          "major": 2876,
          "minor": 9077,
          "distance": 1.2948576
        }
      ],
      "paired_beacons": [
        {
          "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
          "major": 2876,
          "minor": 9077,
          "distance": 1.2948576
        }
      ],
      "event_time": "2016-04-27T14:11:24Z"
    },
    {
      "event_type": "managementzone_exit",
      "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
      "managementzone_id": "8b212ec1-0acf-47e9-8144-c05e34f8c558",
      "heading": 137.23307,
      "speed": 7.3289,
      "beacons": [
        {
          "proximity_uuid": "800e1e57-cae4-4ab2-9e8f-af4e138d7964",
          "major": 4637,
          "minor": 8776,
          "distance": 9.32284
        },
        {
          "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
          "major": 2876,
          "minor": 9077,
          "distance": 1.2948576
        }
      ],
      "paired_beacons": [
        {
          "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
          "major": 2876,
          "minor": 9077
        }
      ],
      "event_time": "2016-04-27T18:11:24Z"
    }
  ]' https://qa-api.leaf.ag/streams/v1/events

HTTP Request

POST /events

Request body should be an array of Event Request objects.

Event Request

This model is only used in the Create Events request.

Parameters Type Required Description
event_type string Yes The type of the event (see Event Types).
event_time time Yes RFC3339 timestamp that specifies when the client observed the event.
data object No The event data. The structure of the data depends on the event_type.
device_id string No The device id. For iOS, it will be the serial number.
user_id string No The ID of the operator who triggered the event.
managementzone_id string No The ID of the management zone in which the event occurred.
beacons []Beacon No Beacons that were nearby when the event was generated.
paired_beacons []Beacon No Beacons that were paired when the event was generated.
latitude float No Latitude Location. The units of latitude is degrees.
longitude float No Longitude Location. The units of longitude is degrees.
heading float No Heading of the device. The units of heading is degrees.
speed float No Speed of the device. The units of speed is meters/second.

HTTP Response

Status Codes

Get Events

gurl -X GET -key $API_KEY -secret $API_SECRET https://qa-api.leaf.ag/streams/v1/events

[
  {
    "event_type": "operator_login",
    "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
    "device_id": "1f4fd6e8-c38e-495d-a084-508a4ff3626b",
    "event_time": "2016-04-25T18:02:02Z",
    "latitude": -83.2284,
    "longitude": 47.3394,
    "heading": 1.2,
    "speed": 33.5,
    "sender": {
      "id": "4557f0b8-f230-42c3-ad93-3259bb24c377"
    }
  },
  {
    "event_type": "operator_logout",
    "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
    "device_id": "1f4fd6e8-c38e-495d-a084-508a4ff3626b",
    "event_time": "2016-04-25T18:05:43Z",
    "latitude": -83.2284,
    "longitude": 43.5336,
    "heading": 137.23307,
    "speed": 7.3289,
    "sender": {
      "id": "4557f0b8-f230-42c3-ad93-3259bb24c377"
    }
  },
  {
    "event_type": "pairing",
    "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
    "managementzone_id": "8b212ec1-0acf-47e9-8144-c05e34f8c558",
    "latitude": -28.202939,
    "longitude": 33.2389,
    "heading": 137.23307,
    "speed": 7.3289,
    "sender": {
      "id": "4557f0b8-f230-42c3-ad93-3259bb24c377"
    },
    "beacons": [
      {
        "proximity_uuid": "800e1e57-cae4-4ab2-9e8f-af4e138d7964",
        "major": 4637,
        "minor": 8776,
        "distance": 9.32284
      },
      {
        "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
        "major": 2876,
        "minor": 9077,
        "distance": 1.2948576
      }
    ],
    "paired_beacons": [
      {
        "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
        "major": 2876,
        "minor": 9077,
        "distance": 1.2948576
      }
    ],
    "event_time": "2016-04-27T18:11:24Z"
  },
  {
    "event_type": "managementzone_enter",
    "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
    "device_id": "1f4fd6e8-c38e-495d-a084-508a4ff3626b",
    "managementzone_id": "8b212ec1-0acf-47e9-8144-c05e34f8c558",
    "heading": 137.23307,
    "speed": 7.3289,
    "sender": {
      "id": "4557f0b8-f230-42c3-ad93-3259bb24c377"
    },
    "beacons": [
      {
        "proximity_uuid": "800e1e57-cae4-4ab2-9e8f-af4e138d7964",
        "major": 4637,
        "minor": 8776,
        "distance": 9.32284
      },
      {
        "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
        "major": 2876,
        "minor": 9077,
        "distance": 1.2948576
      }
    ],
    "paired_beacons": [
      {
        "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
        "major": 2876,
        "minor": 9077,
        "distance": 1.2948576
      }
    ],
    "event_time": "2016-04-27T14:11:24Z"
  },
  {
    "event_type": "managementzone_exit",
    "user_id": "d640de41-1cd9-4dca-9025-8139cfef7126",
    "managementzone_id": "8b212ec1-0acf-47e9-8144-c05e34f8c558",
    "heading": 137.23307,
    "speed": 7.3289,
    "sender": {
      "id": "4557f0b8-f230-42c3-ad93-3259bb24c377"
    },
    "beacons": [
      {
        "proximity_uuid": "800e1e57-cae4-4ab2-9e8f-af4e138d7964",
        "major": 4637,
        "minor": 8776,
        "distance": 9.32284
      },
      {
        "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
        "major": 2876,
        "minor": 9077,
        "distance": 1.2948576
      }
    ],
    "paired_beacons": [
      {
        "proximity_uuid": "cfb6c6d9-7c0d-4edf-8fc9-775f801afa1b",
        "major": 2876,
        "minor": 9077,
        "distance": 1.2948576
      }
    ],
    "event_time": "2016-04-27T18:11:24Z"
  },
  {
    "id": "99ffe889-8702-4cf6-aea4-b77af50dd474",
    "user_id": "1bac2df2-790e-4a73-aa53-0bf89463eec3",
    "latitude": 37.33233141,
    "longitude": -122.0312186,
    "heading": 0,
    "speed": 0,
    "device_id": "54ca6696-2dac-48d2-bfda-a9bcd3c547ef",
    "sender": {
      "id": "4557f0b8-f230-42c3-ad93-3259bb24c377"
    },
    "event_type": "location",
    "data": {
      "equipment_ids": [
        "3ebf2a60-05a2-4a5c-ac58-eda735cae99e",
        "dc6b5866-9eff-4a28-bb0d-56c3008f28ba"
      ]
    },
    "event_time": "2016-04-27T15:57:27Z",
    "created_at": "2016-04-27T15:57:27.327205Z"
  }
]

HTTP Request

GET /events

Query Parameters

Paramter Type Default Description
start_date RFC3339 timestamp Beginning of time Return events only if they occurred after this time
end_date RFC3339 timestamp Now Return events only if they occurred before this time
limit int 10 Return at most limit items
include csv all List of event types to include
exclude csv none List of event types to exclude
beacons bool 1 Set to “0” to disable beacons query
skip int 0 Number of events to skip

Notes

Valid values for include/exclude parameters

HTTP Response

An array of Event Response objects.

Event Response

This model is used for the Get Events response, as well as in the event streams that come from a websocket connection.

Parameter Type Required Description
id string Yes Event ID.
sender object Yes User that sent the event. See the user model.
event_type string Yes Describe the type of event. See Event Types below for valid values.
event_time RFC3339 timestamp Yes Time that event was observed by the client.
created_at RFC3339 timestamp Yes Time that event was created on the server.
data object No Describe event-specific data. See below for the data structure of each event type.
device_id string No The device id. For iOS, it will be the serial number.
user_id string No The ID of the operator who triggered the event.
managementzone_id string No The ID of the management zone in which the event occurred.
beacons []Beacon No Beacons that were nearby when the event was generated.
paired_beacons []Beacon No Beacons that were paired when the event was generated.
lat float No Latitude Location. The units of lat is degrees.
long float No Longitude Location. The units of long is degrees.
heading float No Heading of the device. The units of heading is degrees.
speed float No Speed of the device. The units of speed is meters/second.

Status Codes

Events

Event Types

The event types we currently support are:

CRUD Event

CRUD events happen when any resource in the system is created, updated, or deleted.

Notes

Data structure

Parameter Type Description
resource_type string Resource type. Valid values: [“equipment”, “managementzones”, “users”]
kind string CRUD action. Valid values: [“Insert”, “Update”, “Delete”]
resource string The JSON encoded new state of the concerned resource.
former_resource string The JSON encoded old state of the concerned resource.
gurl -X GET -key $API_KEY -secret $API_SECRET https://qa-api.leaf.ag/streams/v1/events

[
  {
    "user_id": "999fad7b-b222-4a8c-9d39-96ca4cd9f748",
    "event_type": "crud",
    "event_time": "2016-04-25T18:09:15Z",
    "data": {
      "id": "466df65c-7938-4711-b970-d5597dc4b695",
      "kind": "Insert",
      "resource_type": "equipment",
      "resource": "{\"beacon\":{\"major\":2,\"minor\":2,\"uuid\":\"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22\"},\"category\":\"selfpropelled\",\"company_id\":1,\"fields\":[{\"name\":\"field name\",\"value\":\"field value\"}],\"id\":\"466df65c-7938-4711-b970-d5597dc4b695\",\"make\":\"make\",\"model\":\"model\",\"name\":\"myTractor updatee\",\"tags\":[\"tag1\"],\"type\":\"tractor\",\"user_id\":\"999fad7b-b222-4a8c-9d39-96ca4cd9f748\",\"year\":2016}"
    }
  },
  {
    "user_id": "999fad7b-b222-4a8c-9d39-96ca4cd9f748",
    "event_type": "crud",
    "event_time": "2016-04-25T18:09:29Z",
    "data": {
      "id": "466df65c-7938-4711-b970-d5597dc4b695",
      "kind": "Update",
      "resource_type": "equipment",
      "resource": "{\"beacon\":{\"major\":2,\"minor\":2,\"uuid\":\"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22\"},\"category\":\"selfpropelled\",\"company_id\":1,\"created_at\":\"2016-02-11T04:48:17.30343Z\",\"fields\":[{\"name\":\"field name\",\"value\":\"field value\"},{\"name\":\"field name\",\"value\":\"field value\"}],\"id\":\"466df65c-7938-4711-b970-d5597dc4b695\",\"make\":\"make\",\"model\":\"model\",\"name\":\"myTractor updatee\",\"tags\":[\"tag1\",\"tag1\"],\"type\":\"tractor\",\"updated_at\":\"2016-02-11T04:48:39.985196Z\",\"user_id\":\"999fad7b-b222-4a8c-9d39-96ca4cd9f748\",\"year\":2016}",
      "former_resource": "{\"beacon\":{\"major\":2,\"minor\":2,\"uuid\":\"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22\"},\"category\":\"selfpropelled\",\"company_id\":1,\"created_at\":\"2016-02-11T04:48:17.30343Z\",\"fields\":[{\"name\":\"field name\",\"value\":\"field value\"}],\"id\":\"466df65c-7938-4711-b970-d5597dc4b695\",\"make\":\"make\",\"model\":\"model\",\"name\":\"myTractor updatee\",\"tags\":[\"tag1\"],\"type\":\"tractor\",\"updated_at\":\"2016-02-11T04:48:17.30343Z\",\"user_id\":\"999fad7b-b222-4a8c-9d39-96ca4cd9f748\",\"year\":2016}"
    }
  }
]

CRUD event format.

Location Event

Location events are automatically sent to WebSocket clients when heartbeats are created that contain beacons that are paired with equipment.

Parameter Type Required Description
user_id string no User ID of the operator.
device_id string no Identifier of the device that triggered the event.
managementzone_id string no Identifier of the management zone the device was in when it triggered the event.
longitude float64 yes Longitude. The units of longitude is degrees.
latitude float64 yes Latitude. The units of latitude is degrees.
speed float64 yes Speed in meters per second. The units of speed is meters/second.
heading float64 yes Heading (0 is due to north, 90 is due to east, etc). The units of speed is degrees.
timestamp int yes Time of the GPS data.
equipment_ids []string no ID’s of equipment that was present when the location event was triggered.
gurl -X GET -key $API_KEY -secret $API_SECRET 'https://qa-api.leaf.ag/streams/v1/events?include=location'

[
  {
    "id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
    "user_id": "4ae2a3d6-781e-4599-a66e-e775cb4ce0c5",
    "event_type": "location",
    "device_id": "22bc394b-78cb-4a4a-b679-abec4348a8a3",
    "managementzone_id": "8a41c2f7-3212-4139-9a20-ec5d2971a530",
    "longitude": 97.75,
    "latitude": 30.25,
    "heading": 1.2,
    "speed": 33.5,
    "timestamp": 0,
    "data": {
      "equipment_ids": [
        "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
        "74786684-bcc7-43ea-98fd-137902b0bb43"
      ]
    },
    "event_time": "2016-02-11T03:25:29.034209729Z"
  }
]

Location event format.

Operator Login Event

gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '[
    {
      "event_type": "operator_login",
      "user_id": "2acc7975-6f00-4d03-8c77-14f649dea51d",
      "event_time": "2016-02-25T15:02:41Z"
    }
  ]' https://qa-api.leaf.ag/streams/v1/events

Operator Login event format.

Operator Logout Event

gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '[
    {
      "event_type": "operator_logout",
      "user_id": "2acc7975-6f00-4d03-8c77-14f649dea51d",
      "event_time": "2016-02-25T15:03:04Z"
    }
  ]' https://qa-api.leaf.ag/streams/v1/events

Operator Logout event format.

Pairing Event

gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '[
    {
      "event_type": "pairing",
      "beacons": [
        {
          "proximity_uuid": "8d442b8c-ce72-4595-a5dc-138f59da2d26",
          "major": 1008,
          "minor": 7324,
          "distance": 21.2
        },
        {
          "proximity_uuid": "3cba88ca-37e8-4463-b402-bd27a714a3de",
          "major": 2385,
          "minor": 1279,
          "distance": 20.18
        }
      ],
      "paired_beacons": [
        {
          "proximity_uuid": "8d442b8c-ce72-4595-a5dc-138f59da2d26",
          "major": 1008,
          "minor": 7324
        },
        {
          "proximity_uuid": "3cba88ca-37e8-4463-b402-bd27a714a3de",
          "major": 2385,
          "minor": 1279
        }
      ],
      "event_time": "2016-02-25T15:03:04Z"
    }
  ]' https://qa-api.leaf.ag/streams/v1/events

Pairing event format.

Managementzone Enter Event

# Example Request
gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '[
    {
      "user_id": "7b3db577-6db4-4f5c-89d1-1400e510735a",
      "event_type": "managementzone_enter",
      "event_time": "2016-03-25T16:31:58Z",
      "beacons": [
        {
          "proximity_uuid": "b745e29a-1768-4660-93ff-109ddfb552f6",
          "major": 1002,
          "minor": 7327,
          "distance": 1.43938
        },
        {
          "proximity_uuid": "f6235a75-0918-47a1-9e83-a7276c4cae95",
          "major": 2387,
          "minor": 1271,
          "distance": 0.23894
        }
      ],
      "paired_beacons": [
        {
          "proximity_uuid": "b745e29a-1768-4660-93ff-109ddfb552f6",
          "major": 1002,
          "minor": 7327
        }
      ]
    }
  ]' https://qa-api.leaf.ag/streams/v1/events

Managementzone Enter event format.

Managementzone Exit Event

# Example Request
gurl -X POST -key $API_KEY -secret $API_SECRET \
  -d '[
    {
      "event_type": "managementzone_exit",
      "event_time": "2016-03-25T16:31:58Z",
      "user_id": "7b3db577-6db4-4f5c-89d1-1400e510735a",
      "beacons": [
        {
          "proximity_uuid": "b745e29a-1768-4660-93ff-109ddfb552f6",
          "major": 1002,
          "minor": 7327,
          "distance": 1.43938
        },
        {
          "proximity_uuid": "f6235a75-0918-47a1-9e83-a7276c4cae95",
          "major": 2387,
          "minor": 1271,
          "distance": 0.23894
        }
      ],
      "paired_beacons": [
        {
          "proximity_uuid": "f6235a75-0918-47a1-9e83-a7276c4cae95",
          "major": 2387,
          "minor": 1271
        }
      ]
    }
  ]' https://qa-api.leaf.ag/streams/v1/events

Managementzone Exit event format.

GetDevices

This API endpoint retrives a list of active devices for a given company.

Parameter Type Option Description
start_date RFC3339 timestamp Beginning of time Return devices with only if they have data after this time
end_date RFC3339 timestamp Now Return devices with only if they have data before this time

HTTP Request

GET /devices

HTTP Response

[“72b5f1fa-c930-4435-be29-48b5b4773afe”, “1229154a-7f47-407c-bd04-1add5c092fed”]

gurl -key $API_KEY -secret $API_SECRET https://api.leaf.ag/streams/v1/devices

gurl -key $API_KEY -secret $API_SECRET https://api.leaf.ag/streams/v1/devices?start_date=2016-09-09T07:27:20Z&end_date=2016-09-09T17:27:20Z

Errors

The Leaf API uses the following error codes:

Error Code Meaning
400 Bad Request
401 Unauthorized – Check your token
403 Forbidden
404 Not Found
500 Internal Server Error

Golang

Why Golang?

Golang (also called Go) started in 2009 as a solution to multi-core application needs.

Strongly Typed / Statically Typed

Having a strongly typed (and statically typed) language makes it easier to have good designs and performant code.

Compiled / Statically Linked

Because Go is compiled, most errors will be caught at compile time instead of runtime. This result in better stability of the product.

On top of being compiled, Go is (can be) statically linked. This means there are no runtime dependencies (no libc, no other shared libraries needed) which make the deployment very easy.

Using Docker, this also results in much smaller images which means faster deployment and faster testing.

Multi-Platform support

Go has a very simple cross compilation system that make it easy to compile for any platform from your local dev environment.

Speed

With a simple benchmark on 3xlarge AWS instance, we reached 4.5M req/sec, which is not even conceivable with most languages out there.

Concurency

Go is natively concurrent, it exposes mechanism like channels in order to make cross-thread communication easy.

Testing

Part of the Go library is the testing “framework” which makes it easy to reliably test the code and generate coverage reports.

Future proof

Go has been rising for the past 3 years and keeps growing. The community is very strong, there are a lot of libraries/drivers/bindings out there for almost any use case. Using Go puts us in a good situation on both product scalability and developer recruitment.

Installation

Non developer

# OSX
brew install golang
# Ubuntu
apt-get install -y golang

Non-developer installation.

If you are not a developer (i.e. just need to install one of the tool or packages), you can install Go using your system’s package manager.

Developer

# Set your environement (should be in your .profile/.bashrc/.zshrc accordingly)
export GOPATH=$HOME/go
export GOROOT=$HOME/goroot
export GOBIN=$GOROOT/bin
export PATH=$GOBIN:$PATH

# Clone the golang repository
git clone https://github.com/golang/go ~/goroot

# Install go1.4
## Copy the cloned repository to temporary goroot
cp -r ~/goroot ~/go1.4
## Checkout go1.4
cd ~/go1.4/src
git checkout go1.4.2
## Install go1.4
GOROOT=~/go1.4 GOBIN=~/go1.4/bin ./make.bash

# Install go1.5
## Checkout go1.5 in final repository
cd ~/goroot/src
git checkout go1.5.3 # (change according to latest go version)
./make.bash

Developer installation.

As a developer, you will most likely need to introspect and interact with the standard libary. It is bad practice to tamper with system installed files which may result in conflicts when updating. A developer should install Go from source.

Documents

Every Go developer should be very familiar with these documents:

A more advanced go developer needs to be familiar with these documents as well:

Finally, here is the semi-official Golang coding style: CodeReviewComments. Note that this document takes precedence over the CodeReviewComments style guide. We are a bit stricter than them.

Update dependencies

As a lot of our dependencies are activelly maintained, the team will endup with different version of them locally. Our vendor system (Godeps for now, native go vendor when 1.6 get stable) fixes those and allow us to not worry about it when running or testing a service. However, when developing, those differences will create conflicts when merging. To avoid this, make sure you are up to date with all your dependencies once in a while.

A simple way to do so is to use go list:

for i in `go list -f '{{range .Imports}}{{. | printf "%s\n"}}{{end}}' github.com/agrarianlabs/... | \grep github | \grep -v agrarianlabs  | sort | uniq`; do echo $i; go get -d -u $i/...; done

One liner to update all dependencies in Go.

This commandline is quite simple:

Go Tools

As we have the tooling, all the following should pass.

goimports

Install: go get golang.org/x/tools/cmd/goimports.

Doc: https://godoc.org/golang.org/x/tools/cmd/goimports. See as well gofmt.

The goimports tool is similar to gofmt but will also handle imports for you. These tools should never complain when running goimports -l (list files with issues).

While the tool is pretty great, it is not perfect.

Formatting Issue

import (
    "net"
    "sort"

    "os"

    "github.com/creack/goproxy"
    "github.com/creack/ehttp"

    "github.com/creack/ehttp/ehttprouter"
)

Bad. Because goimports groups the import statements while keeping the user’s ones, you will often endup in a situation where your import block looks like this.

import (
    "net"
    "os"
    "sort"

    "github.com/creack/goproxy"
    "github.com/creack/ehttp"
    "github.com/creack/ehttp/ehttprouter"
)

Good.

import (
    "net"
    "os"
    "sort"

    "code.google.com/p/uuid"

    "github.com/creack/goproxy"
    "github.com/creack/ehttp"
    "github.com/creack/ehttp/ehttprouter"
)

Also good. This is perfectly fine but should be done in a way where it makes sense.

Because goimports groups the import statements while keeping the user’s ones, you will often end up in a situation where your import block contains extra new lines. This is an issue that can’t be solved automatically by the tool. The import block should be consistent. This does not forbid manual grouping, but it should be done only for external imports.

Import issue

The way goimports works is by looking into your $GOPATH for a package matching the functions/types/variables that you are using without having the imported path.

This is very useful for fast development but can easily backfire when you have multiple packages with the same name in your gopath.

You should always double check the import paths that are automatically added by the tool to make sure that it imported the expected packages.

gofmt -s

This tool comes with Go. Doc: https://golang.org/cmd/gofmt/

goimports is very similar to gofmt, however, it does not support the -s. For this reason, the developer is expected to check the code against both goimports and gofmt -s.

The -s means “simplify”. It will catch code that is not necessary.

Note: While this tool is great, it is not retro compatible with older version of Go. Example: for _ := range []string{}{} would pass in Go1.3 but would fail in 1.4 as it should be for range []string{}{}. This is not a big issue since the 1.4 format would not compile in 1.3.

errcheck

Install: go get github.com/kisielk/errcheck. Doc: https://github.com/kisielk/errcheck/blob/master/README.md

errcheck will analyze your code and make sure that there are no function calls returning an error that the developer missed.

It can be a hassle when you don’t want to check the error like when doing defer elem.Close(), but it is expected.

You should always explicitly check your errors. You might discard some errors, but all error handling should still be explicit and documented. Example:

package main

import (
    "log"
    "os"
)

func main() {
    f, err := os.Open("file")
    if err != nil {
        log.Fatal(err)
    }
    // The error is explicitly discarded and documented.
    defer func() { _ = f.Close() }() // Best effort.
    _ = f
}

go vet

go vet comes with golang. Doc: https://golang.org/cmd/vet/

This will check various common errors like wrong usage of formatting function, misuse of the unsafe package, invalid json tags, etc.

golint

Install: go get github.com/golang/lint/golint . Doc: https://github.com/golang/lint/blob/master/README.md

golint will enforce everything that is not enforced within the specifications.

Partial list: - Enforce comments format - Make sure the acronyms are used properly - Make sure there is no C (or other language) syntax - Enforce the camelCase (from effective go, but not enforced by gofmt) - Redundant naming - Much more

gometalinter

Install: go get github.com/alecthomas/gometalinter; gometalinter --install --update. Doc: https://github.com/alecthomas/gometalinter/blob/master/README.md

Note: this tool is not mandatory, but is always a plus when it does not complain.

gometalinter will call all the tools above and more.

Some of the things it does that other tools does not: - Duplicate code check - Complexity check - Bad variable shadowing check - Much more

Coding style

Go provides fantastic tooling and documentation around the styling and on how to write proper Go code. While those are a good start, they do not handle all the cases and are often a bit too permissive. This document aims to have code that can be easily read and understood by anyone by enforcing stricter rules.

Even with all those awesome tools, there are still some things that are not automatically enforced.

Variable declaration / instantiation

The reason behind this section is to have consistent code across the whole code base.

Go provides multiple ways to instantiate a variable: var, var () and :=. While they are all good, they should be used wisely.

var statement

func test() error {
    var conf Config
    if err := json.Unmarshal(&conf); err != nil {
        return err
    }
    return nil
}
var globalCount int // Note: bad example for production. Should probably be locked.

func main() {
}

The var statement should be used when instantiating a single variable (i.e. not related to others) and when there is no assignement (i.e. use the zero value of the type).

var() block

package main

import "errors"

// Common errors.
var (
    ErrNotFound      = errors.New("not found")
    ErrInvalidFormat = errors.New("invalid format")
    ErrUnexpectedEOF = errors.New("unexpected EOF")
)

func main() {
}

Good. the errors are a single group declared together.

package main

import "errors"

// Common errors.
var ErrNotFound = errors.New("not found")
var ErrInvalidFormat = errors.New("invalid format")
var ErrUnexpectedEOF = errors.New("unexpected EOF")

func main() {
}

Bad. The errors declarations should be grouped. When not grouped, gofmt will not indent properly.

func main() {
    var (
        port = flag.String("p", 0, "port to use")
        host = flag.String("h", "", "host to use")
    )
    flag.Parse()
}

Good. the command-line flags are a single logical group.

The var() block statement should be used when declaring/instantiating related variables.

:= operator

if err := fct(); err != nil {
    return err
}

Good. The error is properly scoped.

func TestText(t *testing.T) {
    text := "abc"
    // ...
    if expect, got := "abc", text; expect != got {
        t.Fatalf("Unexpected text.\nExpect:\t%s\nGot:\t%s", expect, got)
    }
}

Good. text is isolated and we still create an expect variable in the if block.

var i = 0

Bad. Should be either i := 0 or var i int.

var i int

Good.

i := 0

Good if isolated.

var i int
var j int

Bad. “Related” variables should be declared together.

var (
    i int
    j int
)

Good. “Related” variables are in the same declaration block.

var i, j int

Acceptable if isolated and without affectation.

i := 1
j := 2

Acceptable if isolated.

var (
    unrelatedLock sync.Mutex
    i int
    j int
)

Bad. As the lock is not relate to the indexes, it should not be in the same var() block.

var unrelatedLock sync.Mutex
var (
    i int
    j int
)

Good. i and j are grouped, other variables are isolated.

var (
    i int
    j int
)
unrelatedLock := sync.Mutex{}

Also good if there are no other unrelated variables.

i := 0
j := 0
k := 0

Bad. The variabels are grouped. It should be a var() block.

var (
    i int
    j int
    k int
)

Good. The variables are grouped so we declare it in a var() block.

var i, j, k int

Acceptable. For simalar and/or grouped declaration, we can use the , operator.

The main usage of := is to declare and assign a single variable with a non-zero value.

It is also often used when inlining declaration/instantiation inside a scope like an if block.

Even when variables are related, it is acceptable to use :=, but if you have more than 2 statements, it should probably be moved into a var() block.

Type instantiation

type Test struct{}

Type for following examples.

v := new(Test)

Bad, should use literal instead.

v := &Test{}
v2 := Test{}

Good. Whether it is a pointer or not, with initialization or not, we are using literals.

m := make(map[string]string)
s := make([]string, 0)

Bad, should use literal instead.

m := map[string]string{}
s := []string{}

Good. Even when there are no element to initialize with, we are using literals.

s := make([]string, 16)
s2 := make([]string, 0, 16)

Good when needed, no other choice.

ch := make(chan struct{})
ch2 := make(chan struct{}, 1)

Good. No other choice.

type Test2 struct{
    i *int
}

tt := &Test2{i: new(int)}

Acceptable for native types when needed. Not acceptable with custom types, should use literal instead.

Between new, make and literal, it can be confusing how to instantiate a type.

For consistency, we will not be using new nor make unless in a very specific situation:

Scope

func test() error {
    var conf Config

    buf, err := json.Marshal(conf)
    if err != nil {
        log.Println(err)
    }

    err = json.Unmarshal(buf, &conf)
    if err != nil {
        log.Println(err)
    }
    // If the `Marshal` failed, here, `err` will have the value of `Unmarhsal` even if it didn't fail.
    // Scoping it within the `if` with `:=` would isolate the values.

    if err = json.Unmarshal(buf, &conf); err != nil {
        log.Println(err)
    }
    // On this example, the error is scoped, however, it still does not help, we should have used `:=` instead of `=`.
}

Example (bad)

The reason behind this section is to avoid unexpected variable assignment. That way, all variable are scopped to the smallest possible block.

Reflect

The reflect package can be a great tool, but it is also the source of all evil. Unless you don’t have the choice, don’t use reflect.

It can be acceptable to use reflect.DeepEqual in tests when it makes sense.

Do not ever use reflect.DeepEqual if you don’t need it, i.e. don’t do if reflect.DeepEqual(21, 42) {}. Prefer if 21 == 42 {}.

Defer

var (
    l sync.Mutex
    m = map[string]string{}
)

func heavilyUsedFunction() {
    l.Lock()
    defer l.Unlock()

    m["hello"] = "world"
}

Bad. Small operation, defering the unlock slows down the function.

var (
    l sync.Mutex
    m = map[string]string{}
)

func heavilyUsedFunction() {
    l.Lock()
    m["hello"] = "world"
    l.Unlock()
}

Good. Small operation, not defering makes it much faster. NOTE: Calling l.Unlock without a defer would not be executed in case of a panic.

buf := &bytes.Buffer{}
tw := tar.NewWriter(buf)
defer tw.Close()

Bad, f.Close() returns an error that is not checked. errcheck tool will complain. In this case, the Close() would write the footer of the archive so it is very important to check. NOTE: In tests, defers like this are acceptable when you want to discard the error.

f, err := os.Open("file")
if err != nil {
    return err
}
defer func() { _ = f.Close() }() // Best effort.

Good. Even when discarding the error, we are explicit about it.

Defer statements are very useful, however, you need to be careful when using them.

You need to keep in mind that a defer induces a closure, which might impact the performances of your code. Also, defering a statement is no excuse not to check the error value returned.

Panic

Don’t panic. Ever.

If you need to handle errors during init, prefer Fatalf as the stack trace would not be meaningful, anywhere else in the code, you should return the error or send it via a channel if it is in a goroutine.

The exception for this is in the init() functions of libraries where you might have to use a different logger that your own. In this case, it is best to use panic() in the init.

Named return parameters

func getUser() (string, string, string, int, error) {
    return "Guillaume", "user@domain.com", "Leaf, LLC", 1, nil
}

Bad. The prototype is not explicit enough for documentation.

func getUser() (name, email, company string, uid int, err error) {
    name, email, company, uid, err = "Guillaume", "user@domain.com", "Leaf, LLC", 1, nil
    return
}

Bad. Don’t use naked returns.

func getUser() (name, email, company string, uid int, err error) {
    return "Guillaume", "user@domain.com", "Leaf, LLC", 1, nil
}

Good. The documentation is clear and the return is correct.

func check() (err error) {
    return nil
}

Bad. Don’t use named return when not needed. In this case, having err in the prototype does not brind any value.

func check() error {
    return nil
}

Good. The prototype is self-describing, not using named return.

func check() (err error) {
    defer func() {
        if err != nil {
            // TODO: do something
            return
        }
        if e1 := cleanup(); e1 != nil {
            err = e1
        }
    }
}

Good. The named return parameter is not needed for documentation but makes the error check / set in the defer possible.

Named returns are mainly used for documentation purpose. When a prototype is not explicit enough, it might be interesting to add named returns.

An other situation where it is acceptable to use named returns is to handle error in the defer.

Embedded structures

type Test struct {
    a int
    *Controller
}

Bad. The embedded struct should be the first element.

type Test struct {
    *Controller
    a int
}

Good.

When using embedded structures, they should be the first thing in the “parent” structure.

JSON tags

If you have a structure that will be marshalled to json, it should be explicitly tagged.

Not doing so and relying on Go for the naming will cause issues and conflicts for retro-compatibility. Even if the json name is the same as the field name, it should be explicitly written.

Same idea applies to any other tags like db, xml, yaml, etc..

Import Dot

Even though the Golang’s CodeReviewComments allows it, it is meant for handling circular dependency issues.

You should not use . import. It makes the code much more difficult to read and understand. Your code should not have circular dependency issues anyway.

Import Rename

import (
    "fmt"
    "log"
    "gopkg.in/mgo.v2"
)

Bad. The import path does not match the package name.

import (
    "fmt"
    "log"
    mgo "gopkg.in/mgo.v2"
)

Good. We rename the import with the package name. This does not impact the code, but make it possible to use tag lookup.

When importing multiple package with the same name, you have to rename one of them. When doing so, the name should be short, similar to the original one and make sense. It also need to be camelCase if it is longer.

To make it easier for people using tools like gocode on their editor, we also force the import rename of package name not matching the import path.

Naming conventions

Golang

Golang (also called Go) uses camelCase. golint will validates names. Don’t use snake_case.

Constants should follow the same rules and not be all upper case like in C or other languages.

JSON

When using json, we are using snake_case.

Database

In databases, we are using snake_case as well with plural names for tables.

The primary key, when unique is expected to be the singular version of the table name suffixed with _id.

Example:

Format

The database names format (tables and fields) should be snake_case.

Table name

CREATE TABLE users (
)

The table names should be plural.

Primary key

CREATE TABLE users (
    user_id   SERIAL PRIMARY KEY,
)

The primary key of a table should be the singular name of the table suffixed with _id.

Infrastructure

The goal of the infrastructure is to be scalable and reliable.

In order to accomplish this, we are using tools and services like Docker, Tutum or AWS on the infrastructure side, but what really helps is the concept of micro services.

We are going to develop a serie of micro service with dedicated tasks. Those unit will be updated and scaled individually, which means that even during an upgrade, we will always have a service up and running.

The general idea is to have something like this:

alt text

Global Architecture

The infrastructure runs on Amazon Web Services, a.k.a. AWS.

AWS allows us to configure the network in a way that allows public access only via the load balancer (ELB). To do so, we are using the VPC and Security Group from EC2.

The idea being to have something like this:

alt text diagram

Using the security group, we grant exta access to specific IPs like the office.

As we want to have testing and staging environments we need to replicate this schema. In order to isolate environements from each other, we are using VPC from EC2.

VPCs

VPCs or Virtual Private Clouds are an AWS unit that groups servers together in a given subnet(s). It allows us to isolate our clusters at a network level.

Because the CI / Build server needs certificate to pull code and push to tutum, it is isolated in its own VPC and can’t communicate with any service directly. This require a dedicated security group.

alt text

Security Groups

Security Groups are the “firewall rules” for a given VPC. Because security groups are scoped by VPC, we have some duplicate settings for testing, staging and production.

alt text

Add yourself to a group

You need access to the AWS console to add yourself to a group.

From the AWS console, navigate to EC2 then Security Groups. Once there, select the group you are looking for. If at home, use the “untrusted” networks, at the office, we can use the “trusted” ones. This allows us to control and easily cleanup the access list. On the security group you are looking for, select the “Inbound” tab and “Edit” to add your IP to the given port.

Docker / Deployment

Docker

Tutum

Services, Stack, Node, Cluster

Tutum has some top level concepts.

ECS, Elastic Beanstalk, Others.

Before chosing Tutum, we tried several solutions.

ECS: very difficult to use, manual cluster management EB: difficult to use, lot of overhead, lot of AWS services involded, annoying deployment process, specific DSLs to learn. Fleet: not reliable enough RancherOS: forces us to use their discovery system and OS Kubernete: way overcomplicated, too manyy moving parts Mesos: too heavy, does too much, stip learning curve. OpenShift: too heavy, does too much, stip learning curve.

Router / Discovery

Configuration management

For configuration management, at the moment, we are using Zookeeper. The main reason for this choice is the reliability of it and the ease of use from the driver.

We eventually will migrate to Etcd or more likely Consul.

Continuous Integration

We are usnig Jenkins as our CI. NOTE: Jenkins is now deprecated and being replaced by CircleCI.

Because everything runs on Docker, there is no special configuration for it. We just need Docker, git and make.

alt text diagram

Github configuration

In order to hook a Github repository to Jenkins, we need to go to the repo’s settings, Webhooks & services tab. From there we are going to add a new service: "Jenkins (Github plugin)”.

The hook url is: http://jenkins.leaf.ag:8080/github-webhook/

alt text

Security Group

As Github needs to have access to Jenkins to trigger the builds, we need to grant Github access. We need to add the following ips on tcp/8080: (doc):

Service Discovery

alt text diagram

Events Topology

The following diagram indicates the types of events that flow through the system, who produces them, and who consumes them.

alt text