Table of contents
- Table of contents
- Intro
- Getting access
- Licensing
- Endpoint
- Authentication
- The plant object
- Pagination
- List plants
- Search plants
- Get a single plant
- List varieties of a plant
- List companion plants
- Create a plant
- Update a plant
- Errors
- Help & Feedback
- Supporting free access to plant data for everyone
Intro
On our mission to give everyone interested the knowledge on how to grow useful plants for a food garden, medicinal or regenerative uses, we want the database to be used wherever it can help. This is why we provide an API for developers to add plant data to their applications and services.
The API lets you do everything you can do with plants on the website: list and page through the whole database, full-text search with faceted filtering, read individual plants and their varieties and companions, and create and update plants.
Getting access
API access is fully self-service: sign up for an account (or log in) and create your API keys under My API keys.
If you have any questions or feedback, don’t hesitate to reach out to us.
Licensing
Please note that all data available through this API is licensed under CC BY-SA 4.0. That means you must provide appropriate credit (Permapeople.org), and any work built upon this dataset must be distributed under the same license (CC BY-SA 4.0). We do our best to include data sources via links, descriptions and sources within plant profiles, and encourage our contributors to do the same.
Since this is a free service, we ask that anyone using the API give attribution to plant data sources by linking back to Permapeople.org, either in a specific call-out or in plant profiles where Permapeople plant data is used.
We do not currently allow commercial projects free access to the API. If you have a commercial project and you’d like to gain access to our API, please get in touch and we can work out the details.
Please also read our data acknowledgement.
Endpoint
All following requests must be sent to and will return valid JSON (content-type: application/json; charset=utf-8).
https://permapeople.org/api
Request bodies (for POST/PUT) must be sent as a JSON object with content-type: application/json.
Authentication
To access all API endpoints header-based authentication must be provided for every request. To authenticate, add the following HTTP headers to your request:
x-permapeople-key-id: YOUR_KEY_ID
x-permapeople-key-secret: YOUR_KEY_SECRET
Requests without valid headers return 401 Unauthorized:
{
"error": "not authenticated",
"msg": "Please check your x-permapeople-key-id and x-permapeople-key-secret http headers."
}
The plant object
Every endpoint that returns a plant returns the same shape. Endpoints returning many plants wrap them in a plants array (see Pagination).
{
"id" : 101,
"type" : "Plant",
"scientific_name" : "Morus alba",
"name" : "White mulberry",
"version" : 10,
"description" : "Young leaves are edible.",
"link" : "/plants/morus-alba-white-mulberry",
"slug" : "morus-alba-white-mulberry",
"parent_id" : null,
"updated_at" : "2022-07-30T08:17:26.658Z",
"created_at" : "2020-08-11T16:09:47.485Z",
"images" : {
"thumb" : "https://...",
"title" : "https://..."
},
"data" : [
{ "key" : "Edible", "value" : "true" },
{ "key" : "Growth", "value" : "Medium" },
{ "key" : "Water requirement", "value" : "Moist" },
{ "key" : "Light requirement", "value" : "Full sun, partial sun/shade" },
{ "key" : "USDA Hardiness zone", "value" : "3-9" },
{ "key" : "Layer", "value" : "Trees" },
{ "key" : "Soil type", "value" : "Light (sandy), medium, heavy (clay)" },
{ "key" : "Family", "value" : "Moraceae" },
{ "key" : "Edible parts", "value" : "Fruit, inner bark, leaves" }
]
}
Notable fields:
type<enum>:PlantorVariety. AVarietyhas a non-nullparent_idpointing at its parent plant.version<int>: the number of saved revisions. Used for optimistic locking on update (see Update a plant).data<array>: the flexible attributes of a plant as{key, value}pairs.images<object>: ready-to-use URLs (thumb,title); fields may be null when no image exists.
Pagination
All list endpoints (/plants, /search, /plants/:id/varieties, /plants/:id/companions) return a plants array and an additive pagination object describing the current slice.
{
"plants" : [ {<Plant>}, {<Plant>}, ... ],
"pagination" : { ... }
}
There are two paging modes. /plants defaults to keyset and additionally supports offset; /search, /varieties and /companions use offset.
per_page<int> controls the page size on every list endpoint. The default is 100 and the maximum is 100 (larger values are clamped down).
Keyset pagination (cursor)
The default for List plants. Walk the whole dataset by following the last_id cursor — efficient and stable even while data changes underneath you. The pagination object looks like:
"pagination" : {
"per_page" : 100,
"total" : 8421,
"last_id" : 1340,
"has_more" : true
}
To get the next page, pass last_id back in: GET /api/plants?last_id=1340. Stop when has_more is false.
Offset pagination (pages)
Used when you pass page, and the default for the other list endpoints. Jump to any page directly. The pagination object looks like:
"pagination" : {
"page" : 2,
"per_page" : 100,
"total" : 8421,
"total_pages" : 85
}
List plants
List plants ordered by their internal ID, wrapped in a plants array with a pagination object.
GET https://permapeople.org/api/plants
# Response
{
"plants" : [ {<Plant>}, {<Plant>}, ... ],
"pagination" : {
"per_page" : 100,
"total" : 8421,
"last_id" : 1340,
"has_more" : true
}
}
Params
Provide as GET params in the URL, for example ?last_id=100&per_page=50.
(optional) last_id<int>: Cursor — returns only plants after this id. Use this with has_more to page through the whole list (keyset mode, the default).
(optional) page<int>: Switches to offset mode and returns that page. Use with per_page and total_pages.
(optional) per_page<int>: Page size, default 100, max 100.
(optional) updated_since<iso8601 string>: Only show plants last updated on or after the datetime provided. Works in both paging modes.
Search plants
Returns plants matching a full-text search. This means it will find similarly named plants too, so check that the returned plant is the one you are looking for. Results are paginated (offset mode).
POST https://permapeople.org/api/search
GET https://permapeople.org/api/search?q=mulberry
# Response
{
"plants" : [ {<Plant>}, {<Plant>}, ... ],
"pagination" : {
"page" : 1,
"per_page" : 100,
"total" : 7,
"total_pages" : 1
}
}
Params
For POST, provide as a JSON object with content-type: application/json. For GET, provide as URL query params.
(required) q<string>: Search the whole database for this term. Much like the search on the website.
(optional) type<enum>: Restrict results to Plant/Species or Variety.
(optional) page<int> / per_page<int>: Paging, as described in Pagination.
(optional) <facet>: Any filterable attribute can be passed to narrow results, with a single value or an array of values (matched as OR), e.g. {"q": "mint", "Layer": "Herbs", "Light requirement": ["Full sun", "Partial sun/shade"]}.
Get a single plant
Returns a single plant object for an exact ID.
GET https://permapeople.org/api/plants/<id>
# Response
{<Plant>}
List varieties of a plant
Returns the varieties belonging to a plant, paginated (offset mode).
GET https://permapeople.org/api/plants/<id>/varieties
# Response
{
"plants" : [ {<Plant with type "Variety">}, ... ],
"pagination" : { "page" : 1, "per_page" : 100, "total" : 3, "total_pages" : 1 }
}
Accepts page and per_page params.
List companion plants
Returns the companion plants linked to a plant (link type “companion to”), paginated (offset mode). Antagonists and other link types are not included.
GET https://permapeople.org/api/plants/<id>/companions
# Response
{
"plants" : [ {<Plant>}, ... ],
"pagination" : { "page" : 1, "per_page" : 100, "total" : 5, "total_pages" : 1 }
}
Accepts page and per_page params.
Create a plant
To create a plant, do a POST request with a valid plant object. A valid plant object has at minimum a scientific_name, name and note. On success it returns the whole plant object with status 201 Created, otherwise an error.
POST https://permapeople.org/api/plants
# Response
{<Plant>}
Params
Provide as a JSON object with content-type: application/json.
(required) scientific_name<string>: The scientific name of a plant; if in doubt, use wikipedia to find the correct and current name.
(required) name<string>: The common name. Use the most common english name.
(required) note<string>: Describe the action you did and what sources you used.
(optional) description<string>: A free-text description of the plant.
(optional) type<enum>: Plant or Variety. If Variety is used, parent_id is required and must be an existing plant id.
(optional) data<array>: An array of {key, value} attribute pairs.
Update a plant
To update a plant, do a PUT request with the plant fields you want to change to the plant’s URL. On success it returns the whole plant object, otherwise an error.
Updates use optimistic locking: send the current version you last read. If the plant changed in the meantime, the server returns 422 with a version mismatch error — re-fetch the plant and try again. New data keys are merged into the existing data (sending data never deletes attributes you did not include); sending an existing key updates its value.
PUT https://permapeople.org/api/plants/101
# Request body
{
"version" : 10,
"note" : "Corrected the family from PFAF.",
"data" : [ { "key" : "Family", "value" : "Moraceae" } ]
}
# Response
{<Plant>}
Params
Provide as a JSON object with content-type: application/json.
(required) version<int>: The current version of the plant as read (optimistic locking).
(required) note<string>: A note describing the change.
(required) <changed fields>: At least one changed field — any of scientific_name, name, description, type, parent_id, or data.
Errors
If the API throws an error, it will always return an appropriate HTTP status code and valid JSON in the following format:
{
"error": "short description",
"msg": "longer description on what to do"
}
Common cases:
401 not authenticated— missing or invalid API key headers.422 validation failed— the plant object is invalid;msglists the failing fields.422 version mismatch— the plant changed since you read it; re-fetch and retry the update.
Help & Feedback
If you have any questions or need help using the API, feel free to reach out per mail (hello at) or on twitter. 🌱✌️ Happy coding!
Supporting free access to plant data for everyone
Since Permapeople.org is a free service, we ask that those using the Permapeople API for their own projects provide credit (to Permapeople.org) in the form of backlinks, and donate what they can. You can find donation options through our Libera Pay donations page.