# API request format

AyaNova uses a RESTful API and supports the [JSON](https://www.json.org/) data interchange format exclusively.
No other data formats are supported, your code must supply and consume JSON formatted data.

All developer interaction with the AyaNova API is via the REST server interface only.

## API documentation

Your primary source of information on how to make API requests is the [API explorer console](api-console.md) where every route is documented and can be tested manually before coding.

## API Versioning and URL

The AyaNova API is versioned and all requests must specify as part of the URL the version of the API desired.  The API version number must be 8 or greater.

For example, for this request for the list of AyaType codes: `http://localhost:7575/api/v8.0/AyaType` the server location and request to the start of the API route is specified by this part `http://localhost:7575/api/` and the exact version and route is specified by the final part: `v8.0/AyaType`.  In future releases the API version will be incremented and accessible by specifying the new API version number.  Old versions of the API will be supported wherever possible so an app written against the v8.0 API version will continue to work into the future when newer API versions are released (assuming an older version route hasn't had to be changed due to a serious issue or incompatibility).

The [API explorer console](api-console.md) on your server is always the best source of information on how to access your particular API and features a built in Version selector so you can manually try out any version of any route.

## Dates and times

All dates and times sent or retrieved from the REST interface **must** be in UTC / GMT time zone.  It is the Client software's responsibility to display and accept input of dates in local format but all dates transmitted to or received from the server must be in is0-8601 UTC time zone format only.  For example: `2018-12-19T17:54:13.616028`. Note there is no time zone offset, the time is understood to be UTC already.

## Translation

Every User account in AyaNova has their own UserOptions object which contains their personal Translation settings such as time zone offset, currency symbol and numeric formatting options you can use this value to correctly display and interpret values at a client level.

In addition every user has their own TranslationId setting stored in their User record (not UserOptions) which can be used to fetch and display text in the correct translation by using the methods in the Translation routes.

## Paging, sorting and filtering lists

Most list routes have a common method for paging sorting and filtering via query parameters provided to the route:

### Offset

This parameter controls the paging offset and is expected to be an integer.  If no value is specified the default is 0.

### Limit

This parameter controls the number of items returned starting at the offset provided.  The maximum allowed value is 1000, the default value is 25 if no value is specified.

### DataFilterId - Sorting and Filtering

Sorting and filtering are accomplished by providing an Id value in the DataFilterId parameter of a list for a pre-created and saved `DataFilter` object.

A DataFilter is created separately before it can be used with a list request via the DataFilter route (see the [API explorer console](api-console.md)).

A DataFilter object contains properties for filtering and sorting as well as a name used to display for selection in the user interface and properties that control who can select and use the filter (public or just a single User).

#### DataFilter.sort

This parameter controls the sort order of the data returned.  It is expected to be a *string* representation of a JSON array of objects that contain two fields a `fld` property that contains the string name of the field to be sorted by and a `dir` property that controls the direction of sorting and is one of two values "+" for Ascending or "-" for Descending.  Multiple objects may be specified to sort by multiple columns in order from first to last specified in the array.

Note that this property of the DataFilter is expected to be a *string* representation of the JSON collection, not raw JSON. (I.E. convert your raw JSON to a string format first)

For example the following Sort array will sort a list by Name first in ascending order and then by StartDate second in descending order:

```[{fld:"name", dir:"+"},{fld:"startdate", dir:"-"}```

To determine which field names are valid for a particular list you can make use of the `/FilterOptions` API route for that object which is available for any objects with sort and filterable lists.

If no sort parameter is provided the default is to sort by Id Descending so the most recently created objects appear first in the list.

#### DataFilter.filter

This parameter filters the data returned.  It is expected to be a *string* representation of a JSON array of objects that contain three fields:
- `fld` property that contains the string name of the field to be sorted by
- `op` property that specifies what type of filter operation is required
- `value` property when a comparison value is required such as a "Starts with" type of filter or a special token representing values

The `fld` property must be a valid field for the list in question. To determine which field names are valid for a particular list you can make use of the `/FilterOptions` API route for that object which is available for any objects with sort and filterable lists.

The `op` property must be a valid filter operation type. The 10 possible values for `op` are:

| OP | MEANING |
| ----- | ------------------------------ |
| = | Equality, `fld` data must equal `value` specified to be included in list |
| > | Greater than, `fld` data must be greater than `value` specified to be included in list |
| >= | Greater than or equality, `fld` data must be greater than or equal to `value` specified to be included in list |
| < | Less than, `fld` data must be less than `value` specified to be included in list |
| <= | Less than or equality, `fld` data must be less than or equal to `value` specified to be included in list |
| != | Not equal, `fld` data must not equal `value` specified to be included in list |
| %- | Starts with, `fld` data must start with `value` specified to be included in list |
| -% | Ends with, `fld` data must end with `value` specified to be included in list |
| -%- | Contains, `fld` data must contain `value` specified to be included in list |
| !-%- | Not contains, `fld` data must not contain `value` specified to be included in list |


Note that not all op values are valid for all data types, for example a date doesn't support a Contains type operator.

The `value` property is usually a direct comparison type value such as a date or string or numeric value, however it can also be a special token that is substituted at the moment the list is fetched.

In most cases tokens are for date ranges however there is one special token that applies to any data type `*NULL*`.  When this token is specified as the `value` property value the list will be filtered by null (empty) values for all data types using the `op` comparison Equality operator `=` or in any other operator case it will be treated as if the operator was `!=` Not equal.

Tokens for date ranges generally provide a *relative* to the current moment (and time zone) pre-defined range of dates.  This means the filter can be saved and re-used and the date range will always filter *relative* to the current date and time in the *user's own time zone* (as specified in their UserOptions object).  So, for example, if two users are set to two different time zones they will get different results for some of these filters depending on whether that token is a relative one or absolute.  

For example the `{[past]}` token is relative to the current date and time but it is unaffected by any time zone considerations whereas the `{[yesterday]}` token takes into consideration the user's time zone when filtering.

These are the available tokens for date filters:

| TOKEN | MEANING |
| ----- | ------------------------------ |
| {[yesterday]} | Include records where `fld` contains a date and time between 12:00 am yesterday morning (zero hour) and 12:00 am today |
| {[today]} | Include records where `fld` contains a date and time between 12:00 am today and 12:00 am tomorrow |
| {[tomorrow]} | Include records where `fld` contains a date and time between 12:00 am tomorrow and 12:00 am the day after tomorrow |
| {[lastweek]} | Include records where `fld` contains a date and time between two sundays ago at midnight and last sunday at midnight |
| {[thisweek]} | Include records where `fld` contains a date and time between last sunday at midnight and next sunday at midnight |
| {[nextweek]} | Include records where `fld` contains a date and time between next sunday at midnight and the sunday after that (+7 days) at midnight |
| {[lastmonth]} | Include records where `fld` contains a date and time between 12:00 am the first day of last month and 12:00 am the first day of the current month |
| {[thismonth]} | Include records where `fld` contains a date and time between 12:00 am the first of this month and 12:00 am the first of next month |
| {[nextmonth]} | Include records where `fld` contains a date and time between 12:00 am the first of next month and 12:00 am the first day of the second month from now |
| {[14daywindow]} | Include records where `fld` contains a date and time between 12:00 am 7 days before today and 12:00 am 15 days after the first date |
| {[past]} | Include records where `fld` contains a date and time that occurs before now |
| {[future]} | Include records where `fld` contains a date and time that occurs after now |
| {[lastyear]} | Include records where `fld` contains a date and time between 12:00 am January 1st last year and 12:00 am January 1st this year |
| {[thisyear]} | Include records where `fld` contains a date and time between 12:00 am January 1st this year and 12:00 am January 1st next year |
| {[last3months]} | Include records where `fld` contains a date and time from now minus 3 months to now |
| {[last6months]} | Include records where `fld` contains a date and time from now minus 6 months to now |
| {[lastcalendaryear]} | Include records where `fld` contains a date and time from now minus 365 days to now |
| {[yeartodate]} | Include records where `fld` contains a date and time from 12:00 am January 1st this year to now |
| {[past90days]} | Include records where `fld` contains a date and time from now minus 90 days to now |
| {[past30days]} | Include records where `fld` contains a date and time from now minus 30 days to now |
| {[past24hours]} | Include records where `fld` contains a date and time from now minus 24 hours to now |
| {[january]} | Include records where `fld` contains a date and time between 12:00 am January 1st this year and 12:00 am February 1st this year |
| {[february]} | Include records where `fld` contains a date and time between 12:00 am February 1st this year and 12:00 am March 1st this year |
| {[march]} | Include records where `fld` contains a date and time between 12:00 am March 1st this year and 12:00 am April 1st this year |
| {[april]} | Include records where `fld` contains a date and time between 12:00 am April 1st this year and 12:00 am May 1st this year |
| {[may]} | Include records where `fld` contains a date and time between 12:00 am May 1st this year and 12:00 am June 1st this year |
| {[june]} | Include records where `fld` contains a date and time between 12:00 am June 1st this year and 12:00 am July 1st this year |
| {[july]} | Include records where `fld` contains a date and time between 12:00 am July 1st this year and 12:00 am August 1st this year |
| {[august]} | Include records where `fld` contains a date and time between 12:00 am August 1st this year and 12:00 am September 1st this year |
| {[september]} | Include records where `fld` contains a date and time between 12:00 am September 1st this year and 12:00 am October 1st this year |
| {[october]} | Include records where `fld` contains a date and time between 12:00 am October 1st this year and 12:00 am November 1st this year |
| {[november]} | Include records where `fld` contains a date and time between 12:00 am November 1st this year and 12:00 am December 1st this year |
| {[december]} | Include records where `fld` contains a date and time between 12:00 am December 1st this year and 12:00 am January 1st next year |



For example the following filter array JSON (in string format) will return only items where the Name starts with "Bob" and the Notes field exactly equals "Aardvark":

`"filter": "[  {\"fld\": \"name\",    \"op\": \"%-\",    \"value\": \"Bob\"  },  {    \"fld\": \"notes\",    \"op\": \"=\",    \"value\": \"Aardvark\"  }]"
}`

If no filter parameter is provided no filtering will be done on the list.
