Introduction
Welcome to the Companion API! You can use our REST API to access Companion API endpoints, which can get information on observations in our database.
You can view code examples in PHP and C# in the dark area to the right.
Replace {{SERVER_PREFIX}}
in the described webservices by the right value (depending on the server you are requesting):
- Stage server prefix: https://companion-stg.labs.smag.tech
- Live server prefix: https://companion.smag.tech
Please refer to your point of contact if you have any problem.
Authentication
Companion uses JSON Web Token (JWT) authentication. Companion expects for a JWT to be included in all API requests to the server in a header that looks like the following.
Authorization: Bearer myjwttoken
See how you can generate your JWT below.
Please note that the algorithm used to sign the token is HMAC-SHA256.
Generate JWT
// package NuGet jose-jwt is used here
string payload = JsonConvert.SerializeObject(
new {
iss = "your_api_key", // TODO replace value with your credentials
iat = DateTimeOffset.ToUnixTimeSeconds() // current timestamp
}
);
string jwt = Jose.JWT.Encode(
payload,
System.Text.UTF8Encoding.Default.GetBytes(
"PleaseKeepItSecret!" // TODO replace value with your credentials
),
JwsAlgorithm.HS256
);
// In this example,
// jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ5b3VyX2FwaV9rZXkiLCJpYXQiOjE1MTYyMzkwMjJ9.hBBy96qEfmEW9OJyaOU5Lcbahszst8KEXFaxlbcvrJk"
<?php
use \Firebase\JWT\JWT; // The following code works with firebase/php-jwt
$payload = [
'iss' => 'your_api_key', // TODO replace value with your credentials
'iat' => time() // current timestamp
];
$jwt = JWT::encode(
$payload,
'PleaseKeepItSecret!', // TODO replace value with your credentials
'HS256'
);
// In this example,
// $jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ5b3VyX2FwaV9rZXkiLCJpYXQiOjE1MTYyMzkwMjJ9.81E1KKRWJk92Qxo6o5sqPk-b583QSfKcbhE0cxsgzy8"
?>
There are three parameters you will need to define to generate a JWT.
The two following data have to be put in what is called the payload, it enables Companion API to identify the access rights for the JWT.
Parameter | Description |
---|---|
iss | "Issuer": Your api key provided by your point of contact |
iat | "Issued at": Timestamp (unix time) identifying the time at which the JWT was issued (you should set it to current timestamp when generating JWT) |
Then you need to use your secret key provided by your point of contact.
Following the previous indications, you can follow the example on the dark area to generate your JWT.
Your JWT should look like the following: xxxxx.yyyyy.zzzzz
Referential
Crops
The request returns JSON structured like this:
[
{
"crop_code": "1101",
"crop_name": "Orge",
"eppo_code": "HORVX",
"crop_picture_path": "https://companion.smag.tech/images/images/crops/barley.jpg",
"pests": null,
"seeds": null,
"stages": null
},
{
"crop_code": "1112",
"crop_name": "Blé tendre d'hiver",
"eppo_code": "TRZAW",
"crop_picture_path": "https://companion.smag.tech/images/images/crops/sww.jpg",
"pests": null,
"seeds": null,
"stages": null
}
]
HTTP Request
GET {{SERVER_PREFIX}}/api/v1/crops
Headers
Key | Prefix | Format | Description |
---|---|---|---|
Authorization | Bearer | Authorization: Bearer myjwttoken |
myjwttoken should be replaced by the JWT generated previously. |
Response
Name | Description |
---|---|
crop_code | Crop code in Companion Example: 1112 |
crop_name | Crop name Example: Wheat |
eppo_code | EPPO code Example: TRZAW |
crop_picture_path | Absolute URL to crop picture |
pests | null (used for other webservices) |
seeds | null (used for other webservices) |
stages | null (used for other webservices) |
Pests
The request returns JSON structured like this:
[
{
"crop_code": "1101",
"crop_name": "Orge",
"eppo_code": "HORVX",
"crop_picture_path": "https://companion.smag.tech/images/images/crops/barley.jpg",
"pests": [
{
"pest_code": "00048",
"pest_name": "Fusariose ",
"pest_picture_path": "https://companion.smag.tech/images/images/pests/barley_fusariose_icon.jpg"
},
{
"pest_code": "00055",
"pest_name": "Helminthosporiose ",
"pest_picture_path": "https://companion.smag.tech/images/images/pests/barley_helminthosporiose_icon.jpg"
}
],
"seeds": null,
"stages": null
}
]
HTTP Request
GET {{SERVER_PREFIX}}/api/v1/pests
Headers
Key | Prefix | Format | Description |
---|---|---|---|
Authorization | Bearer | Authorization: Bearer myjwttoken |
myjwttoken should be replaced by the JWT generated previously. |
Response
Pests are grouped by crops, so the results have arrays of pests inside of of arrays of crops.
Name | Description |
---|---|
crop_code | Crop code in Companion Example: 1112 |
crop_name | Crop name Example: Wheat |
eppo_code | EPPO code Example: TRZAW |
crop_picture_path | Absolute URL to crop picture |
pests | See below |
seeds | null (used for other webservices) |
stages | null (used for other webservices) |
Pests elements are filled with:
Name | Description |
---|---|
pest_code | Pest code in Companion Example: BASF39 |
pest_name | Pest name Example: Oidium (Leaves) |
pest_picture_path | Absolute URL to pest picture |
Seeds
The request returns JSON structured like this:
[
{
"crop_code": "1101",
"crop_name": "Orge",
"eppo_code": "HORVX",
"crop_picture_path": "https://companion.smag.tech/images/images/crops/barley.jpg",
"pests": null,
"seeds": [
{
"seed_id": 1,
"seed_name": "06 JS 206",
"gnis_code": "515C760"
},
{
"seed_id": 2,
"seed_name": "091027-526",
"gnis_code": "515B386"
},
{
"seed_id": 3,
"seed_name": "093028-521",
"gnis_code": "515B383"
}
},
"stages": null
}
]
HTTP Request
GET {{SERVER_PREFIX}}/api/v1/seeds
Headers
Key | Prefix | Format | Description |
---|---|---|---|
Authorization | Bearer | Authorization: Bearer myjwttoken |
myjwttoken should be replaced by the JWT generated previously. |
Response
Seeds are grouped by crops, so the results have arrays of seeds inside of of arrays of crops.
Name | Description |
---|---|
crop_code | Crop code in Companion Example: 1112 |
crop_name | Crop name Example: Wheat |
eppo_code | EPPO code Example: TRZAW |
crop_picture_path | Absolute URL to crop picture |
pests | null (used for other webservices) |
seeds | See below |
stages | null (used for other webservices) |
Seeds elements are filled with:
Name | Description |
---|---|
seed_id | ID of the seed related to the pest Can be null. |
seed_name | Name of the seed related to the pest Example: ALIGATOR Can be null. |
gnis_code | GNIS code Can be null. |
Growth stages
The request returns JSON structured like this:
[
{
"crop_code": "1101",
"crop_name": "Orge",
"eppo_code": "HORVX",
"crop_picture_path": "https://companion.smag.tech/images/images/crops/barley.jpg",
"pests": null,
"seeds": null,
"stages": [
{
"stage_code": "1",
"stage_bbch": "0",
"stage_name": "Pré-semis",
"stage_order": 10
},
{
"stage_code": "2",
"stage_bbch": "1",
"stage_name": "Pré-levée",
"stage_order": 20
}
]
}
]
HTTP Request
GET {{SERVER_PREFIX}}/api/v1/stages
Headers
Key | Prefix | Format | Description |
---|---|---|---|
Authorization | Bearer | Authorization: Bearer myjwttoken |
myjwttoken should be replaced by the JWT generated previously. |
Response
Stages are grouped by crops, so the results have arrays of stages inside of of arrays of crops.
Name | Description |
---|---|
crop_code | Crop code in Companion Example: 1112 |
crop_name | Crop name Example: Wheat |
eppo_code | EPPO code Example: TRZAW |
crop_picture_path | Absolute URL to crop picture |
pests | null (used for other webservices) |
seeds | null (used for other webservices) |
stages | See below |
Stages elements are filled with:
Name | Description |
---|---|
stage_code | Crop's growth stage code in Companion Can be null. |
stage_bbch | BBCH code |
stage_name | Crop's growth stage name Example: 1 node Can be null. |
stage_order | Order in crop |
Metos
The request returns JSON structured like this:
[
{
"meto_code": 4,
"meto_name": "Sur 20 pieds, combien sont concernés ?",
"meto_unit": "Pied(s) concerné(s) sur 20 pieds observés.",
"meto_unit_short": null
},
{
"meto_code": 10,
"meto_name": "Sur 10 siliques, combien sont touchées ?",
"meto_unit": "Silique(s) touchée(s) sur 10 siliques observées.",
"meto_unit_short": null
}
]
HTTP Request
GET {{SERVER_PREFIX}}/api/v1/metos
Headers
Key | Prefix | Format | Description |
---|---|---|---|
Authorization | Bearer | Authorization: Bearer myjwttoken |
myjwttoken should be replaced by the JWT generated previously. |
Response
Name | Description |
---|---|
meto_code | Meto code in Companion |
meto_name | Meto name |
meto_unit | Unit |
meto_unit_short | Short unit used in expert protocol. Can be null. |
Notas
The request returns JSON structured like this:
[
{
"nota_code": -28,
"nota_name": "Attaque forte"
},
{
"nota_code": 14,
"nota_name": "1 à 9"
}
]
HTTP Request
GET {{SERVER_PREFIX}}/api/v1/notas
Headers
Key | Prefix | Format | Description |
---|---|---|---|
Authorization | Bearer | Authorization: Bearer myjwttoken |
myjwttoken should be replaced by the JWT generated previously. |
Response
Name | Description |
---|---|
nota_code | Nota code in Companion |
nota_name | Nota name |
Observations
Get All Observations
The request returns JSON structured like this:
[
{
"id": 57174,
"observation_date": "2019-05-15T10:10:56",
"latitude": 45.6885045,
"longitude": 4.7677997,
"postal_code": "69540",
"city": "Irigny",
"user_id": 10053,
"user_email": "AnonUser10053@gmail.com",
"username": "AnonUser10053",
"user_profession": "GROWER",
"user_photo_path": null,
"crop_code": "1112",
"crop_name": "BTH",
"eppo_code": "TRZAW",
"crop_picture_path": "https://companion.smag.tech/images/crops/sww.jpg",
"seed_id": null,
"seed_name": null,
"gnis_code": null,
"sowing_date": null,
"growthstage_code": 4,
"growthstage_name": "3 feuilles",
"growthstage_picture_path": "https://companion.smag.tech/images/images/growthstages/sww_3leaves_out.jpg",
"pest_code": "BASF16",
"pest_name": "Cicadelles",
"pest_picture_path": "https://companion.smag.tech/images/pests/sww_cicadelle_icon.jpg",
"is_expert_protocol": true,
"responses": [
{
"meto_code": 112,
"meto_name": "Quelle est la classe majoritaire ?",
"meto_unit": null,
"notas": [
{
"characteristic": "",
"nota_code": -10,
"nota_name": "Limaces noires jeunes"
}
]
},
{
"meto_code": 113,
"meto_name": "Sur 10 plantules successives de 5 lignes de semis différentes, quel est % de plantules attaquées ?",
"meto_unit": "% de plantules attaquées",
"notas": [
{
"characteristic": "",
"nota_code": 0,
"nota_name": "7"
}
]
},
{
"meto_code": 180,
"meto_name": "Quelle est la somme des 4 comptages de piège INRA ? (Nombre / m²)",
"meto_unit": "Nombre / m²",
"notas": [
{
"characteristic": "[Grises - jeunes (<1 cm)]",
"nota_code": 0,
"nota_name": "73"
},
{
"characteristic": "[Grises - adultes]",
"nota_code": 0,
"nota_name": "66"
},
{
"characteristic": "[Noires - jeunes (<1 cm)]",
"nota_code": 0,
"nota_name": "50"
},
{
"characteristic": "[Noires - adultes]",
"nota_code": 0,
"nota_name": "70"
},
{
"characteristic": "[Autres - jeunes (<1 cm)]",
"nota_code": 0,
"nota_name": "0"
},
{
"characteristic": "[Autres - adultes]",
"nota_code": 0,
"nota_name": "68"
}
]
}
],
"risk_level": 1,
"comment": null,
"photo_path": null
},
{
"id": 57175,
"observation_date": "2019-05-16T15:10:56",
"latitude": 45.6885045,
"longitude": 4.7677997,
"postal_code": "69540",
"city": "Irigny",
"user_id": 10053,
"user_email": "AnonUser10053@gmail.com",
"username": "AnonUser10053",
"user_profession": "GROWER",
"user_photo_path": null,
"crop_code": "1112",
"crop_name": "BTH",
"eppo_code": "TRZAW",
"crop_picture_path": "https://companion.smag.tech/images/crops/sww.jpg",
"seed_id": 1905,
"seed_name": "ULI 12",
"gnis_code": "",
"sowing_date": "2019-05-16T15:11:02",
"growthstage_code": 31,
"growthstage_name": "Début tallage",
"growthstage_picture_path": "https://companion.smag.tech/images/growthstages/sww_tillering.jpg",
"pest_code": "BASF16",
"pest_name": "Cicadelles",
"pest_picture_path": "https://companion.smag.tech/images/pests/sww_limace_icon.jpg",
"pest_code": "15774",
"pest_name": "Limaces / escargots",
"is_expert_protocol": false,
"responses": [
{
"meto_code": 26,
"meto_name": "Sur 10 feuilles, combien sont touchées ?",
"meto_unit": "Feuille(s) touchée(s) sur 10 feuilles observées.",
"notas": [
{
"characteristic": "",
"nota_code": 43,
"nota_name": "1 à 3"
}
]
}
],
"risk_level": 2,
"risk_level": 1,
"comment": null,
"photo_path": null
}
]
This endpoint retrieves all observations that you can access.
HTTP Request
GET {{SERVER_PREFIX}}/api/v1/observations
Headers
Key | Prefix | Format | Description |
---|---|---|---|
Authorization | Bearer | Authorization: Bearer myjwttoken |
myjwttoken should be replaced by the JWT generated previously. |
Query Parameters
All parameters are optional.
Parameter | Description |
---|---|
fromDate | Format: yyyyMMdd . If defined, observations made before the fromDate won't be returned. |
toDate | Format: yyyyMMdd . If defined, observations made after the toDate won't be returned. |
Response
Name | Description |
---|---|
id | |
observation_date | Date when observation was made Format: yyyy-MM-dd'T'HH:mm:ss |
latitude | Location's latitude of the observation |
longitude | Location's longitude of the observation |
postal_code | Postal code of the observation |
city | City of the observation |
user_id | User ID who made the observation |
user_email | User email |
username | Username in Companion |
user_profession | User's profession Possible values: GROWER, CROP_ADVISOR, OTHER. |
user_photo_path | Absolute URL to user profile photo Can be null if user does not have a profile photo. |
crop_code | Crop code in Companion Example: 1112 |
crop_name | Crop name Example: Wheat |
eppo_code | EPPO code Example: TRZAW |
crop_picture_path | Absolute URL to crop picture |
seed_id | ID of the seed related to the pest Can be null. |
seed_name | Name of the seed related to the pest Example: ALIGATOR Can be null. |
gnis_code | GNIS Code Can be null. |
sowing_date | Sowing date Format: yyyy-MM-dd'T'HH:mm:ss |
growthstage_code | Crop's growth stage code in Companion Can be null. |
growthstage_name | Crop's growth stage name Example: 1 node Can be null. |
growthstage_picture_path | Absolute URL to growth stage picture Can be null. |
pest_code | Pest code in Companion Example: BASF39 |
pest_name | Pest name Example: Oidium (Leaves) |
pest_picture_path | Absolute URL to pest picture |
risk_level | Value from 0 to 3 (lowest to highest). Example: 2 Can be null. |
comment | Comment made by the user Can be null if user has not posted any comment. |
photo_path | Absolute URL to the observation picture Can be null if user has not taken any photo. |
is_expert_protocol | Indicates whether the observation was made with Companion PRO expert function |
responses | List of values set by user. Each question is structured with Meto structure |
Meto structure
Name | Description |
---|---|
meto_code | Methodology code in Companion Example: 4 Can be null. |
meto_name | Methodology (usually a question). Example: Out of 20 stalks, how many are affected ? Can be null. |
meto_unit | Methodology unit. Example: Affected plant base(s) out of 20 observed bases. Can be null. |
notas | List of answers for the question. Each answer is structured with Nota structure |
Nota structure
Name | Description |
---|---|
characteristic | Useful when the question is for several characteristics. Empty if the question does not affect different characteristics. |
nota_code | Nota code in Companion Example: 14 = 0 if no nota code associated (often when in expert protocol). |
nota_name | Notation value (according to methodology). Example: 1 to 9 Can be null. |
Errors
Companion API uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx
range indicate success. Codes in the 4xx
range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc.). Codes in the 5xx
range indicate an error with Stripe's servers (these are rare).
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. This error has different reasons: - Token could not be read - Wrong api key in token (which means your api key is not found in Companion database) - Bad token (which means your JWT generated seems not good, please ensure you use the right secret key) - Expired token - fromDate does not conform to expected format : "yyyyMMdd" - toDate does not conform to expected format : "yyyyMMdd" |
401 | Unauthorized -- Your authorization key is wrong. |
403 | Forbidden -- The access to the endpoint requires specific rights. You can also have this error the case you have tried to call our API at least 10 times during the last hour. |
429 | Too Many Requests -- You're requesting the server too many times! Slow down! |
500 | Internal Server Error -- We had a problem with our server. Try again later or refer to your point of access. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |