Crops API: Unified text and image retrieval for maize and rice
Four operations on a single per-crop namespace. Text chat returns ranked passages from the curated crop knowledge base. Text diagnose runs a short, multi-turn disambiguation funnel over the same KB. Media search returns annotated reference images. Media diagnose runs the same disambiguation funnel against the image library. Both funnels are designed for the words farmers actually use, colour, shape, location on the leaf, not technical jargon.
What is the Crops API?
The Crops API exposes FildraAI's two crop experts, maize and rice, through a single per-crop namespace. Each crop has four operations: text chat (passages from the knowledge base), text diagnose (multi-turn funnel over the KB), media search (reference images), and media diagnose (multi-turn funnel over the image library). Both diagnose funnels accept everyday descriptive language rather than agronomy terminology; when a query is too ambiguous to retrieve confidently the API asks one short clarifying question at a time.
The Crops API supersedes the legacy /api/v1/chat/message and /api/v1/media/{plant}/* routes. Those routes remain live during the migration window but return deprecation headers (see Deprecated routes below). New integrations should target /api/v1/crops/{plant}/* exclusively.
What you do NOT get from this API
To protect the research and curated KB that make the experts useful, responses are scrubbed of internal scoring fields. You will not see candidate ranking weights, the question-bank boost/penalty matrices, the funnel's internal session state, or raw retrieval scores. You see the final answer or the next clarifying question, the same surface our own apps render, and nothing that would let a competitor reconstruct the orchestration logic.
Authentication
All Crops API endpoints require a valid API key. Use the X-Api-Key header (Bearer tokens are also accepted):
X-Api-Key: YOUR_API_KEY
Authorization: Bearer YOUR_API_KEY
Text operations require the crop:search scope. Media operations require the media:search scope. Keys are issued per application from the FildraAI developer dashboard and can be scoped to a single crop (e.g. crop:maize) for tiered billing. Requests without a valid key return 401 Unauthorized; missing scope returns 403 Forbidden.
Usage billing
All POST requests on the Crops API are billed per call, tracked against the API key used in the request. Diagnose-funnel turns are each billed as a single call, three turns to converge counts as three calls. The free tier is capped low (sufficient for evaluation, insufficient for any real product). Heavy callers should contact us about enterprise pricing.
Endpoints
POST /api/v1/crops/{plant}/chat
Text RAG over the crop KB. Send a natural-language query, receive ranked passages with source attribution.
Scope: crop:search.
POST /api/v1/crops/{plant}/diagnose
Multi-turn text diagnostic funnel. The API asks 1–3 short clarifying questions before returning a top-candidate disease plus supporting passages. Scope: crop:search.
POST /api/v1/crops/{plant}/media/search
Image search. Query the annotated crop image library by natural-language description. Scope: media:search.
POST /api/v1/crops/{plant}/media/diagnose
Multi-turn image diagnostic funnel. Same staged contract as text diagnose but the funnel asks physical questions (raised vs flat, powder vs no powder) and returns matched reference images. Scope: media:search.
{plant} is currently one of maize or rice. Both crops use the same request and response envelopes; the underlying KB and image catalogue are crop-specific.
Acceptable use
Do not train competing systems on Crops API output.
You may use Crops API responses to render guidance to your own end users (farmers, agronomists, extension workers, integrators). You may NOT use the responses, passages, diagnoses, image metadata, retrieval scores, or session payloads, to build a derivative classifier, knowledge base, or diagnostic system that competes with FildraAI or any FildraAI partner offering. Bulk scraping of the API for model-distillation purposes is a Terms-of-Service violation. We monitor request patterns and reserve the right to revoke keys that show distillation-style usage.
Attribution requirement
Any user-visible surface that renders Crops API content must show "Powered by FildraAI" in a reasonable, persistent location (footer, About panel, response card). This is a low-friction acknowledgement that signals to your users where the underlying expertise comes from and protects everyone from the misperception that an unverified third-party tool is the source of agronomic guidance.
Advisory only, agricultural decisions
The Crops API returns reference information from a curated knowledge base. It does not replace agronomic judgement, local extension support, or laboratory diagnosis. Use it as a decision aid alongside other tools. FildraAI does not warrant outcomes that result from acting on API output alone.
Text chat, passage retrieval
POST /api/v1/crops/{plant}/chat retrieves the top-k most relevant knowledge-base passages for a natural-language query, scoped to the crop in the URL path. This is the right endpoint when you want curated reference content to display alongside a user question.
Required
text(string), Natural-language query
Optional
locale(string, defaulten-us), Response languagek(integer 1–20, default 6), Maximum passages to returnclient_request_id(string), Idempotency key for safe retries
Example request
curl -X POST "https://api.fildraai.com/api/v1/crops/maize/chat" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "maize leaf blight",
"locale": "en-us",
"k": 6
}'
Response includes ok, reply (short summary), docs[] (ranked passages with id, title, section, content, score), and a public meta block (plant, locale, k, build_id). Internal facet routing and oversample debug fields are stripped from the response.
Text diagnose, multi-turn funnel
POST /api/v1/crops/{plant}/diagnose runs a staged disambiguation flow. The first turn classifies the query into a symptom frame; if confidence is too low to commit to a diagnosis, the API returns one short clarifying question. Echo the returned session on the next turn with the farmer's answer added, and the funnel narrows. After three answers it commits regardless.
Required
q(string), Farmer's natural-language description
Optional
locale(string, defaulten-us)k(integer 1–20, default 6), Passages to return when the funnel commitssession(object), Echo the previous response'ssessionon turn 2+, with the answer added undersession.answers[question_id]
Example, turn 1
curl -X POST "https://api.fildraai.com/api/v1/crops/maize/diagnose" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "leaves turned brown and dried up",
"locale": "en-us"
}'
The MVP funnel asks at most three questions, in priority order:
- Growth stage, seedling / vegetative / tillering or jointing / heading or flowering / grain fill / mature
- Plant part, leaves / stalk or stem / sheath / panicle or tassel / roots / whole plant
- Colour, yellow / orange rust / brown-tan / grey-white / black / purple-red
Response envelope
Every turn returns the same fields: action ("ask_question" or "show_passages"), ambiguity, confidence, candidates[] (top disease slugs), diagnosis (top class when committed), question (with id, ask, options, importance, never the internal boost/penalise dicts), items[], why (user-readable rationale, no score values), and session (opaque, echo back unchanged).
Media search, image retrieval
POST /api/v1/crops/{plant}/media/search retrieves annotated crop disease reference images by natural-language description. Useful for surfacing visual examples alongside text guidance, or for image-led browsing UIs.
Required
q(string), Natural-language description of the crop symptom or search querylocale(string), Locale key for the response language, e.g.en-us,sw-ke,fr-af
Optional
k(integer, default 8), Maximum number of images to returnscope(string, default "global"), Geographic scope filtercategory(string), Filter by image category tagimage_group(string), Filter by image group identifierinclude_scores(boolean, default false), Include relevance scores in each result item
Example request
curl -X POST "https://api.fildraai.com/api/v1/media/rice/search" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "yellowing leaves with brown spots near the base",
"locale": "en-us",
"k": 5,
"include_scores": true
}'
Media search, response schema
The intended successful search response returns a job-style result with matched image items. Production currently returns a 500 job creation error for search and diagnose routes, so treat this schema as the contract to use once the media queue path is healthy again.
{
"ok": true,
"count": 5,
"items": [
{
"id": "img_abc123",
"title": "Rice leaf blight reference image",
"file": "rice_leaf_blight_001.jpg",
"plant": "rice",
"class": "bacterial_leaf_blight",
"topic": "disease",
"locale": "en-us",
"score": 0.91,
"media_download_url": "https://...",
"tags": ["leaf", "lesion", "blight"],
"category": "field",
"image_group": "rice_blight_set_a"
}
],
"meta": {
"query": "yellowing leaves with brown spots",
"plant": "rice",
"locale": "en-us",
"took_ms": 124
}
}
Each item in items represents a matched reference image. The score field is only present if include_scores was set to true in the request. Internal storage URLs are stripped from the response for security, use media_download_url to access the image.
Media diagnose, staged image funnel
The /diagnose endpoint runs a multi-turn disambiguation flow. Rather than immediately returning images, it may first ask one or more clarifying questions to narrow the search. This is useful when a description could match multiple disease classes.
Turn 1, Initial query
- Send
qandlocale; omitsession - If
actionisask_question, show the question fromquestion.askto the user - Store the full
sessionobject from the response
Turn 2+, Answer and continue
- Echo the
sessionobject from the previous response - Add the farmer's answer inside
session.answers[question_id] - When
actionbecomesshow_images, theitemsarray contains the matched images
Confidence threshold
The diagnostic flow moves to show_images once confidence exceeds 0.75 or after three disambiguation rounds, whichever comes first. The ambiguity field in each response (one of very_high, high, medium, low) reflects current uncertainty.
Farmer language coverage
The funnel does not require a farmer to know plant-pathology vocabulary like lesion, whorl, or chlorotic. It maps everyday descriptive words to symptom groups, then uses those groups to score candidate diseases. The complete keyword table is below, use it to set client-side hints and example prompts.
| Symptom group | Recognised words | What it signals |
|---|---|---|
| spots | spot, spots, lesion, lesions, mark, marks, dot, dots, speck, specks | Generic discrete-mark group. High-ambiguity on its own. |
| browning | brown, browning, brownish, tan, tannish | Brown discolouration. Common across many diseases. |
| yellowing | yellow, yellowing, pale, discolor(ed/oured), chlorotic | Yellow / pale discolouration. |
| powder | powder, powdery, dust, dusty, puff | Strong signal for rusts (maize) and smuts (rice). |
| raised | raised, bump, bumpy, bumps, blister, blisters, pustule, pustules, rough, lumpy | Raised texture. Maize: rust pustules. Rice: hispa blister mines. |
| burnt | burnt, burn, burned, scorch, scorched, fire, charred | Burn-look symptoms (NCLB, leaf scald). |
| streak | streak, streaks, stripe, stripes, line, lines | Linear lesions (bacterial leaf streak, MLB). |
| halo | halo, halos, ring, rings | Ring around the lesion. Maize: GLS. Rice: brown spot. |
| wilt | wilt, wilting, wilted, droop, droopy, limp | Loss of turgor; whole-plant symptom. |
| rot | rot, rotten, rotting, decay, decaying | Tissue breakdown (stalk rot, sheath rot). |
| orange | orange | Specific colour. orange + powder is a low-ambiguity signature for rust. |
| holes | hole, holes, eaten, eat, chewed, chew | Physical damage; pest indicator rather than disease. |
What works today verified
These phrases were all correctly parsed into useful symptom frames during integration testing:
"looks brown"→browning"starting to look yellow"→yellowing"I see brown spots"→spots + browning"the spots look like burn"→spots + burnt"powdery orange stuff on leaves"→powder + orange(low-ambiguity, retrieves immediately without follow-up questions)"lower leaves are wilting"→wilt+leaf_position=lower"tiny dots all over"→spots
Known gaps to plan around limitation
The current normaliser does whitespace tokenisation and exact keyword match, no stemming, no punctuation stripping. The following inputs return no symptom frame today and fall straight to action: "ask_question" with ambiguity: "very_high":
- Punctuation attached to a keyword:
"brown."or"spots,"are tokenised as"brown."/"spots,"and miss the table. - Inflected forms:
"yellowish","browner"are not in the synonym table."yellowing"and"brown"do work. - Disease names as keywords:
"rust","blight","smut"are class names the funnel predicts, not inputs it recognises. Farmers using these are usually right, but the funnel will still ask a clarifying question. - Vague distress phrases:
"looks bad","my plants are dying","diseased"carry no physical detail. The funnel will ask the highest-value physical question first (raised vs flat). - Hyphenated terms:
"green-yellow"is one token and does not matchyellow.
Client tip: lowercase the input and strip trailing punctuation before sending. For multi-sentence descriptions, send the most physical sentence (the one with colour/shape/texture words) for the best frame match.
Locale and language support
The locale parameter controls both the language of metadata returned and the search index used. If the requested locale is not available for the given crop, the API falls back to the closest available locale (usually en-us) and sets fallback_used: true in the response.
Supported locales
en-us, Englishsw-ke, Kiswahili (East Africa)fr-af, French (West/Central Africa)zh-cn, Simplified Chinesezh-tw, Traditional Chinese
Fallback behaviour
- Each response item includes
requested_localeandserved_localefields fallback_used: truemeans the index was served from a different locale than requested- If no locale index exists at all, the API returns
404with errormedia_not_found
Deprecated routes
The three routes below are the legacy ancestors of the unified Crops API. They remain functional during the migration window but every successful response carries three RFC 8594 headers: Deprecation: true, Sunset: Mon, 31 Aug 2026 00:00:00 GMT, and Link: </api/v1/crops/{plant}/...>; rel="successor-version". After the Sunset date the legacy routes will return 410 Gone.
| Legacy route | Successor |
|---|---|
| POST /api/v1/chat/message | POST /api/v1/crops/{plant}/chat |
| POST /api/v1/media/{plant}/search | POST /api/v1/crops/{plant}/media/search |
| POST /api/v1/media/{plant}/diagnose | POST /api/v1/crops/{plant}/media/diagnose |
Migration tips
The new routes take the plant in the URL path rather than the request body. Otherwise the request shapes are functionally equivalent. The new /diagnose endpoint for text is brand-new, there is no legacy equivalent. Watch the Sunset header in your HTTP client and route migration alerts to your on-call channel.
Error codes
The Media Search API returns standard HTTP status codes. Common error cases:
Client errors (4xx)
400, Missing or invalid parameter (e.g. emptyqor missinglocale)401, Missing or invalid API key403, Key does not have the required scope or audience404, Media index not found for the requested plant and locale429, Rate limit exceeded
Server errors (5xx)
500, Internal error (media_search_failedormedia_diagnose_failed)503, Media index is being rebuilt (media_build_pending); retry after a short delay
503 during index rebuild
When a crop index is being rebuilt in the background, search requests return 503 with error code media_build_pending. This is a temporary state, the response message will indicate when the build is expected to complete. Implement exponential backoff before retrying.