Getting Started with Modelshop APIs¶
The Modelshop Data API is organized around REST. Our API has simple to construct URLs and uses built in HTTP features for authentication and error handling. Below we will show basic examples of how to interact with the Modelshop Data API to send and retrieve data from Modelshop Models. These examples are built using the Requests Library for Python, but should provide clear examples of how to perform these tasks in your client language of choice. Additionally, the Modelshop Data API is highly flexible, with a wide array of optional parameters. This reference is not intended to be an exhaustive list of all options. For further detail, please see the complete API documentation.
Modelshop API Documentation <https://docs.modelshop.com/api/>
# Import the lib
import requests
For this example, we will be using a sample user (creatively name sampleuser) that has been created on a demo installation of Modelshop Server. Additionally, we have created a very simple model (SampleModel), owned by sampleuser to demonstrate sending and getting data. This model consists of a single DataList, with a single View into it.
Here we set up the parameters required to access this model and view as sampleuser.
server_url = "https://demo.modelshop.com/modelshop" # The base url for the location of the Modelshop installation.
username = "sampleuser" # Username for authentication
password = "P@ssword12345" # Password for authentication
model = "SampleModel" # The name of the model to be accessed
model_owner = "sampleuser" # The username of the user who owns the model, this can different from username if the model has been shared
view = "Accounts" # View to be used
Sample GET Requests¶
Get bulk records from a view¶
url = "{}/api/data/{}/{}/{}".format(server_url,model_owner,model,view)
r = requests.get(url, auth=(username, password))
r.json()
URL:
https://demo.modelshop.com/modelshop/api/data/sampleuser/SampleModel/Accounts
Response:
{'errors': [],
'resultsId': 299,
'success': True,
'totalRecords': 16,
'moreData': False,
'hasModelErrors': False,
'hasErrors': False,
'hasWarnings': False,
'hasInfos': False,
'moreMessages': False,
'viewStale': False,
'records': [{'id': 1,
'version': 34,
'accountId': '4551',
'name': 'James Smith',
'value': '212068.61'},
{'id': 2,
'version': 35,
'accountId': '9223',
'name': 'Michael Smith',
'value': '82570.24'},
{'id': 3,
'version': 36,
'accountId': '3830',
'name': 'Robert Smith',
'value': '119642.18'},
{'id': 4,
'version': 37,
'accountId': '4265',
'name': 'Maria Garcia',
'value': '138076.94'},
{'id': 5,
'version': 38,
'accountId': '5883',
'name': 'David Smith',
'value': '111261.13'},
{'id': 6,
'version': 39,
'accountId': '6234',
'name': 'Maria Rodriguez',
'value': '67762.81'},
{'id': 7,
'version': 40,
'accountId': '1099',
'name': 'Mary Smith',
'value': '138447.26'},
{'id': 8,
'version': 41,
'accountId': '6301',
'name': 'Maria Hernandez',
'value': '112133.83'},
{'id': 9,
'version': 42,
'accountId': '1032',
'name': 'Mark Jones',
'value': '75693.29'},
{'id': 10,
'version': 43,
'accountId': '9205',
'name': 'Ted Stevens',
'value': '144999.34'},
...
]}
Get limited bulk records from a view¶
url = "{}/api/data/{}/{}/{}".format(server_url,model_owner,model,view)
params = {
'limit' : 2
}
r = requests.get(url, auth=(username, password), params=params)
r.json()
URL: https://demo.modelshop.com/modelshop/api/data/sampleuser/SampleModel/Accounts?limit=2
Response:
{'errors': [],
'resultsId': 298,
'success': True,
'totalRecords': 16,
'moreData': True,
'hasModelErrors': False,
'hasErrors': False,
'hasWarnings': False,
'hasInfos': False,
'moreMessages': False,
'viewStale': False,
'records': [{'id': 1,
'version': 34,
'accountId': '4551',
'name': 'James Smith',
'value': '212068.61'},
{'id': 2,
'version': 35,
'accountId': '9223',
'name': 'Michael Smith',
'value': '82570.24'}]
}
Get records from a view using a simple filter¶
field = 'accountId' # The field to be filtered on
value = '1032' # The value to be used as a filter
url = "{}/api/data/{}/{}/{}/{}/{}".format(server_url,model_owner,model,view,field,value)
r = requests.get(url, auth=(username, password))
URL: https://demo.modelshop.com/modelshop/api/data/sampleuser/SampleModel/Accounts/accountId/1032
Response:
{'errors': [],
'resultsId': 301,
'success': True,
'totalRecords': 17,
'moreData': True,
'hasModelErrors': False,
'hasErrors': False,
'hasWarnings': False,
'hasInfos': False,
'moreMessages': False,
'viewStale': False,
'records': [{'id': 9,
'version': 42,
'accountId': '1032',
'name': 'Mark Jones',
'value': '75693.29'}]}
More advanced GET requests¶
The Modelshop REST APIs support more advanced queries, including compount filters and sorting. Filters can even include expressions that leverage Modelshop calculations.
Filters are UURL encoded Json arrays with the following fields (example):
[{ 'field' : 'accountId',
'type' : 'EQUALS',
'value' : 1032
},
{ 'field' : 'name',
'type' : 'LIKE',
'value' : 'Smith'
}]
URL: https://demo.modelshop.com/modelshop/api/data/sampleuser/SampleModel/Accounts?filter=[{'field':'accountId','type':'EQUALS','value':1032},{'field':'name','type':'LIKE','value':'Smith'}]
Note that after URL encoding the actual URL will look more like:
URL Encoded URL: `https://demo.modelshop.com/modelshop/api/data/sampleuser/SampleModel/Accounts?filter=%5B%7B%22field%22%3A%22accountId%22%2C%22type%22%3A%22EQUALS%22%2C%22value%22%3A%221032%5D%2C%7B%22ffield%22%3A%22name%22%2C%22type%22%3A%22LIKE%22%2C%22value%22%3A%22Smith%5C%22%5D%22%7D%5D
The possible values of type are:
EQUALS(“Equals”), LESS(“Less”), GREATER(“Greater”), LESSEQUAL(“Lessequal”), GREATEREQUAL(“Greaterequal”), NOTEQUAL(“Notequal”), LIKE(“Like”), NOTLIKE(“Notlike”), IN(“In”), NOTIN(“Notin”), EXPRESSION(“Expression”);
Similarly, an array of ‘sort’ query parameters can be added using the following format:
[{ 'property' : 'version',
'direction' : 'ASC'
},
{ 'property' : 'value',
'direction' : 'DESC'
}]
Sample PUT Request¶
url = "{}/api/data/{}/{}/{}".format(server_url,model_owner,model,view)
## Payload should be wrapped in a 'records' envelope
payload = {
'records': [
{
'accountId': '12345',
'name': 'John Snow',
'value': 1000000
}
]
}
r = requests.put(url, auth=(username, password), json=payload)
r.json()
URL: https://demo.modelshop.com/modelshop/api/data/sampleuser/SampleModel/Accounts
Response:
{'errors': [],
'resultsId': 0,
'success': True,
'totalRecords': 0,
'moreData': False,
'hasModelErrors': False,
'hasErrors': False,
'hasWarnings': False,
'hasInfos': False,
'moreMessages': False}
Using Access Tokens¶
Modelshop provides a way to access resources via API without requiring user authentication using Access Tokens. This mechanism is designed for temporary access only, for example when coordinating a transaction with a third-party software that does not have a direct Modelshop login, or when deploying Modelshop dashboards as an iFrame.
How it works¶
The query parameter ‘accessToken’ can be appended to many of the Modelshop APIs that are needed to work with the model, including retrieving and sending data, retrieving charts and dashboard access. The accessToken must be retrieved by an authenticated user and can be customized to not specify which resources can be accessed, but in many cases add additional filters to further restrict a sub-set of data that access is being granted to. Additionally, access tokens can be specified as one-time use or an expiration timestamp can be provided. Access tokens are designed to be temporary and will not persist through a server restart even when no expiration is provided.
Retrieving an access token¶
The following API is used to create or append to an access token.
api/modelutil/{userId}/{modelPath}/accesstoken/{itemType}/{itemName}/{accessLevel}
With the following parameters:
userId - The user id for the owner of the targeted model (not necessarily the logged in user)
modelPath - The path to the model in 'normalized' form (the model name preceded by any folders, e.g. MyFolder/MyModel)
itemType - Type of access: MODEL, DATAITEM, VIEW, CONNECTOR, DASHBOARD, etc.
itemName - The name of the access item
accessLevel - The level of access being requested: NONE, READ, WRITE, EDIT
expires - DateTime of expiration
onetime - True or false is a one-time access token
filter - Filter expression to limit the returned data
reference - Only return data that references this entity
accessToken - Use an existing accessToken and add this access to the chain
The return from this call will be a DefaultMessage, where the returnValue contains the Access Token which is formatted as a 32 character UUID in a format that resembles this: 1ae5bf66-4271-4159-a07c-891ccbbdf66d
Note that the call to retrieve an access token can include restricting qualifiers including filter and reference. These restrictors are similar to the filter and reference that can be added to API calls to retrieve data, charts and other assets. When added to the Access Token request, any API calls that use the Access Token will first apply these filters and reference restrictions prior to returning data. This technique allows the issuance of restricted access to data APIs (and iFrame components like dashboards) that will limit the data retrieved to a subset based on filtering.
The following two examples show calling to generate an access token for a dashboard in a model called CARES Act, and a subsequent call to chain additional access to a view on that dashboard using the same access token and including a filter to limit the data to only employers with more than 10 employees.
GET: http://localhost:8080/modelshop/api/modelutil/tomtobin/CARESAct/accesstoken/dashboard/Loan%20Details/WRITE
GET: http://localhost:8080/modelshop/api/modelutil/tomtobin/CARESAct/accesstoken/view/Loan/READ?accessToken=1ae5bf66-4271-4159-a07c-891ccbbdf66d&filter=%5B%7B%22field%22%3A%22currentEmployees%22%2C%22type%22%3A%22EXPRESSION%22%2C%22value%22%3A%22%3E10%22%7D%5D
Note that JSON elements sent as parameters (such as filters) need to be URI Encoded. Prior to encoding, the filter expression was an array with one filter:
[{"field":"currentEmployees","type":"EXPRESSION","value":">10"}]
Using an Access Token¶
Access tokens can be used to retrieve data without requiring a named user login to Modelshop. Access will still require some level of Modelshop login, but a client can login as a guest user prior to calling an API that accepts an Access Token (with the query parameter accessToken). By default, Modelshop instances are configured with a public/public user allowing anonymous access to APIs that require basic authorization, or additional guest users can be configured as needed.
Many standard APIs that access data accept an accessToken, including get data, put data, charts, cubes and dashboards. In general, modifying the model structure or administrator APIs are not accessible using an Access Token. If an accessToken is configured for one time use, the token will become invalid after the first API call using that token.
Using Access Tokens with dashboards¶
Additionally, dashboards in Modelshop can be published as independent URLs and iFrame code snippets. When calling a Modelshop dashboard, the caller can supply an accessToken parameter to grant access to an anonymous user to the dashboard content. With the current implementation, if the Access Token API is used to grant access to a dashboard, any views or charts included in that dashboard will also require that the token be granted access to the underlying resource.
Modelshop includes the ability to chain multiple Access Token privileges together under the same token. This allows one Access Token to provide access to a dashboard, as well as all of the views and charts that may be included in the dashboard. Other dashboard widgets like gauges and tables are available once the dashboard is accessible.
To chain multiple privileges together on the same Access Token, simply provide the first access token as a query parameter to subsequent calls requesting additional privileges.
An example iFrame call to a dashboard that includes an accessToken query parameter is shown below.
<iframe frameborder="0" src="http://localhost:8080/modelshop/index.jsp#model=tomtobin:MODEL:CARESAct&panel=DASHBOARD:Loan~Details&displaydashboard&accessToken=1ae5bf66-4271-4159-a07c-891ccbbdf66d" style="overflow: hidden; height: 100%; width: 100%"></iframe>