# REST data source JSON format For Hypersync apps that retrieve data from a REST data source, the [RestDataSourceBase](/hypersync-sdk/sdk-005-data-sources) class makes it possible to extract, transform, and sort multiple data sets without writing code. The `/json/dataSource.json` file is used to define these datasets. At the top level, a `dataSource.json` file should expose an object with three properties: - `baseUrl` - `dataSets` - `messages` > **Note**: Only `dataSets` is required. The other two properties are both optional. ## baseUrl The `baseUrl` property defines a common root URL for all endpoints in the `dataSets` collection. When specified in the `dataSource.json` file, each dataset’s `url` value is treated as relative to this base URL. If your datasets reference APIs that do not share a common root, omit the `baseUrl` property and provide full URLs in each dataset definition. ## dataSets A dataset is a named object that represents a specific data item or collection (e.g. an array) retrievable from a data source. Datasets can—and should—be reused across multiple proof types, and they can also support non-proof scenarios such as collecting user data during the `validateCredentials` process. Each entry in the `dataSets` object corresponds to a single dataset used by your custom Hypersync app. Each dataset object contains the following properties: | Property | Required? | Description | | --- | --- | --- | | `url` | Yes | Relative or full URL for the REST API. | | `method` | No | `GET`, `POST`, or `PATCH`. The default is `GET`. | | `body` | No | Body included in `POST` and `PATCH` requests. | | `result` | Yes | `object` or `array` | | `description` | No | A description of the dataset. | | `documentation` | No | Link to the REST API documentation. | | `joins` | No | Additional datasets to join to this dataset. | | `lookups` | No | Lookups that are retrieved for each object in the result. | | `filter` | No | The predicate applied to the retrieved data. | | `transform` | No | Transform to apply to each object in the filtered result. | | `sort` | No | Sort to apply to the transformed data. | | `pagingScheme` | No | The definition of pagination behavior. | ## Transforming data Objects returned from a REST API often need formatting before being shown to users. The `transform` property defines which fields to include in the dataset. Each property name becomes the dataset field, and its value maps to the corresponding field in the API’s JSON response. The simplest transformation is renaming fields. For example, in the [JSONata](https://jsonata.org/) example below, the dataset field `realname` maps to the API property `full_name`. The `realname` field is then referenced in your `proof.json`. ### Transform with JSONata Sometimes API data needs to be transformed before it can be used in a dataset. The Hypersync SDK supports transformations using JSONata, a powerful query and transformation language with an extensive library of expressions. **Examples** - Map the API field `full_name` to the dataset field owner, using username as a fallback if `full_name` is empty. - Combine values from the `roles` array into a single string for the `role` field. - Convert the `last_login_time` value from a Unix timestamp (seconds) to a readable date. Refer to the [official JSONata documentation](https://docs.jsonata.org/overview) for a complete list of operators and functions. #### Example ``` { "$schema": "https://cdn.jsdelivr.net/gh/Hyperproof/hypersync-sdk/schema/restDataSource.schema.json", "baseUrl": "https://THE_SERVICE.com/api/v2", "dataSets": { "users": { "description": "Returns a list of all the users", "documentation": "", "url": "/v1/objects/user", "transform": { "username": "username", "realname": "full_name", "owner": "[(full_name) = ''] ? username : full_name", "email": "email", "role": "$join([roles], ', ')" "enabled": "enabled", "last_login_time": "$fromMillis(last_login_time * 1000)", }, "result": "array" } } } ``` ### Transform with value lookups APIs often return values that need to be remapped for readability or consistency. For example, an API might return a user status of `active` or `deactivated`, which you may want to display as "Active" and "Inactive". The `valueLookups` object in the `dataSource.json` enables this mapping without writing code. Each property acts as a map; keys represent the original API values, and their corresponding values define the replacement strings. Once defined, mappings in `valueLookups` can be applied in your datasets using the `$vlookup` function. #### Example ``` { "$schema": "https://cdn.jsdelivr.net/gh/Hyperproof/hypersync-sdk/schema/restDataSource.schema.json", "baseUrl": "https://THE_SERVICE.com/api/v2", "dataSets": { "currentUser": { "description": "Returns information about the authorized user.", "documentation": "https://THE_SERVICE.com/docs/api/users/me", "url": "users/me", "transform": { "username": "username", "firstName": "givenName", "lastName": "surname" }, "result": "object" }, "groups": { "description": "Returns a list of all the groups in My Service.", "documentation": "https://THE_SERVICE.com/docs/api/groups", "url": "groups", "transform": { "id": "id", "groupName": "groupName", "members": "memberCount" }, "result": "array" }, "users": { "description": "Returns a list of all the users in My Service.", "documentation": "https://THE_SERVICE.com/docs/api/users", "url": "users", "transform": { "id": "id", "firstName": "givenName", "lastName": "surname", "email": "emailAddress", "status": "$vlookup('statuses', status)" }, "result": "array" } }, "valueLookups": { "statuses": { "active": "Active", "deactivated": "Inactive" } } } ```