Case: Classification

Published August 3, 2026

Authentication

Create an access credential from My PhenoNet → API Access. Send it with every request:

http
Authorization: AccessKey <access_id>:<secret_key>

Keep the secret key on your server. Do not expose it in browser code or a public repository.

Submit a classification task

POST https://api.phenonet.org/v1/openapi/classification/

Send a JSON request body. image_url must be an HTTPS URL from an image host allowed by the platform.

Field Required Description
image_url Yes HTTPS URL of the image to classify.
task_name No A name for this task. Defaults to API prediction.
model_id No Available single-image model ID. The platform default is used when omitted.
json
{
  "image_url": "https://files.example.org/images/wheat-001.jpg",
  "task_name": "wheat-001",
  "model_id": "your-model-id"
}

A successful submission returns HTTP 202 and a server-generated task_id:

json
{
  "code": 202,
  "msg": "accepted",
  "data": {
    "task_id": "server-generated-task-id",
    "status": "queued",
    "status_url": "https://api.phenonet.org/v1/openapi/classification/server-generated-task-id/",
    "created_at": "2026-08-03T00:00:00+00:00",
    "finished_at": null
  }
}

Get task status

GET https://api.phenonet.org/v1/openapi/classification/{task_id}/

The response status is one of queued, running, waiting, succeeded, or failed. When it succeeds, data.result contains the predicted stage and its index.

Python example

python
import time

import requests

BASE_URL = "https://api.phenonet.org/v1/openapi/classification/"
ACCESS_ID = "your-access-id"
SECRET_KEY = "your-secret-key"

headers = {
    "Authorization": f"AccessKey {ACCESS_ID}:{SECRET_KEY}",
}

payload = {
    "image_url": "https://files.example.org/images/wheat-001.jpg",
    "task_name": "wheat-001",
    # "model_id": "your-model-id",  # Optional.
}

created = requests.post(BASE_URL, headers=headers, json=payload, timeout=30)
created.raise_for_status()
task = created.json()["data"]
task_id = task["task_id"]

while task["status"] not in {"succeeded", "failed"}:
    time.sleep(5)
    response = requests.get(f"{BASE_URL}{task_id}/", headers=headers, timeout=30)
    response.raise_for_status()
    task = response.json()["data"]

if task["status"] == "succeeded":
    print(task["result"])
else:
    print("Task failed:", task)

Error responses

HTTP status Meaning
400 The request body is invalid, contains an unexpected field, or the image URL is not allowed.
401 The access credential is missing or invalid.
404 The task does not exist or does not belong to this credential.
409 Task dispatch is already in progress.
503 The compute service did not accept the task.