Browse all documentation

Historical Palmoil FFB price API

Get FFB schedule history

Endpoint and request

REST endpoint
GET /v1/commodities/oil-palm-ffb-price/observations
Contract 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

NameRequiredTypeMeaning
series_idYesquery · stable Narwhal IDSeries returned by physical-series discovery.
startNoquery · YYYY-MM-DDInclusive lower bound. It must be supplied together with end.
endNoquery · YYYY-MM-DDExclusive upper bound. It must be later than start.
limitNoquery · integer, 1–500Maximum complete schedules to return. Defaults to 100.
cursorNoquery · opaque stringContinuation 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
}
FieldTypeRequiredMeaning
series_id / commodity / country / areastringsYesStable identity and physical-market scope.
producer_type / producer_arrangementstrings or nullYesProducer scope shared by every returned schedule.
price_basis / currency / unitstringsYesShared value meaning and quote convention.
observationsarrayYesComplete schedules ordered by effective_from, oldest first.
next_cursorstring or nullYesOpaque 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_exceeded or quota_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.