Go back to list


In API v2 we want to introduce a consistent approach based on the concept of CQRS (Command-Query responsibility separation). This means, that we threat querying and modifying data separately:

  • for basic data queries, we use the OData standard  - this is the query part
  • for modifying data (and sometimes for more specific data queries), we use standard POST endpoints - this is the command part
  • use JsonPatch syntax for changing only the selected values of a resource

This means, that we don’t try to be fully REST-ful, which we decided is not a good approach for the growing needs of our customers.


Some properties returned by the API endpoints as well as error messages are translatable. For instance, a trainer's bio can be translated into multiple languages. By default API V2 will look for a translation in your company's primary language.

However, you can request a specific language by using a Accept-Language header. Here's an example:

Accept-Language: da, en-gb;q=0.8, en;q=0.7

You can read more about this here: https://datatracker.ietf.org/doc/html/rfc2616#page-104

What is OData?

OData is open data transfer standard. It is in some ways similar to the more widely known GraphQL. If you ever used any kind of ORM library, you can see OData as a kind of ORM through HTTP.

In practice, that means, that if you want to query members, you would make a request:

GET /api/v2/odata/Members

There is an entity called Member, and you can query it by calling it’s endpoint. But there is more, you can for example query members, whose first name is John:

GET /api/v2/odata/Members?$filter=firstName eq 'John'

Your members are assigned to some club, which is their home club. You may want to pull that clubs’ data along with the member info. With OData it’s easy:

GET /api/v2/odata/Members?$filter=firstName eq 'John'&$expand=homeClub

With OData you can also build very complicated queries. Here is a query that retrieves the first 100 of not deleted payment plans available in the club with ID=1:

GET /api/v2/odata/PaymentPlans?$top=100&$filter=isDeleted eq false and availableInClubs/any(c: c/id eq 1)

OData syntax is very rich. As a reference, you can check the official documentation here: http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part2-url-conventions.html It’s not very good as a starting point, but rather as a reference for more complicated cases. To start your adventure with OData we would recommend some of the tutorials available online.


JSON Patch is a format for describing changes to a JSON document. It can be used to avoid sending a whole document when only a part has changed. When used in combination with the HTTP PATCH method, it allows partial updates for HTTP APIs in a standards-compliant way. The patch documents are themselves JSON documents.

This paragraph provided an example of using the PATCH request with JSON PATCH syntax used in the body of such requests. A JSON Patch document is a sequential list of operations to be applied to an object. In this case, the body payload is a JSON array of objects: every object is composed of an op field, a path, and a value.

The op field describes the operation to perform on our target, path refers to the name of our field, and the value is the replacement for our target. The request will replace certain field with the new value. Furthermore, the op field accepts a bunch of operations on data, including:

  • Add
  • Remove
  • Replace
  • Move
 PATCH /Api/v2/Members/UpdateMemberDetails/12345 Host: company.perfectgym.pl Content-Type: application/json-patch+json [ { "op": "replace", "path": "PersonalData/Email", "value": "test1234@perfectgym.com" } ]

As a reference, you can check official documentation here: https://datatracker.ietf.org/doc/html/rfc6902/

Help us improve the Knowledge Base experience and rate this article!
No votes have been submitted yet.