Historical Palmoil FFB price API
Get FFB schedule history
Endpoint and request
REST endpoint
GET /v1/commodities/oil-palm-ffb-price/observationsContract request
curl --request GET \
--url "https://api.narwhalapi.com/v1/commodities/oil-palm-ffb-price/observations?series_id=id-ri-oil-palm-ffb-smallholder-purchase-agreement&start=2026-08-01&end=2026-09-02&limit=100" \
--header "Authorization: Bearer $NARWHAL_API_KEY"MCP uses commodities_get_oil_palm_ffb_price_observations. REST and MCP share the same schema, account quota, rights check, and problem shape.
Parameters
| Name | Required | Type | Meaning |
|---|---|---|---|
series_id | Yes | query · stable Narwhal ID | Series returned by physical-series discovery. |
start | No | query · YYYY-MM-DD | Inclusive lower bound. It must be supplied together with end. |
end | No | query · YYYY-MM-DD | Exclusive upper bound. It must be later than start. |
limit | No | query · integer, 1–500 | Maximum complete schedules to return. Defaults to 100. |
cursor | No | query · opaque string | Continuation token bound to the same series and date range. |
Response
Contract example
{
"series_id": "id-ri-oil-palm-ffb-smallholder-purchase-agreement",
"commodity": "OIL-PALM-FFB",
"country": "IDN",
"area": "ID-RI",
"producer_type": "smallholder",
"producer_arrangement": "purchase_agreement",
"price_basis": "official_purchase_schedule",
"currency": "IDR",
"unit": "kilogram",
"observations": [
{
"effective_from": "2026-08-26",
"effective_to": "2026-09-01",
"released_on": "2026-08-26",
"revision": 1,
"prices": [
{
"tree_age_min_years": 9,
"tree_age_max_years": 9,
"price": "3878.72"
}
]
}
],
"next_cursor": null
}| Field | Type | Required | Meaning |
|---|---|---|---|
series_id / commodity / country / area | strings | Yes | Stable identity and physical-market scope. |
producer_type / producer_arrangement | strings or null | Yes | Producer scope shared by every returned schedule. |
price_basis / currency / unit | strings | Yes | Shared value meaning and quote convention. |
observations | array | Yes | Complete schedules ordered by effective_from, oldest first. |
next_cursor | string or null | Yes | Opaque continuation token, or null at the end. |
Errors and quota
400 invalid_query— a code, area, date range, limit, or selector is invalid.400 invalid_cursor— the cursor is invalid or does not match the series and range.401 invalid_api_key— the Bearer key is missing or rejected.404 physical_price_observations_not_found— no complete approved data matches the request.429 rate_limit_exceededorquota_exhausted— the shared allowance is exhausted.503 physical_price_unavailable— a complete publication cannot safely satisfy the Interface.
Rejected requests and server errors do not consume monthly quota.
Coverage
History includes accepted complete schedules only. It is not a completeness claim for every area or year.
Public access is not open yet.