Run API
The Run API is a RESTful API that collects common tasks around creating and updating runs, variables, and data in one endpoint.
It provides largely the same functionality as the lower-level Data API and Model APIs, but organized around particular user interactions with the project ("runs").
The Run API supports the following methods:
The Run API operates on the following resources / data structures:
POST
You can use the POST
request to create new runs and to call model operations on existing runs.
Create a New Run
Method: POST
URI:
/v2/run/
{account id}/
{project 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 with the required fields:
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 (examples: missing required field; invalid field added; account, project, or model file not found)500
: Server error while starting the run (example: syntax errors in the model)
Return Body:
The new run record (JSON object) just created.
Example:
curl -X POST \
'https://api.forio.com/v2/run/acme/supply-chain-game' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{"model": "model.py"}'
Example Response:
{
"morphology": "MANY",
"id": "000001539d43a51db44159ddb1a354e484df",
"user": {
"firstName": "j",
"lastName": "smith",
"id": "233ef9a8-af8e-41ad-84ba-9a21097f6f55",
"userName": "jsmith@acme.com",
"email": "jsmith@acme.com"
},
"model": "model.py",
"scope": null,
"ephemeral": null,
"created": "2016-03-22T17:17:46.092Z",
"initialized": true,
"active": true,
"project": "supply-chain-game",
"lastModified": "2016-03-22T17:17:46.092Z",
"account": "acme",
"files": null,
"variables": null,
"saved": false,
"trashed": false
}
Notes:
- In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
- See the error record for more information on how to interpret possible errors.
Call an Operation for One Run
Method: POST
URI:
/v2/run/
{account id}/
{project id}/
{run id}/operations/
{name of operation}
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:
arguments
: An array of the arguments for the operation.- For a complete list of fields, see details on the operation record.
Return Status:
200
: Successfully called operation400
: Invalid request (examples: unrecognized field in request body; operation not defined in model)
Return Body:
JSON object with the name
of the operation, the arguments
passed in, and the result
(return value) of the operation, if any. For a complete list of fields, see the operation record.
Example:
curl -X POST \
'https://api.forio.com/v2/run/acme/supply-chain-game/000001539d43a51db44159ddb1a354e48506/operations/estimate' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{"arguments": [ "input string", 25, true ]}'
Example Response:
{
"name": "estimate",
"arguments": [ "input string", 25, true ],
"result": 20.44
}
Notes:
- In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
- General errors with API usage, such as making a call without appropriate permissions, simply return the appropriate HTTP status code. Specific errors because of a problem with the model operation itself return a complete error record.
PATCH
You can use the PATCH
request to update the values of run data or model variables associated with the run.
Important: You can update run data at any time. However:
- You can only update model variables (that is, variables associated with the run) if the run is in memory. Runs are automatically replayed (and so brought back into memory) when you
PATCH
a variable. - For Vensim, you can only update model variables in the current time step.
- In general, the preferred way to update model variables is to call a method from the model and have the method persist the variables (using the
record()
statement if your model is in Python).
Update Run Data
Method: PATCH
URI:
/v2/run/
{account id}/
{project id}/
{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 with fields (names / values) you want to update. For a complete list of fields, see details on the run record.
Return Status:
200
: Successfully updated run400
: Invalid request
Return Body:
JSON object with the updated data.
Example:
curl -X PATCH \
'https://api.forio.com/v2/run/acme/supply-chain-game/000001539d43a51db44159ddb1a354e48506' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{"saved": true }'
Example Response:
{
"saved: true
}
Notes:
- In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
- Any data that you pass in here is added to the run data. That is, your request body can include both fields that are already part of the run record, and fields that are not initially part of the run record, e.g.
{"saved": true, "scenario": "A", "level": "basic"}
.
Update Run Data for One or More Runs
For the special case of the run record fields saved
, closed
, and trashed
, you can update these fields for multiple runs at once.
Method: PATCH
URI:
/v2/run/
{account id}/
{project id}/
{filter}
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 fields (names / values) you want to update. Available fields include saved
, closed
, and trashed
.
Return Status:
204
: Successfully updated runs400
: Invalid request
Return Body:
- None
Example:
curl -X PATCH \
'https://api.forio.com/v2/run/acme/supply-chain-game/;saved=false' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{"saved": true }'
Example Response:
For a successful request, no response is returned.
Notes:
- In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
- All runs matching the filter are updated.
- Only the fields
saved
,closed
, andtrashed
can be updated using this bulk update format.
Update Variables for One Run
Method: PATCH
URI:
/v2/run/
{account id}/
{project id}/
{run id}/variables
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, variables updated409
: Invalid request, conflict (examples: variable not defined in model; value provided for update is not compatible with variable type)
Return Body:
A JSON array with the variables updated and their current (newly updated) values.
Example:
curl -X PATCH \
'https://api.forio.com/v2/run/acme/supply-chain-game/000001539d43a51db44159ddb1a354e48506/variables' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
--data '{"sample_int": 16, "sample_dict[\"day\"]": "tuesday", "sample_array[1]": 300}'
Example Response:
{
"sample_int": 16,
"sample_dict[\"day\"]": "tuesday",
"sample_array[1]": 304
}
Notes:
- In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
- The variable names may include hard-coded array indices (
name[index]
) or object fields (name.field
) if desired. Array indices are modeling-language dependent. - If the variable is in a separate scope, that scope must be included in the variable name in the URI (
myModule.sample_string
). - The body of the requst must be valid JSON. Therefore, for boolean variables in Python models,
- You can use boolean values directly:
{ "sample_bool": true }
. - You can use the Python convention for boolean values only if you pass the string value:
{ "sample_bool": "True" }
.
- You can use boolean values directly:
- For arrayed variables in Vensim models, by default the time step is the last index (
name[index, time step]
). Use the model context file to specify whether the time step is the first or last index. (Note that for arrayed constants in Vensim models, there is no time index.) - For Vensim "LOOKUP" variables, the Epicenter format is an array. Each array element is itself an array with two elements: the x-y pairs from the original Vensim variable. When using the
PATCH
method, update the entire Epicenter representation (replace all values); you can change the number of ordered pairs if desired. For example:- Original Vensim LOOKUP representation:
[(2000,0)-(2010,2)],(2000,1),(2005,.5),(2010,1)
- Epicenter representation:
[ [2000,1], [2005,.5], [2010,1] ]
- Original Vensim LOOKUP representation:
- For Vensim models, variables designated as "CONSTANT" or "LOOKUP" variables can only be changed at the start of the simulation run (before the Vensim
startGame
operation is called). - For additional examples of working with complex variables (e.g. multidimensional arrays, lists, dicts, etc.), see the specific language pages:
Alternatively, you can include the "variables" specifically in the request body, rather than the URI. For example:
curl -X PATCH \ 'https://api.forio.com/v2/run/acme/supply-chain-game/3575dd84-272f-4ffe-ad64-46d1d621da0a' \ --header 'Content-Type:application/json' \ --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \ --data '{"variables": {"sample_int": 20, "sample_string": "hello again"}}'
Then the response is:
{ "variables": { "sample_int": 20, "sample_string": "hello again" } }
- See the error record for more information on how to interpret possible errors.
GET
Retrieve One Run
Method: GET
URI:
/v2/run/
{account id}/
{project id}/
{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/run/acme/supply-chain-game/000001533965543534cd21a606beb8feb9d6' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response:
{
"morphology": "MANY",
"id": "000001539d43a51db44159ddb1a354e484df",
"user": {
"firstName": "j",
"lastName": "smith",
"id": "233ef9a8-af8e-41ad-84ba-9a21097f6f55",
"userName": "jsmith@acme.com"
},
"model": "model.py",
"scope": null,
"created": "2016-03-22T17:17:46.092Z",
"initialized": true,
"active": true,
"project": "supply-chain-game",
"lastModified": "2016-03-22T17:17:46.092Z",
"account": "acme",
"files": null,
"saved": false,
"trashed": false
}
Notes:
- In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
- 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/run/
{account id}/
{project id}/
{filter, sort}
URI Optional Parameters:
The {filter} is a set of matrix parameters, and takes the format:
;field1=value1;field2=value2
.Fields available for filtering include:
id
,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:
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:
curl -G \
'https://api.forio.com/v2/run/acme/supply-chain-game/;saved=true?sort=lastModified&direction=asc' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response:
[
{
"morphology": "MANY",
"id": "000001539d43a51db44159ddb1a354e484df",
"user": {
"firstName": "j",
"lastName": "smith",
"id": "233ef9a8-af8e-41ad-84ba-9a21097f6f55",
"userName": "jsmith@acme.com"
},
"model": "model.py",
"scope": null,
"created": "2016-03-22T17:17:46.092Z",
"initialized": true,
"active": true,
"project": "supply-chain-game",
"lastModified": "2016-03-22T17:17:46.092Z",
"account": "acme",
"files": null,
"saved": true,
"trashed": false
},
... // other run records matching the filter, if any
// ordered by lastModified, 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
.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).
Retrieve Variables as Part of Each Run Record
You can use either the GET
request for one run or the GET
request for many runs and append ?include=
to also return specific model variables in the body of the run record.
Method: GET
URI:
/v2/run/
{account id}/
{project id}/
{run id or filter}?include=
{comma-separated list of variable names}
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 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 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 request404
: Variable not found, when the URI uses the{run id}
format and the run is in memory (for example:GET /v2/run/acme/supply-chain-game/1234/?include=badvar
)410
: Variable not found (not recorded), when the URI uses the{filter}
format, or when the URI uses the{run id}
format but the run is not in memory (for example:GET /v2/run/acme/supply-chain-game/;saved=true/?include=badvar
)416
: 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:
- If the URI includes a run id directly, the response is the run record, with the named variables also included.
- If the URI includes a filter (even if the filter is simply
;id=myRunId
), the response is an array of such run records.- In the case of filtering only, if you have specified a
Range
header in the request, or if your request returns more than 100 run records, the response may not be all of the run records matching your filter. The response includes only those records indicated in theContent-Range
header.
- In the case of filtering only, if you have specified a
- See the run record for more information on specific fields returned.
Example (single run id):
curl -G \
'https://api.forio.com/v2/run/acme/supply-chain-game/000001539d43a51db44159ddb1a354e48542?include=sample_dict,sample_int,sample_array[2]' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response (single run id):
{
"morphology": "MANY",
"id": "000001539d43a51db44159ddb1a354e48542",
"user": {
"firstName": "j",
"lastName": "smith",
"id": "233ef9a8-af8e-41ad-84ba-9a21097f6f55",
"userName": "jsmith@acme.com"
},
"model": "model.py",
"variables": {
"sample_array[2]": 6,
"sample_int": 16,
"sample_dict": {
"day": "tuesday",
"month": 2
}
},
"scope": null,
"created": "2016-03-22T18:00:14.059Z",
"initialized": true,
"active": false,
"project": "supply-chain-game",
"lastModified": "2016-03-22T18:00:14.059Z",
"account": "acme",
"files": null,
"saved": true,
"trashed": false
}
Example (filter):
curl -G \
'https://api.forio.com/v2/run/acme/supply-chain-game/;saved=true?include=sample_dict,sample_int,sample_array' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response (filter):
[
{
"morphology": "MANY",
"id": "000001539d43a51db44159ddb1a354e48542",
"user": {
"firstName": "j",
"lastName": "smith",
"id": "233ef9a8-af8e-41ad-84ba-9a21097f6f55",
"userName": "jsmith@acme.com"
},
"model": "model.py",
"variables": {
"sample_array": [
2,
4,
6,
8
],
"sample_int": 16,
"sample_dict": {
"day": "tuesday",
"month": 2
}
},
"scope": null,
"created": "2016-03-22T18:00:14.059Z",
"initialized": true,
"active": false,
"project": "supply-chain-game",
"lastModified": "2016-03-22T18:00:14.059Z",
"account": "acme",
"files": null,
"saved": true,
"trashed": false
},
... // other run records matching the filter, if any
]
Notes:
In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
When using a single run id in the URI,
- The run is retrieved from memory if available. If the run is not in memory, it is retrieved from the database.
- If the run is in memory, the
variables
in the response includes all (requested) variables. However, if the run is only in the database, thevariables
only includes (requested) variables that have been explicitly saved. (Variables are saved to the database usingEpicenter.record()
or similar, see Writing your model.) - The variable name may include hard-coded array indices (
name[index]
) or object fields (name.field
) if desired. Array indices are modeling-language dependent.
When using a filter in the URI,
- When reading from many runs, all information is pulled from the database, regardless of whether the run is also currently in memory. As a consequence, only variables that have been explicitly saved to the database are available for query using this method. (Variables are saved to the database using
Epicenter.record()
or similar, see Writing your model.) - The variable name may NOT include hard-coded array indices (
name[index]
) or object fields (name.field
); only the complete variable is available when you are reading from many runs.
- When reading from many runs, all information is pulled from the database, regardless of whether the run is also currently in memory. As a consequence, only variables that have been explicitly saved to the database are available for query using this method. (Variables are saved to the database using
There are three different variations that you can use to specify a particular variable name in the URI. The following expressions all add
sample_int
to thevariables
in the response body:?include=sample_int
?include=variables.sample_int
?include=.sample_int
If the variable is in a separate scope, that scope must be included in the variable name in the URI (
myModule.sample_string
).The filter can itself refer to model variables, for example
curl -G \ 'https://api.forio.com/v2/run/acme/supply-chain-game/;saved=true;sample_int=12' \ --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Note that as with other filters, when using a filter in the URI, all information is pulled from the database, regardless of whether the run is also currently in memory. In particular, only runs in which the
sample_int
variable was saved to the database usingEpicenter.record()
or similar, with the value of 12, are returned.A second note is that variable filters may not be used in isolation. A run filter (e.g. filtering by group, user or a property such as saved) must be used in addition.
The model variable in the filter is included in the returned run record:
[ { "morphology": "MANY", "id": "000001539d43a51db44159ddb1a354e48542", "user": { "firstName": "j", "lastName": "smith", "id": "233ef9a8-af8e-41ad-84ba-9a21097f6f55", "userName": "jsmith@acme.com" }, "model": "model.py", "variables": { "sample_int": 12 }, "scope": null, "created": "2016-03-22T18:00:14.059Z", "initialized": true, "active": false, "project": "supply-chain-game", "lastModified": "2016-03-22T18:00:14.059Z", "account": "acme", "files": null, "saved": true, "trashed": false }, ... // other run records matching the filter, if any ]
Retrieve Only Variables
You can use either the GET
request for one run or the GET
request for many runs and append /variables/?include=
to return an object with specific model variables request (or an array of such objects).
Method: GET
URI:
/v2/run/
{account id}/
{project id}/
{run id or filter}/variables/?include=
{comma-separated list of variable names}
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 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 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 request404
: Variable not found, when the URI uses the{run id}
format and the run is in memory (for example:GET /v2/run/acme/supply-chain-game/1234/variables?include=badvar
)410
: Variable not found (not recorded), when the URI uses the{filter}
format, or when the URI uses the{run id}
format but the run is not in memory (for example:GET /v2/run/acme/supply-chain-game/;saved=true/variables?include=badvar
)416
: 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:
- If the URI includes a run id directly, the response is an object whose fields are the requested variables.
- If the URI includes a filter (even if the filter is simply
;id=myRunId
), the response is an array of such objects, one object for each run.- In the case of filtering only, if you have specified a
Range
header in the request, or if your request returns more than 100 runs, this array may not contain objects for all runs matching your filter. The array includes only objects for those runs indicated in theContent-Range
header.
- In the case of filtering only, if you have specified a
Example (single run id):
curl -G \
'https://api.forio.com/v2/run/acme/supply-chain-game/000001539d43a51db44159ddb1a354e48542/variables/?include=sample_dict,sample_int,sample_array[2]' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response (single run id):
{
"sample_array[2]": 6,
"sample_int": 16,
"sample_dict": {
"day": "tuesday",
"month": 2
}
}
Example (filter):
curl -G \
'https://api.forio.com/v2/run/acme/supply-chain-game/;saved=true/variables/?include=sample_dict,sample_int,sample_array' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response (filter):
[
{
"sample_array": [
2,
4,
6,
8
],
"sample_int": 10,
"sample_dict": {
"day": "monday",
"month": 2
}
},
... // other run records matching the filter, if any
]
Notes:
In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
When using a single run id in the URI,
- The run is retrieved from memory if available. If the run is not in memory, it is retrieved from the database.
- If the run is in memory, the object in the response includes all (requested) variables. However, if the run is only in the database, the object only includes (requested) variables that have been explicitly saved. (Variables are saved to the database using
Epicenter.record()
or similar, see Writing your model.) - The variable name may include hard-coded array indices (
name[index]
) or object fields (name.field
) if desired. Array indices are modeling-language dependent.
When using a filter in the URI,
- When reading from many runs, all information is pulled from the database, regardless of whether the run is also currently in memory. As a consequence, only variables that have been explicitly saved to the database are available for query using this method. (Variables are saved to the database using
Epicenter.record()
or similar, see Writing your model.) - The variable name may NOT include hard-coded array indices (
name[index]
) or object fields (name.field
); only the complete variable is available when you are reading from many runs.
- When reading from many runs, all information is pulled from the database, regardless of whether the run is also currently in memory. As a consequence, only variables that have been explicitly saved to the database are available for query using this method. (Variables are saved to the database using
There are three different variations that you can use to specify a particular variable name in the URI. The following expressions all add
sample_int
to the object in the response body:/variables/?include=sample_int
/variables/?include=variables.sample_int
/variables/?include=.sample_int
If the variable is in a separate scope, that scope must be included in the variable name in the URI (
myModule.sample_string
).
Retrieve a Single, Dereferenced Variable Value from One or More Runs
You can use either the GET
request for one run or the GET
request for many runs and append /variables/varName
to return the dereferenced value of that variable (or an array of such values).
Method: GET
URI:
/v2/run/
{account id}/
{project id}/
{run id or filter}/variables/
{variable name}
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 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 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 request404
: Variable not found, when the URI uses the{run id}
format and the run is in memory (for example:GET /v2/run/acme/supply-chain-game/1234/variables/badvar
)416
: 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:
- If the URI includes a run id directly, the response is the value of the variable.
- If the URI includes a filter (even if the filter is simply
;id=myRunId
), the response is an array of such values, one value for each run.- In the case of filtering only, if you have specified a
Range
header in the request, or if your request returns more than 100 runs, this array may not contain variable values for all runs matching your filter. The array includes only values for those runs indicated in theContent-Range
header.
- In the case of filtering only, if you have specified a
Example (single run id):
curl -G \
'https://api.forio.com/v2/run/acme/supply-chain-game/000001539d43a51db44159ddb1a354e48542/variables/sample_int' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response (single run id):
16
Example (filter):
curl -G \
'https://api.forio.com/v2/run/acme/supply-chain-game/;saved=true/variables/sample_int' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Example Response (filter):
[
16,
null, // if the variable does not exist or is not saved for this run
... // other variable values for runs matching the filter, if any
]
Notes:
In the URI, the Account ID is the Team ID (for team projects) or User ID (for personal projects).
When using a single run id in the URI,
- The run is retrieved from memory if available. If the run is not in memory, it is retrieved from the database. In this case, the requested variable must have been explicitly saved. (Variables are saved to the database using
Epicenter.record()
or similar, see Writing your model.) - The variable name may include hard-coded array indices (
name[index]
) or object fields (name.field
) if desired. Array indices are modeling-language dependent. - If the variable does not exist or is not saved, there is an error (
404
).
- The run is retrieved from memory if available. If the run is not in memory, it is retrieved from the database. In this case, the requested variable must have been explicitly saved. (Variables are saved to the database using
When using a filter in the URI,
- When reading from many runs, all information is pulled from the database, regardless of whether the run is also currently in memory. As a consequence, only variables that have been explicitly saved to the database are available for query using this method. (Variables are saved to the database using
Epicenter.record()
or similar, see Writing your model.) - The variable name may NOT include hard-coded array indices (
name[index]
) or object fields (name.field
); only the complete variable is available when you are reading from many runs. - If the variable requested does not exist or is not saved for one of the runs, the corresponding entry in the resulting array is
null
.
- When reading from many runs, all information is pulled from the database, regardless of whether the run is also currently in memory. As a consequence, only variables that have been explicitly saved to the database are available for query using this method. (Variables are saved to the database using
If the variable is in a separate scope, that scope must be included in the variable name in the URI (
myModule.sample_string
).
Data Structure
The Run API operates on the Run, Operation, and Error record data structures. It also returns data structures containing variable names and values.
Run Record
The Run record describes the run.
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 to create a run. |
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 creating a run. |
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 creating a run. |
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 creating a run. |
active |
no | A read-only flag in the run record. It is true when the run is in memory and false when the run is only in the databased. See additional information on run persistence. |
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. |
trashed |
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. |
closed |
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 creating a run:
{
"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,
"trashed": false,
"active": true,
"initialized": true,
"scope": null
}
Operation Record
The POST
request to call an operation takes an operation record with the arguments
of the operation. It returns the operation record with details on the operation called, including name
, arguments
, and result
.
Field | Required? | Description |
---|---|---|
name |
no | The name of the model operation called. This is required in the URI of the POST request but is not included in the request body. It is always present in the response. |
arguments |
no | An array of arguments to the operation called. If the operation does not take any arguments, you can either omit the arguments field, or pass an empty array. It is present in the response only if arguments were passed in to the operation. Each argument can be of any type (including JSON objects), as long as there is a corresponding operation in the model. |
result |
no | The return value from the operation. This is not included in the POST request; it may be present in the response. If there is no return value, this field is not included. Note that the return value may or may not also be stored in a model variable, depending on the operation. |
**Example Operation Record**
An example operation record returned as a response to a POST
request:
{
"name": "runmodel",
"arguments": [ "input string", 25, true ],
"result": 20.44
}
Error Record
There are many reasons why the Run API may return an error. These are listed briefly under the specific requests, above. This section describes the error records returned.
Error on Run Creation: 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 |
---|---|---|
message |
yes | A summary of how the error occurred. This will typically contain enough information to allow you to correct the error. |
information.runId |
yes | The potential run id of the run. Note that this run is not accessible, because it was not successfully created. |
information.timestamp |
yes | When the error occured. |
information.code |
yes | Kind of error, if available, for example MODEL_NOT_FOUND . |
information.context |
yes | An object with additional information about where or how the error occured. Fields within this object vary depending on the request. For example, modelFile (the name of the requested model file.) |
type |
yes | The kind of underlying error, based on the language in which this part of Epicenter was implmented. This can be safely ignored. |
**Example: 400 Error Record**
{
"information": {
"code": "MODEL_NOT_FOUND",
"context": {
"modelFile": "othermodel.py"
},
"runId": "0000015b92c5fcbf3146463104821549b704",
"timestamp": "2017-04-24T19:05:56"
},
"type": "com.forio.epicenter.grid.transformer.ModelNotFoundException",
"message": "Could not locate model(/var/epicenter-files/projects/acme/supply_chain_game/model/othermodel.py)"
}
Error on Run Creation: 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 |
---|---|---|
message |
yes | A summary of how the error occurred. This will typically contain enough information to allow you to correct the error. |
information.runKey |
yes | The potential run id of the run. Note that this run is not accessible, because it was not successfully created. |
information.code |
yes | Kind of error, if available, for example MODEL_INITIATION . |
type |
yes | The kind of underlying error, based on the language in which this part of Epicenter was implmented. This can be safely ignored. |
trace |
yes | The stack trace of the error, if available. |
**Example: 500 Error Record**
{
"information": {
"runKey": "0000015b92c5fcbf3146463104821549b6f9",
"code": "MODEL_INITIATION"
},
"type": "python",
"message": "SyntaxError: invalid syntax (badmodel.py, line 6)",
"trace": [
{
"type": "python",
"function": "load_model",
"file": "/usr/local/lib/python2.7/dist-packages/epicenter-py2.7.egg/epicenter/worker/python/python_worker.py",
"line": 75
},
{
"type": "python",
"function": "import_module",
"file": "/usr/lib/python2.7/importlib/__init__.py",
"line": 37
}
],
}
Error on Run Manipulation: 40x
When a POST
request or PATCH
request cannot be completed, the response is a 40x
error.
Field | Required? | Description |
---|---|---|
message |
yes | A summary of how the error occurred. This will typically contain enough information to allow you to correct the error. |
information.runId |
yes | The unique identifier of the run. |
information.timestamp |
yes | When the error occured. |
information.code |
yes | A code name for the type of error encountered. For example, OPERATION_ERROR or VARIABLE_NOT_FOUND . |
information.context |
yes | An object with additional information about where or how the error occured. Fields within this object vary depending on the request. Examples include names (array of relevant variable or operation names), arguments (array of arguments to an operation, from the request body), value (updated value for variable, from the request body), etc. |
type |
yes | The kind of underlying error, based on the language in which this part of Epicenter was implmented. This can be safely ignored. |
trace |
no | Depending on the kind of error, a stack trace may also be included in the error record. |
**Example Error Record for Run Manipulation**
An example error record returned as a response to a POST
request to call an operation that caused a model error:
{
"information": {
"code": "OPERATION_ERROR",
"context": {
"name": "updateTwo",
"arguments": "[15]"
},
"runId": "0000015b92c5fcbf3146463104821549b6ef",
"timestamp": "2017-04-24T19:00:12"
},
"type": "python",
"message": "TypeError: updateTwo() takes exactly 2 arguments (1 given)",
"trace": [
{
"type": "python",
"function": "process",
"file": "/usr/local/lib/python2.7/dist-packages/epicenter-py2.7.egg/epicenter/worker/commands.py",
"line": 240
},
{
"type": "python",
"function": "proc_call",
"file": "/usr/local/lib/python2.7/dist-packages/epicenter-py2.7.egg/epicenter/worker/python/python_worker.py",
"line": 114
},
{
"type": "python",
"function": "function_call",
"file": "/usr/local/lib/python2.7/dist-packages/epicenter-py2.7.egg/epicenter/worker/python/json_codec.py",
"line": 130
}
]
}
Error on Variable Retrieval: 40x
When the GET
request cannot be completed, the response is 404
if the run is in memory, or 410
if it is not.
Field | Required? | Description |
---|---|---|
message |
yes | A summary of the error which occurred. This will typically contain enough information to allow you to correct the error. |
information.runId |
yes | The id of the run. |
information.timestamp |
yes | When the error occurred. |
information.code |
yes | Kind of error, for example VARIABLE_NOT_FOUND or UNRECORDED_VARIABLE . |
information.context.names |
yes | An array of the names of the variables which cannot be retrieved. |
type |
yes | The kind of underlying error, based on the language in which this part of Epicenter was implmented. This can be safely ignored. |
**Example Error Record for Variable Retrieval**
Request:
curl -G \
'https://api.forio.com/v2/run/acme/supply-chain-game/000001539d43a51db44159ddb1a354e48542/variables/?include=goodvar,badvar,otherbadvar' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
Response:
{
"information": {
"code": "VARIABLE_NOT_FOUND",
"context": {
"names": [
"badvar",
"otherbadvar"
]
},
"runId": "0000015bf8d4bcee880df6b868d23eb3f7f2",
"timestamp": "2017-05-11T22:10:06"
},
"type": "python",
"message": "NameError: name 'badvar' is not defined"
}