Skip to content
Luis Ramos edited this page Sep 15, 2019 · 26 revisions

This page describes Open Food Network's API (this page has been rebuilt in Sept 2019 as part of the issue #3001).

OFN API is no longer based on Spree's API and only includes OFN specific endpoints.

API DOCUMENTATION

We use swagger and json-api to document the OFN API. You can see the documentation here: https://app.swaggerhub.com/apis/luisramos0/the-open_food_network/0.1

Authorization

To access the API, you need an API key. This can be found in the admin backend at the right of the edit user page. That can be passed with the X-Spree-Token request header, or the token query parameter. The user api key can be found in the OFN backoffice: click on the menu Users, select the user that will use the API, see "API KEY".

Some basic API implementation details for developers

The OFN API is implemented in a specific namespace /api. There are quite a few endpoints that are not under /api that render json, particularly in /admin (where they are mixed with html rendering endpoints). We do not consider these endpoints as part of the OFN API.

AMS is the serialization solution used in the OFN API, that means we stopped using rabl files in OFN. In OFN codebase, there should be no API code under app/views because AMS serializers should all be under /app/serializers.

How to build a new API endpoint (with examples)

Routes

To build a new API endpoint first you need to check what endpoint or action you what to add. There's a API specific routes file for API routes here.

We will use api/products/bulk_products as our "good" example, you can see this endpoint is a specific GET endpoint in the api routes file here.

Some comments about this example api/products/bulk_products endpoint:

  • this could be the default index endpoint in the main /products route but because it's returning "products the user can edit" and not "all products the user can see", it's acceptable to have it in a different url, in this case api/products/bulk_products. The name bulk refers to the client page that uses this endpoint, ideally this should not be the case the the endpoint should only refer to the data it returns, not its clients. In this case a better name would be for example api/products/editable.

Controllers

All API controllers are now under app/controllers/api here.

We can find our example bulk_products action in the api/products_controller.rb here.

Common Actions

In this products controller you will also find typical actions implemented:

  • show - GET /api/products/{product_id} - gets one product
  • create - POST /api/products - creates a product with given details
  • update - GET /api/products/{product_id} - updates a product with given details
  • destroy - DELETE /api/products/{product_id} - deletes a product with given Id
  • index (not present in this case) - GET /api/products - lists products

Serializers - Output Payloads

In order to create the results for your endpoint, you should use AMS Serializers, you can re-use existing ones, they are all under app/api/serializers here, or you can create new ones in the same folder.

Note about serializers usage: a lot of these serializers are used outside the API: they are used to render json data that is injected in the DOM of the pages rendered.

Note about the admin namespace: currently we have two namespaces app/serializers/api and app/serializers/api/admin. The api/admin folder contains serarializers for the admin side of the OFN app but I dont think this is consistent... there's no admin namespace in the API itself and the API uses both serializers from serializers/api/ and serializers/api/admin...

A note about managing Serializers: we should keep the number of serializers to a minimum, make sure you really need a new serializer when you create one. In some cases, you will need a specific serializer for the same entity, we dont have conventions for this yet but try to make these generic if possible, see for example enterprise_thin_serializer, the enterprise_serializer and the basic_enterprise_serializer. This is not simple but necessary for enterprises.

Pagination

In OFN we use kaminari for pagination.

You can check the products/bulk_product pagination code for reference. Basically, the query string can include ?page=1&per_page=15 and the result object can be filtered with the .page and .per methods, see another example in the orders index search.

The pagination data in the payload should follow this structure.

Parameters - Input Payloads

For filtered lists we use ransack. This search will be done on the index action typically. The filters will be sent through the query parameters and encoded under the q parameter, like this example: ?q%5Bbill_address_firstname_start%5D=Luis&q%5Bbill_address_lastname_start%5D=Ramos&q%5Bcompleted_at_not_null%5D=true&q%5Bemail_cont%5D=[email protected]&q%5Bs%5D=completed_at+desc

This will enable us to simply filter results using ransack and params[:q] like here.

Regarding input data for POST and PUT endpoints where client will send data to create or update resources. This data is currently being sent via form_data. We should probably switch all our endpoints to take json data from clients instead.

Clone this wiki locally