This page shows you how to order a pre-season nitrogen recommendation for a field, using the field's own fertilization or yield history rather than a request date, and how to read back the result.
PNRX is one of five products in Spacenus's ANA precision-farming family. Base URL, authentication, the shared map-order fields, the credit model, bulk mechanics, and the status codes/completion-event conventions common to all five products are covered in the ANA overview page — this page only covers what's specific to PNRX.
Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | maps/preseason-nitrogen-recommendation/orders/ | Create a new PNRX order. Single object only — no bulk support (see below). |
GET | maps/preseason-nitrogen-recommendation/orders/{ORDER_ID}/ | Retrieve one order. |
GET | maps/preseason-nitrogen-recommendation/orders/ | List orders. |
Authentication and permissions
Send your access token as a bearer token, as described in the overview page. In addition to a valid token, the caller's role needs the following dynamic permission:
| Action | Required permission |
|---|---|
| Create | pnrx.create |
| List / Retrieve | pnrx.view |
A request from a caller that lacks the required permission gets HTTP 403 with a structured body, not the generic envelope:
{ "code": "permission_denied", "message": "You do not have permission to perform this action.", "details": { "required_permission": "pnrx.create", "action": "create", "resource": "pnrx" } }
No date field
Unlike NRX or VI, a PNRX create request never takes an explicit date. PNRX derives its own processing window from the fertilization years you provide in year_wise_fertilizations (see below) — there's nothing to pass for "when."
Request fields
The fields shared by every ANA map-order create request — field_uuid/field_boundary, output_data_type, no_of_classes, is_background — apply here too; see the overview page's shared fields table rather than duplicating it here. On top of those, PNRX takes the following fields:
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
crop | string (enum) | Yes | — | One of: wheat, rapeseed, corn, barley, rye, triticale, cotton, red cabbage, white cabbage, chinese cabbage, cauliflower, other citrus fruits, oranges. |
orchard_age_years | integer | Conditionally required | — | Only relevant when crop is other citrus fruits or oranges — see the branching rule below. |
target_yield_t_ha | number | Conditionally required | — | Same citrus/orange-only relevance as orchard_age_years. |
yield_history | array of objects | Conditionally required | — | Required when crop is other citrus fruits or oranges. Each item: {"year": integer, "actual_yield_t_per_ha": number}. |
year_wise_fertilizations | object | Conditionally required | — | Required for every crop except other citrus fruits/oranges. Maps a 4-digit year (as an object key) to {"n_applied": integer >= 0}. Years must not exceed the current year. |
This endpoint's crop field is named
crop, notcrop_typelike the Nitrogen Recommendation Map endpoint. It also accepts 2 values the Nitrogen Recommendation Map endpoint doesn't:other citrus fruitsandoranges.
The crop-dependent field sets
Which of the fields above are required — and which are silently ignored — depends entirely on crop:
crop is other citrus fruits or oranges
yield_history becomes required. year_wise_fertilizations is ignored and stripped from the request even if you send it.
crop is anything else
year_wise_fertilizations becomes required. yield_history, orchard_age_years, and target_yield_t_ha are ignored and stripped from the request even if you send them.
Sending the "wrong" field set for your crop doesn't error. The irrelevant fields are just silently dropped — only the required set for your crop is validated.
Region restriction
If
cropisother citrus fruitsororanges, the field must be located in Spain. A request for a citrus/orange crop on a field outside Spain is rejected with HTTP 422 Unprocessable Entity and the message "Service not available for field outside spain." This restriction does not apply to any other crop.
Bulk ordering
PNRX does not support bulk ordering. POST maps/preseason-nitrogen-recommendation/orders/ only accepts a single order object — sending an array is not supported for this product.
Status codes
| Status | Trigger |
|---|---|
| 200 | Order created. |
| 400 | Validation failure — for example a missing/unrecognized crop, or a request missing the required field set for its crop. |
| 402 | Insufficient wallet credit. |
| 404 | field_uuid/field_boundary didn't resolve to a field. |
| 409 | A pre-season recommendation for this field already exists and is active, within a 120-day request window. The response body includes the existing map's data (which may be null in some cases) — treat this as success, not an error. |
| 422 | Region restriction — a citrus/orange crop on a field outside Spain (see above). |
| 500 | An internal error occurred preparing satellite imagery or dispatching the order for processing. |
A duplicate PNRX request (409, above) doesn't cost extra credit. A field is only ever charged once — on its first successful ANA order, across any of the five products — and a request can only come back as a duplicate if an earlier order for that field already exists, meaning the charge already happened on that earlier order. See ANA Maps Overview for the full credit model.
The 409 duplicate check only looks at orders that are already active — unlike NRX and SPM, it does not also block on orders that are still processing. That means a second PNRX request for the same field while an earlier one is still processing is not blocked, and will create a second order.
Retrieve response
GET maps/preseason-nitrogen-recommendation/orders/{ORDER_ID}/ returns the standard order fields plus:
| Field | Notes |
|---|---|
map_type | Always "pnrxm" for this product. |
status | One of pending, processing, active, failed. |
preseason_recommendation | The recommendation result. |
preseason_recommendation_existing_date | Set when this response reflects a pre-existing recommendation. |
post_code_based_recommendation | Post-code-level recommendation data. |
preseason_recommendation_analytics | Supporting analytics for the recommendation. |
Completion event
When an order finishes, PNRX publishes pnrx_order_completed. On success it includes order_id, field_id, field_uuid, company_id, and map_uuid. See the overview page's completion-events section for the general event/delivery mechanics and where a failed order's error field fits in.
Example: create an order
This example uses the year_wise_fertilizations variant, since it applies to every crop except the two citrus/orange values.
curl -X POST https://backend.spacenus.de/api/v1.2/maps/preseason-nitrogen-recommendation/orders/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"field_uuid": "FIELD_UUID",
"crop": "wheat",
"year_wise_fertilizations": {
"2023": {"n_applied": 120},
"2024": {"n_applied": 140}
},
"output_data_type": 1,
"no_of_classes": 5
}'A successful response:
{
"status": "success",
"message": "Map processing started successfully.",
"data": {
"order_id": "ORDER_ID",
"status": "processing"
}
}Example: retrieve an order
curl https://backend.spacenus.de/api/v1.2/maps/preseason-nitrogen-recommendation/orders/ORDER_ID/ \
-H "Authorization: Bearer YOUR_TOKEN"{
"status": "success",
"message": "Success",
"data": {
"order_id": "ORDER_ID",
"map_type": "pnrxm",
"status": "active",
"field_uuid": "FIELD_UUID",
"preseason_recommendation": {},
"preseason_recommendation_existing_date": null,
"post_code_based_recommendation": {},
"preseason_recommendation_analytics": {}
}
}