Image diagnosis on the live FildraAI API with honest endpoint status and audience boundaries

The legacy synchronous /api/v1/diagnose gateway has been retired. The active image-diagnosis path is async: POST /api/v1/image_diagnosis/infer/basic returns HTTP 202 with a job_id; clients poll GET /api/v1/ml/jobs/{job_id} for status and /result once complete. Raw-key image diagnosis, metadata, ML crop recommendation, and map overview routes are validated in production.

base: https://api.fildraai.com
user and service key audiences
4 diagnosis crops
raw-key routes validated

API Reference

Production endpoint status

Use this page as the current integration contract, not placeholder documentation. It separates file-upload routes from staged-image routes and calls out what was actually observed on the live API.

POST /api/v1/image_diagnosis/infer/basic

Active user-key image-diagnosis endpoint, replacing the retired synchronous /api/v1/diagnose gateway. Returns HTTP 202 with a job_id; poll GET /api/v1/ml/jobs/{job_id} for status and /result once the inference completes.

Authentication
X-Api-Key: YOUR_API_KEY
Alternative: Authorization: Bearer YOUR_API_KEY
Base URL
https://api.fildraai.com
Audience
Active production route for user-key clients. Returns HTTP 202 with a job_id; poll the job endpoints below for status and result.
Request Method
POST with multipart/form-data
File Upload
Form field: image (binary file data)
Query Parameters
plant (required), top_k (optional), locale (optional)
Supported Plants
cassava, maize, rice, tomato
Locale Resolution
Priority: ?locale=...Accept-Languageen-us
Query parameter takes priority if both are set

Query Parameters

Parameter Type Required Description
plant String Yes Plant type to diagnose. Must be one of: cassava, maize, rice, tomato.
top_k Integer No Number of predictions to return. Accepted range is 1–10. If omitted, the service uses 3.
locale String No Preferred response locale. Common examples include en-us and zh-tw. Unsupported values are rejected by the diagnosis service.
Implementation note: this is the active public user-key endpoint, which replaced the retired synchronous /api/v1/diagnose gateway. It is different from raw-key inference routes used by trusted server-side pipelines that already stage images in storage. Returns HTTP 202 with a job_id; clients poll GET /api/v1/ml/jobs/{job_id} for status and /result for the diagnosis.

Additional Diagnosis Paths

Staged-image diagnosis routes

These endpoints diagnose images that are already staged in storage. Production validation on May 13, 2026 returned 200 for both user keys and server keys. Server-side products should still keep raw storage keys and API secrets on the backend, not in browsers or mobile clients.

POST /api/v1/image_diagnosis/infer/basic

Use this when your backend already has a staged object key. The request body is JSON and the response returns ranked predictions with Grad-CAM URLs but without knowledge enrichment.

Field Type Required Description
plantStringYescassava, maize, rice, or tomato.
raw_keyStringYesPreviously staged storage key, for example uploads/diagnose/user-123/maize/sample.jpg.
localeStringNoResponse locale. Falls back to request locale handling when omitted.
job_idStringNoOptional caller-supplied correlation id. Generated server-side if omitted.
top_kIntegerNoPrediction count. Defaults to 3, capped at 10.
countryStringNoReserved for future geographic filtering and logging.
POST /api/v1/image_diagnosis/infer/with_knowledge

This is the knowledge-backed variant of raw-key diagnosis. It returns the same prediction core plus a knowledge object per prediction, with section filtering and resolved citations already embedded where applicable.

Field Type Required Description
plantStringYesCrop scope for inference and profile resolution.
raw_keyStringYesStaged object key for the image already stored by your backend flow.
sectionsList of strings or CSV stringNoProfile sections to keep. Examples: ["visual_profile","lookalikes"] or "visual_profile,decision_support".
lookalikesBooleanNoAlias flag that expands to the matching section set.
visual_profileBooleanNoAlias flag for visual explanation sections.
decision_supportBooleanNoAlias flag for management guidance sections.
Allowed sections: cause, linkage, model_integration, visual_profile, lookalikes, decision_support, progression_profile, geographic_applicability, assistant_contract, evidence, evidence_summary, data_quality, validation_warnings.

Usage & Limits

Credits and runtime limits

API-key billing is credit-based. Playground usage is enforced by the backend identity service and is separate from developer API-key credits.

Guest playground
Backend managed
Guest playground requests are signed for backend allowance checks. The website no longer stores authoritative guest counters in the Flask session.
Authenticated playground
Backend managed
Authenticated playground requests use signed identity headers. The account page treats playground usage as informational until a backend status endpoint is wired in.
API key quota
50 included API credits / month
Paid API top-up credits are available after the included monthly API allowance is exhausted.

How usage is calculated

  • Guest and authenticated playground windows are separate from API key usage.
  • Playground quota enforcement lives in the API backend, not in the website billing table.
  • Included API credits are counted against the current calendar month; paid top-up credits do not reset monthly.
  • Clients should handle authentication, quota, and validation failures explicitly rather than assuming every non-200 response is transient.
API credit access: the public top-up anchor is now US$3 for 20 API credits. Standard API calls cost 1 credit, image diagnosis costs 2 credits, and heavier premium workflows can cost more.

Code Examples

Integration Examples

Use live production URLs. Do not replace the host with a placeholder domain, and do not send service keys to browsers or mobile clients.

cURL, Basic Request
# Active user-key endpoint. Returns HTTP 202 with a job_id; poll job endpoints for the result.
curl -X POST "https://api.fildraai.com/api/v1/image_diagnosis/infer/basic?plant=rice&top_k=3&locale=en-us" \
  -H "X-Api-Key: YOUR_USER_API_KEY" \
  -F "image=@/absolute/path/to/rice_leaf.jpg"
Python, Raw-Key Basic Inference
# Server-side inference when the image is already staged in storage
import requests

base_url = "https://api.fildraai.com"
api_key = "YOUR_SERVER_API_KEY"

url = f"{base_url}/api/v1/image_diagnosis/infer/basic"
payload = {
    "plant": "rice",
    "raw_key": "uploads/diagnose/some-user/rice/some-file.jpg",
    "locale": "en-us",
    "job_id": "demo-job-001",
    "top_k": 3,
    "country": "zambia"
}
headers = {
    "X-Api-Key": api_key,
    "Content-Type": "application/json"
}

response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()

result = response.json()
print(result)
JavaScript, Knowledge-Enriched Diagnosis
// Server-side diagnosis + filtered knowledge sections
async function diagnoseWithKnowledge(rawKey) {
  const response = await fetch("https://api.fildraai.com/api/v1/image_diagnosis/infer/with_knowledge", {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': 'YOUR_SERVER_API_KEY'
    },
    body: JSON.stringify({
      plant: 'tomato',
      raw_key: rawKey,
      locale: 'en-us',
      top_k: 2,
      sections: ['visual_profile', 'lookalikes', 'decision_support'],
      lookalikes: true
    })
  });

  return await response.json();
}

Send an image directly (multipart upload)

The examples above use raw_key, the server-side path. If your client has the image file in hand (a mobile app, a script, or Postman), use the multipart upload form below instead. The API accepts the file under the image form field plus a plant form field or ?plant= query parameter.

Python, Multipart Upload (requests)
import requests

url = "https://api.fildraai.com/api/v1/image_diagnosis/infer/basic"
headers = {"X-Api-Key": "YOUR_USER_API_KEY"}

# `files` triggers multipart/form-data automatically.
# `data` carries non-file form fields alongside the upload.
with open("/absolute/path/to/maize_leaf.jpg", "rb") as fh:
    response = requests.post(
        url,
        headers=headers,
        data={"plant": "maize", "locale": "en-us", "top_k": 3},
        files={"image": ("maize_leaf.jpg", fh, "image/jpeg")},
        timeout=60,
    )

response.raise_for_status()
print(response.json())
JavaScript, Multipart Upload (fetch + FormData)
// Works in browsers and Node 18+ (built-in fetch + FormData).
// `fileInput` is <input type="file">, use the first selected file.
async function diagnoseImage(file) {
  const form = new FormData();
  form.append('image', file, file.name);
  form.append('plant', 'maize');
  form.append('locale', 'en-us');
  form.append('top_k', '3');

  const response = await fetch(
    'https://api.fildraai.com/api/v1/image_diagnosis/infer/basic',
    {
      method: 'POST',
      headers: { 'X-Api-Key': 'YOUR_USER_API_KEY' },
      // IMPORTANT: do NOT set Content-Type, the browser sets the
      // correct multipart boundary automatically when you pass FormData.
      body: form,
    }
  );

  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
}

Test in Postman

Postman is the fastest way to verify your API key and image work before wiring up code. The five steps below mirror what the Python and JavaScript snippets do above.

  1. Create a new request. Method POST, URL https://api.fildraai.com/api/v1/image_diagnosis/infer/basic.
  2. Add the API key header. Under the Headers tab, add X-Api-Key with your user-audience key as the value.
  3. Switch the body to multipart. Under the Body tab, select form-data (not raw / x-www-form-urlencoded).
  4. Add the image and form fields. Create a key called image, hover the right edge of the key cell, change its type from Text to File, then pick your JPEG. Add four more text rows: plant=maize, locale=en-us, top_k=3.
  5. Send it. A successful response returns 200 with a predictions array. Common failures: 401 (key missing/wrong), 403 (key audience or scope mismatch), 400 (plant not in cassava/maize/rice/tomato, or file isn't a real JPEG/PNG).

Screenshots below, drop the captured PNGs into /static/img/docs/postman/ with the filenames shown.

Screenshot 1 Setting the method + URL Show Postman with POST selected and the full URL pasted in. Filename: postman_diagnosis_01_url.png
Screenshot 2 Adding the X-Api-Key header Headers tab with one row visible: X-Api-Key + your masked key value. Filename: postman_diagnosis_02_header.png
Screenshot 3 Body → form-data with image File row Body tab, form-data selected, the image row toggled to File with a selected JPEG, and the three text rows below. Filename: postman_diagnosis_03_formdata.png
Screenshot 4 200 response with predictions Response pane showing 200 status + pretty-printed JSON with a predictions array. Filename: postman_diagnosis_04_response.png
Tip: save your API key as a Postman environment variable (e.g. ) so you don't paste it into every request and so screenshots you share don't leak it.

Response Examples

Successful response

The raw-key diagnosis response currently returns the diagnosis fields directly. It does not include a top-level success flag or gateway block.

Example Success Response
{
  "plant": "maize",
  "locale": "en-us",
  "kb_locale": "en-us",
  "job_id": "2ae7df30-3e3b-4d7b-b89d-6626a3d08b02",
  "top_k": 3,
  "raw_key": "uploads/fieldvision/codex_live_api_validation_6f477789fa.jpg",
  "result_key": "diagnostics/gradcams/2ae7df30-3e3b-4d7b-b89d-6626a3d08b02/result.json",
  "result_url": "https://signed-storage-url.example/result.json",
  "predictions": [
    {
      "class_index": 4,
      "label": "grey_leaf_spot",
      "confidence": 0.9412,
      "gradcam_key": "diagnostics/gradcams/.../pred_1.png",
      "gradcam_url": "https://signed-storage-url.example/pred_1.png"
    },
    {
      "class_index": 2,
      "label": "common_rust",
      "confidence": 0.0418,
      "gradcam_key": "diagnostics/gradcams/.../pred_2.png",
      "gradcam_url": "https://signed-storage-url.example/pred_2.png"
    }
  ],
  "inference_plants": ["cassava", "maize", "rice", "tomato"],
  "supported_plants": ["cassava", "maize", "rice", "tomato"]
}

Error response

Validation, authentication, quota, and server failures should all be handled explicitly in client code.

Example Error Response
{
  "success": false,
  "error": "bad_request",
  "message": "Unsupported plant: 'wheat'. Supported plants: cassava, maize, rice, tomato",
  "status_code": 400
}
Implementation note: do not hard-code an exact prediction schema unless your deployment contract guarantees it. Safely parse top-level diagnosis fields and handle validation, audience, quota, and upstream failures separately from model output.
Knowledge-backed variant: the response from /api/v1/image_diagnosis/infer/with_knowledge keeps the same top-level fields and adds canonical_disease_key plus a per-prediction knowledge object containing the filtered profile sections you requested.

Common error classes

  • 400 Bad Request: missing query parameter, unsupported plant, invalid image type, empty file, or file too large
  • 401 Unauthorized: missing API key or invalid API key
  • 403 Forbidden: wrong audience, missing scope, or API not allowed for the key
  • Quota exceeded: usage rejected after the configured guest, authenticated, or API-key quota is exhausted
  • 500 Internal Server Error: storage or diagnosis engine failure

Need more diagnosis API calls?

Buy API top-up credits or choose an API plan from your account billing page. Credits are granted only after payment success is confirmed.