Model Run API
The Model Run API provides create, read, update, and delete (CRUD) capabilities for runs of a project.
A run is a collection of interactions with the project and its model. Every time you want to interact with a project, you need to create a new run.
The Model Run API supports the following methods:
The Model Run API operates on the following resources / data structures:
POST
Use the Model Run API POST
method to create a new run.
Create a New Run
Method: POST
URI:
/v2/model/run
Headers:
Content-Type: application/json
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
Body: JSON object with the required fields:
account
: The Account ID. This is the Team ID (for team projects) or User ID (for personal projects).project
: The Project ID.model
: The primary model file.- For a complete list of fields, see details on the run record.
Return Status:
200
: Successfully created run400
: Invalid request (e.g. invalid account or project)500
: Server error while starting the run (e.g. syntax errors in the model)
Return Body:
The new run record (JSON object) just created.
Example:
curl -X POST \
'https://api.forio.com/v2/model/run/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{"account": "acme", "project": "supply-chain-game", "model": "model.py"}'
Example Response:
{
"user": {
"id": "d730a1b5-5451-4627-b16d-f3a7ed63f039",
"userName": "jsmith@acme.com",
"firstName": "j",
"lastName": "smith"
},
"files": null,
"morphology": "MANY",
"created": "2016-03-07T21:29:04.244Z",
"lastModified": "2016-03-07T21:29:04.244Z",
"id": "000001533965543534cd21a606beb8feb9c7",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"active": true,
"initialized": true,
"scope": null
}
Notes:
- See the error record for more information on how to interpret possible errors.
Create a New Run Using an Existing Run ("Reset")
Sometimes you know that you will be creating the same kind of run — a run with the same account
, project
, and model
— many times. In this case, you can use a variant of the Model Run API POST
method to help optimize performance and speed up the creation of the new run: you can create a new run based on an existing run. The new run reuses the existing model session on the Epicenter backend server.
Method: POST
URI:
/v2/model/run/
{original run id}
Headers:
Content-Type: application/json
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
Body: {}
Return Status:
200
: Successfully created run400
: Invalid request (e.g. invalid account or project)500
: Server error while starting the run (e.g. syntax errors in the model)
Return Body: The new run record (JSON object) just created.
Example:
curl -X POST \
'https://api.forio.com/v2/model/run/00000152a9aa44e228363a623c14ed07ba34' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{}'
Example Response:
{
"user": {
"id": "d730a1b5-5451-4627-b16d-f3a7ed63f039",
"userName": "jsmith@acme.com",
"firstName": "j",
"lastName": "smith"
},
"files": null,
"morphology": "MANY",
"created": "2016-03-07T21:29:04.244Z",
"lastModified": "2016-03-07T21:33:52.443Z",
"id": "000001533965543534cd21a606beb8feb9d6",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"active": true,
"initialized": true,
"scope": {}
}
Notes:
This request is valid both for existing runs that are currently in memory and for existing runs that are currently only in the database. (See more information on run persistence.)
This request:
Note that relevant, existing run properties are copied from the original run to the new run. For example,
scope.group
is copied, butsaved
andinitialized
have their values set as for a new run created throughPOST /v2/model/run
. See more information on the run record.Optionally, you can pass in any of the same fields you pass in when creating a new run from scratch. For example, if you want to have the run in a different group, pass in
{"scope": {"group": "newGroup"}}
instead of{}
in the body of this request.See the error record for more information on how to interpret possible errors.
Retrieve Many Runs
Most of the time when you retrieve one or more run records, you use the GET
request, described below.
However, sometimes when you would like to use the GET
method for an API, your request may require a very long URI, for example: https://api.forio.com/v2/model/run?id=000001533965543534cd21a606beb8feb9d6&id=000002734969543534cd21a606beb8feb31c&id=...
.
For these situations, Epicenter APIs support the option of using a POST
method with additional parameters in place of the GET
method.
Method: POST
URI:
/v2/model/run?_method=GET
Headers:
Content-Type: application/json
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
Body: JSON object describing the query. For example:
{"id": ["000001533965543534cd21a606beb8feb9d6", "000002734969543534cd21a606beb8feb31c"]}
Return Status:
200
: Successfully retrieved runs
Return Body: An array of records (JSON objects) returned by the query.
Example:
curl -X POST \
'https://api.forio.com/v2/model/run?_method=GET' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{"id": ["000001533965543534cd21a606beb8febb03", "000001533965543534cd21a606beb8febb07"] }'
Example Response:
[
{
"user": null,
"files": null,
"morphology": "MANY",
"created": "2016-03-07T23:38:53.850Z",
"lastModified": "2016-03-07T23:38:53.850Z",
"id": "000001533965543534cd21a606beb8febb03",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"initialized": true,
"scope": null
},
{
"user": null,
"files": null,
"morphology": "MANY",
"created": "2016-02-08T21:18:49.434Z",
"lastModified": "2016-02-08T21:18:49.434Z",
"id": "000001533965543534cd21a606beb8febb07",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"initialized": true,
"scope": null
}
]
GET
You can retrieve the run record for any run using the Run API GET
method.
Retrieve One Run
Method: GET
URI:
/v2/model/run/
{run id}
Headers:
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
Body: None
Return Status:
200
: Successful response400
: Invalid request
Return Body: The run record (JSON object) for this run.
Example:
curl -G \
'https://api.forio.com/v2/model/run/000001533965543534cd21a606beb8feb9d6' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response:
{
"user": {
"id": "d730a1b5-5451-4627-b16d-f3a7ed63f039",
"userName": "jsmith@acme.com",
"firstName": "j",
"lastName": "smith"
},
"files": null,
"morphology": "MANY",
"created": "2016-03-07T21:29:04.244Z",
"lastModified": "2016-03-07T21:33:52.443Z",
"id": "000001533965543534cd21a606beb8feb9d6",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"active": true,
"initialized": true,
"scope": {}
}
Notes:
- The run is retrieved from memory if available. If the run is not in memory, it is retrieved from the database.
Retrieve One or More Runs
When you retrieve runs using filters and sorts, all runs are retrieved from the database.
Method: GET
URI:
/v2/model/run/
{filter, sort}
URI Optional Parameters:
The {filter} is a set of query parameters, and takes the format:
?field1=value1&field2=value2
.Fields available for filtering include:
id
,account
,project
,model
,saved
,scope.worldId
.The {sort} is a query parameter indicating the field by which to sort the runs before they are returned, and a second query parameter with the direction of the sort. This takes the format:
?sort=field1&direction=dir
.Fields available for sorting include:
account
,project
,model
,created
,lastModified
. The default islastModified
.The
direction
can beasc
(ascending) ordesc
(descending). The default isdesc
.See more information on the run record for a complete description of these fields.
Headers:
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
(Optional)
Range: records
{i}-
{j}- Depending on your filter, this request may return many run records. The default page size is 100. You can limit the number of records returned by adding the
Range
header.
- Depending on your filter, this request may return many run records. The default page size is 100. You can limit the number of records returned by adding the
Body: None
Return Status:
200
: Successful response206
: Successfully retrieved the partially complete response (for example if you request records 0-20 with theRange
header and there are 35 records)400
: Invalid request416
: No records are found in a given search range (for example if you request records 10-15 with theRange
header and there are only 8 records)
Return Body: An array of JSON objects with the run records matching the filter. If you have specified a Range
header in the request, or if your request returns more than 100 run records, this may not be all of the run records matching your filter. The array includes only those records indicated in the Content-Range
header.
Example (filtering):
curl -G \
'https://api.forio.com/v2/model/run/?id=00000152a9aa44e228363a623c14ed07ba34' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response:
[
{
"user": null,
"files": null,
"morphology": "MANY",
"created": "2016-02-08T21:18:49.434Z",
"lastModified": "2016-02-08T21:18:49.434Z",
"id": "00000152a9aa44e228363a623c14ed07ba34",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"initialized": true,
"scope": null
}
]
Example (filtering and sorting):
curl -G \
'https://api.forio.com/v2/model/run/?account=acme&project=supply-chain-game&sort=created&direction=asc' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response:
[
{
"user": null,
"files": null,
"morphology": "MANY",
"created": "2016-02-08T21:18:49.434Z",
"lastModified": "2016-02-08T21:18:49.434Z",
"id": "00000152a9aa44e228363a623c14ed07ba34",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"initialized": true,
"scope": null
},
... // other run records matching the filter, if any
// ordered by created, ascending
]
Notes:
- All runs are retrieved from the database.
- If the
sort
parameter is not specified in the URI, the default sort is bylastModified
. - If the
direction
parameter is not specified in the URI, the default direction isdesc
. Optionally, you can add the query parameter
?include=active
to your request. Then, the response includes theactive
field of the run record. This istrue
for runs that are currently in memory andfalse
for runs that are only in the database.Whether or not you add the
Range
header to your request, the response header contains:Content-Range: records i-j/k
where
i
is the index of the first record returned,j
is the index of the last record returned, andk
is the total number of records in the result set, or*
if that number is computationally infeasible (for instance, because you are querying across multiple projects).For example,
Content-Range: records 0-9/57
orContent-Range: records 20-29/*
.If no records are returned, the response body is empty and the
Content-Range
header in the response isContent-Range: records -/0
If you leave off the start index, this is considered an implied start index of 0 rather than an invalid range. The response header includes status code of
200
or206
depending on the ending index.This use of the
Range
header is part of the RFC 2616 (see details in Section 14.16 and 14.35).
PATCH
You can update some of the data in the run record using the Model Run API PATCH
method.
Update Run Data
Method: PATCH
URI:
/v2/model/run/
{run id}
Headers:
Content-Type: application/json
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
Body: JSON object whose fields are variable names and whose values are the updated variable values, e.g. { "fieldName1": "fieldValue1", "fieldName2": "fieldValue2"}
.
Return Status:
200
: Successful response, property updated400
: Invalid property or property that is read-only (see the run record for complete list of properties)
Return Body: A JSON object with the updated data.
Example:
curl -X PATCH \
'https://api.forio.com/v2/model/run/00000152fbfbeae5d4e225640aebaef9abd7' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{ "saved": true }'
Example Response:
{
"saved": true
}
Notes:
- Currently you can only update the
saved
andinitialized
properties. These are flags in every run record that you can use to mark runs. (They are not related to whether the run is persisted in the database.)
DELETE
If you no longer need a particular run, you can remove it from memory using the Run API DELETE
method.
Runs must be in memory in order for you to update variables or call operations on them. Runs are automatically replayed, and brought back into memory, when you attempt to update a model variable or call a model operation.
Remove One Run from this Project
Method: DELETE
URI:
/v2/model/run/
{run id}
Headers:
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
Body: None
Return Status:
200
: Successful response, run deleted from memory
Return Body: The deleted run record.
Example:
curl -X DELETE \
'https://api.forio.com/v2/model/run/000001533965543534cd21a606beb8febaeb' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response:
{
"user": {
"id": "d730a1b5-5451-4627-b16d-f3a7ed63f039",
"userName": "jsmith@acme.com",
"firstName": "j",
"lastName": "smith"
},
"files": null,
"morphology": "MANY",
"created": "2016-03-07T23:29:48.704Z",
"lastModified": "2016-03-07T23:29:48.704Z",
"id": "000001533965543534cd21a606beb8febaeb",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"initialized": true,
"scope": null
}
Notes:
- IMPORTANT: Note that this request only removes the run from memory on the Epicenter servers; it does not remove the run from the Epicenter backend database. See more information on run persistence.
Remove Multiple Runs from this Project
Method: DELETE
URI:
/v2/model/run?id=
{run id1}&id=
{run id2}
Headers:
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
Body: None
Return Status:
200
: Successful response, run deleted from memory
Return Body: An array of the deleted run records.
Example:
curl -X DELETE \
'https://api.forio.com/v2/model/run?id=000001533965543534cd21a606beb8febb03&id=000001533965543534cd21a606beb8febb07' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response:
[
{
"user": {
"id": "d730a1b5-5451-4627-b16d-f3a7ed63f039",
"userName": "jsmith@acme.com",
"firstName": "j",
"lastName": "smith"
},
"files": null,
"morphology": "MANY",
"created": "2016-03-07T23:38:36.896Z",
"lastModified": "2016-03-07T23:38:36.896Z",
"id": "000001533965543534cd21a606beb8febb03",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"initialized": true,
"scope": null
},
{
"user": {
"id": "d730a1b5-5451-4627-b16d-f3a7ed63f039",
"userName": "jsmith@acme.com",
"firstName": "j",
"lastName": "smith"
},
"files": null,
"morphology": "MANY",
"created": "2016-03-07T23:38:53.850Z",
"lastModified": "2016-03-07T23:38:53.850Z",
"id": "000001533965543534cd21a606beb8febb07",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"initialized": true,
"scope": null
}
]
Notes:
- IMPORTANT: Note that this request only removes the run from memory on the Epicenter servers; it does not remove the run from the Epicenter backend database. See more information on run persistence.
HEAD
You can retrieve metadata about a run using the Model Run API HEAD
method.
Retrieving Metadata about the Run Record
Method: HEAD
URI:
/v2/model/run/
{run id}
Headers:
Content-Type: application/json
Authorization: Bearer
{access token}- This can be either the user access token of any user (team member or end user) with access to the run, or the project access token for the project.
Body: None.
Return Status:
200
: Successful response, property updated
Return Body: None. Only headers are returned.
Example:
curl -X HEAD \
'https://api.forio.com/v2/model/run/00000152fbfbeae5d4e225640aebaef9abd7' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response:
Only headers are returned.
Notes:
This request allows you to retrieve information written in response headers, including server information and resource last modified information, without having to retrieve all the data associated with a
GET
request.In particular, this is useful for verifying whether you are retrieving the run from memory or from the database:
- The
Pragma
field in the response header is present and set topersistent
if this run is persisted in the Epicenter backend database. - The
Pragma
field is not present in the response header if the run is only in memory on the Epicenter servers.
- The
OPTIONS
For any Epicenter API, use the OPTIONS
method to view reference information on properties and arguments of that API.
Method: OPTIONS
URI: /v2/model/run
Example:
curl -X OPTIONS 'https://api.forio.com/v2/model/run'
Data Structure
The Model Run API operates on the Run record data structure. When a run cannot be created, an error is returned.
Run Record
The Run record describes the run. It is returned in response to any POST
request. Either a Run record or an array of Run Records is returned in response to any GET
request.
Field | Required? | Description |
---|---|---|
id |
yes | The identifier of the run. Always included in a response; should not be included as part of a POST request. |
account |
yes | The Account ID of the account for which the run is created. This is the Team ID (for team projects) or User ID (for personal projects). Required when creating a run and always included in a response. |
project |
yes | The Project ID of the project for which the run is created. Required when creating a run and always included in a response. |
model |
yes | The name of the primary model file. This is the one file in the project where model execution should begin, and that explicitly exposes variables and operations. Required when creating a run and always included in a response. |
user |
no | Information about the user that created the run, including id , userName , firstName , lastName . If the access token used to create the run was a user access token, the user information is included; if it was a project access token, the user information is null. |
scope |
no | A description of where the run is available. Typically you use this if your project includes end users and groups; for example, the scope should always be passed in if this run belongs to an end user of your project.
|
created |
yes | When the run record was created, in ISO 8601 format. Always included in a response; should not be included as part of a POST request. |
lastModified |
yes | When the run record was most recently updated, in ISO 8601 format. Always included in a response; should not be included as part of a POST request. |
files |
no | Only relevant for Vensim models. If you are using a Vensim model and you have additional data to pass in to your model, pass a files object that includes name : value pairs. (Note that you'll also need to add this same files object to your Vensim Model Context file.) Each name can be any designation you like. Each value is name of the file to load. This file must be in your project's Model folder. For example: "files": {"data": "myData.xlsx"} or "files": {"file1": "myFirstFile.xlsx", "file2": "mySecondFile.xlsx"} . See a complete example in How To: Use External Data in Vensim. |
active |
yes | This field is true if the run is currently in memory, and false if the run is only in the database. (See more on run persistence.) Always included in a response; should not be included as part of a POST request. |
saved |
no | A flag in the run record, set to false when the run is created. You can set this field as needed; its value is not tied to run creation or run persistence. |
initialized |
no | A flag in the run record, set to true when the run is created. You can set this field as needed; its value is not tied to run creation or run persistence. |
morphology |
no | Read only and internal use only. |
**Example Run Record**
An example Run record returned as a response to a POST
request:
{
"user": {
"id": "d730a1b5-5451-4627-b16d-f3a7ed63f039",
"userName": "jsmith@acme.com",
"firstName": "j",
"lastName": "smith"
},
"files": null,
"morphology": "MANY",
"created": "2016-03-07T21:29:04.244Z",
"lastModified": "2016-03-07T21:29:04.244Z",
"id": "000001533965543534cd21a606beb8feb9c7",
"account": "acme",
"project": "supply-chain-game",
"model": "model.py",
"saved": false,
"active": true,
"initialized": true,
"scope": null
}
Error Record
The Error record describes the problem when a run cannot be created. It is returned in response to a POST
request that cannot be completed.
Error: 400 Invalid Request
When the POST
request cannot be completed because of a problem with the request body, the response is a 400
error.
Field | Required? | Description |
---|---|---|
fault |
yes | The kind of fault, if available. |
type |
yes | Kind of error, if available. |
run_id |
yes | The identifier of the run, if it was created. |
message |
yes | The specific error message. |
error |
yes | Boolean, set to true for all errors. |
**Example: 400 Error Record**
{
"fault": null,
"type": "model_not_found",
"run_id": "000001533965543534cd21a606beb8fec3a0",
"message": "Could not locate model(/opt/forio/files/projects/acme/supply-chain-game2/model/model.py)",
"error": true
}
Error: 500 Server Error
When the POST
request cannot be completed because of a problem with the model, the response is a 500
error.
Field | Required? | Description |
---|---|---|
cause |
yes | Specific cause, if available. |
context |
yes | Additional detail, if available. |
trace |
yes | The stack trace of the error, in the |
information |
yes | Additional detail, if available. |
type |
yes | Kind of error, if available. |
message |
yes | The specific error message, as provided by the environment listed in type . |
native |
yes | Internal use only. |
**Example: 500 Error Record**
{
"cause": null,
"context": null,
"trace": [
{
"type": "python",
"function": "__execute__",
"file": "/usr/local/lib/python3.4/dist-packages/epicenter-py3.5.egg/epicenter/worker/python/python_worker.py",
"line": 61
}
],
"information": null,
"type": "python",
"message": "SyntaxError: invalid syntax (model.py, line 7)",
"native": null
}