REST API¶
WebPlan provides a RESTful interface for accessing data stored in the WebPlan database. To access the REST API, you use standard HTTP methods like GET, POST, and DELETE. Though we provide a simple python client to access the API, you can also use any other technique to access the API if you like to do so.
Requests and Responses¶
The response format is JSON if not stated otherwise. The request body for POST request always needs to be JSON formatted if present. For strings parameters we usually only allow nice strings, containing only alphanumeric characters, minuses, spaces and underscores, whereas they have to start and end with an alphanumeric.
A response code of 2xx indicates that the request was understood and accepted. Furthermore the following status codes are used:
- 400 (Bad Request): The request was not understood. This can happen if you supplied not all required parameters.
- 401 (Unauthorized): This request requires Authentication.
- 403 (Forbidden): The request was understood but refused to be fulfilled. This can happen if you try to modify somebody else’s resources or the action you tried to perform is not allowed in general.
- 404 (Not Found): You tried to access a resource that does not exist.
More details on what went wrong is given in the response body.
Authentication¶
Some requests require authentication. Currently the only supported authentication scheme is HTTP Basic Authentication. You need to authenticate using your login credentials as created on the WebPlan website to perform such requests.
Problems¶
The Problem resource provides functionality for querying information about problems, submitting new problems and modifying tags and equivalences. The common URL for accessing problems is /api/problems/ and further parameters as specified below.
GET single Problem¶
Use a GET request for the URL /api/problems/{problem_hash}/ to retrieve information stored for the problem specified by problem_hash. The response is a JSON object that looks like this:
{
// List of hashes of equivalent problems.
"equivalents": [],
// Best known solution costs.
"best_costs": 52.0,
// Problem hash
"hash": "35e101524e4f6711ea5af73ace550788dd1108d1",
// List of tags associated with this problem
"tags": [
// Tag "typing" of type "pddl_requirement", indicating that the problem
// uses the pddl-requirement typing in its pddl domain specification.
{
"type": "pddl_requirement",
"name": "typing",
"number": null
},
// Tag "sokoban" of type "domain"
{
"type": "domain",
"name": "sokoban",
// Number of this problem in the set of problems with this tag.
"number": 25
},
// ...
]
}
GET PDDL Files¶
The problem PDDL file can be retrieved as plain text using a GET request to the URL:
/api/problems/{problem_hash}/problem.pddl
For the domain PDDL file respectively:
/api/problems/{problem_hash}/domain.pddl
Cost Revisions¶
The history of all best known problem costs can be received by a GET request to:
/api/problems/{problem_hash}/cost_revisions
Responses looks like this:
[
{
"created_at": "2012-01-27T10:30:04.541625",
"best_costs": 9.0,
"revision": "6f4b49162771"
},
{
"created_at": "2012-01-20T10:30:04.541625",
"best_costs": 10.0,
"revision": "b1325a6f40a3"
}
]
List Problems¶
A GET request for the URL /api/problems/ lists all problems that match the specified query string parameters. Valid query string parameters are:
- tag - Tag filters query string.
Example Request¶
The following query lists all problems tagged with domain,sokoban. The response is a list of problems, each of them having the same format as described in GET single Problem.
$ curl --request GET "http://localhost:8000/api/problems/?tag=domain,sokoban%20seq-sat"
[
{
"equivalents": [],
"best_costs": 52.0,
"hash": "35e101524e4f6711ea5af73ace550788dd1108d1",
"tags": [
//...
]
},
{
"equivalents": [],
"best_costs": 23.0,
"hash": "e868032ee43cb27c8b971a156c8f09ca10b1192a",
"tags": [
// ...
]
}
]
Submit a Problem¶
Use a POST request to /api/problems/ to submit a new problem. This request requires Authentication.
The request body has to be a JSON-Object with two keys domain_pddl and problem_pddl containing PDDLs as strings:
{
"problem_pddl": "PDDL problem specification goes here",
"domain_pddl": "PDDL domain specification goes here"
}
As response the problem is returned as described in GET single Problem. A status code of 201 indicates that the problem was not in the database before and was created whereas status code 200 indicates that a problem with the same hash was already in the database.
Tagging a Problem¶
Tags can be added or removed from a Problem with POST requests to /api/problems/{problem_hash}/add_tags or /api/problems/{problem_hash}/remove_tags respectively. These requests require Authentication.
The request body has to be a JSON-Object that looks like this:
{
// List of tags to add or remove
"tags": [
{
// Tag type, can be any nice string.
"type": "domain",
// Tag name, can be any nice string.
"name": "sokoban",
// Optional number of this problem in the set of problems with this tag.
"number": 25
// Optional, add_tags only: Flag this tag as private (see below).
"private": True
},
// more tags go here ...
]
}
A tag flagged as private can only be added or removed to problems by the user who created it (added it first to any problem). Please not that the private flag is a property of the tag itself and not to the relation of the tag to a problem, as one might wrongly assume from the way it is set. If you try to add a tag with private=True to a problem that was already added with private=True before (to any problem), your request will fail with status code 403 (Forbidden). This also happens if you try to add or remove a private tag of another user.
As response the problem is returned as described in GET single Problem.
Setting equivalent Problems¶
The equivalence relation of a Problem can be set with POST request to /api/problems/{problem_hash}/set_equivalents. This request requires Authentication.
The request body has to be a JSON-Object that looks like this:
{
// List of problem hashes
"equivalents": [ "a problem hash", "another problem hash" ]
}
As response the problem is returned as described in GET single Problem.
Plans aka ProblemResult¶
The ProblemResult resource provides functionality for querying information about plans. The common URL for accessing ProblemResults is /api/problem_results/.
GET single ProblemResult¶
A ProblemResult is uniquely identified by its id. If you know the id of the ProblemResult you are interested in, you can access it directly using the URL /api/problem_results/{id}/. The response is a JSON object that looks like this:
{
// Name of the planner that computed this plan
"planner_name": "lama",
// IPC-Score
"score": 1.0,
// Hash of the problem that was solved
"problem_hash": "3dac40aca91d9bd5919b3a366e2f2acb59d5c108",
// Unique identifier of this result
"id": 1697,
// Plan costs
"costs": 169009.0
}
GET Plan File¶
The plan file of a ProblemResult can be retrieved as plain text by sending a GET request to the URL:
/api/problem_results/{id}/plan
List ProblemResults¶
If you don’t know the id of the ProblemResult you are looking for or you are interested in all Results that satisfy a given criteria, you can use a GET request to /api/problem_results/ and specify some of the supported query string parameters. Not supplying any parameters just lists all ProblemResults. Valid query string parameters are:
- problem_hash: The problem you are looking for. If you’re looking for all ProblemResults of a given problem for example, this is your friend.
- planner_name: Name of the planner that computed the ProblemResult.
- upload_id: Id of the Upload (set of ProblemResults).
- tag: Tag filters query string.
Example Request¶
A GET request for the following URL lists all ProblemResults of planner “lama” for problems tagged with domain,sokoban
/api/problem_results/?tag=domain,sokoban&planner_name=lama
The response is a list of ProblemResults, each of them having the same format as described in GET single ProblemResult
[
{
"planner_name": "lama",
"score": 1.0,
"problem_hash": "0d92dc91e5438b9f72d1533b902a2579490a46d3",
"id": 1874,
"costs": 44.0
},
{
"planner_name": "lama",
"score": 1.0,
"problem_hash": "29dcd24ea2b31568ceb0b1bc6e291cfa05a0d836",
"id": 1875,
"costs": 31.0
},
// ...
]
Submitting a ProblemResult¶
Use a POST request to /api/problem_results/ to submit a new ProblemResult. This request requires Authentication.
The request body has to be a JSON-Object with the following mandatory keys:
{
// ID of the upload
"upload_id": 2,
// Name of the planner
"planner_name": "lama",
// Problem that you solved
"problem_hash": "29dcd24ea2b31568ceb0b1bc6e291cfa05a0d836",
// Your plan for the problem
"plan": "your plan here"
}
Your plan will be validated with VAL. If it is a valid solution for the specified problem, your request is responded with status code 201 (created) and the response body contains the ProblemResult as described in GET single ProblemResult. If your plan was not accepted because VAL considered it as invalid, an empty response (status code 204) is returned.
If you supply the name of planner that has not been created yet, it will be created for you with the optimal flag set to false. If you supply the name of a planner that belongs to another user, you’ll get an error (403, forbidden).
Please not that in order to be able to supply a valid upload_id, you need to create an upload first. Also note that IPC-Scores are NOT computed automatically for performance reasons. Make sure to call Compute Scores before using them.
Deleting a ProblemResult¶
Use a POST request to /api/problem_results/{id} to delete a ProblemResult. This request requires Authentication. Status code 204 (no content) is returned if your request was fulfilled. Please note that you can only delete ProblemResults of Uploads that have not been finalized.
Upload¶
An Upload is a set of ProblemResults.
List Uploads¶
Send a GET request to /api/result_uploads/ to get a list of all existing Uploads. A list of JSON-Objects is returned that looks like this:
[
{
"username": "manu",
"id": 1,
"name": "ipc08"
},
{
"username": "manu",
"id": 4,
"name": "ipc11"
},
// ...
]
Creating an Upload¶
Use a POST request to /api/result_uploads/ to create an Upload. This request requires Authentication. The request body has to be a JSON-Object with a key name containing a name for this upload.
Deleting an Upload¶
Use a DELETE request to /api/result_uploads/{id} to create an Upload. This request requires Authentication. Deletion is only allowed for uploads that have not been finalized.
Finalizing an Upload¶
Use a POST request to /api/result_uploads/{id}/finalize to finalize an Upload. This request requires Authentication. Once an Upload has been finalized, it cannot be modified nor deleted anymore. Finalizing an upload also computes its scores.
Compute Scores¶
For performance reasons, scores are not computed automatically after submitting a new ProblemResult. Send a POST request to /api/result_uploads/{id}/compute_scores to compute scores for all ProblemResults in an Upload. This request requires Authentication.
Tag¶
In addition to the tagging features described in Tagging a Problem the possibility to list, rename or delete tags is available under the URL /api/tags/.
List Tags¶
A GET request for /api/tags/ lists all available tags. The response looks like this:
[
{
// Number of problems this tag is assigned to
"num_problems": 20,
// Type string
"type": "domain",
// Unique identifier of this tag
"id": 125,
// Private flag
"private": true,
"name": "sokoban"
}, // ...
]
If you send an authenticated request and supply the additional query parameter own_only=1 only tags that you’ve write-access to are returned.
Change a Tag¶
You can change the type and name of a tag by sending a POST request to /api/tags/{id}. This request requires Authentication. The request body has to be a JSON-Object with one (or both) of the following attributes:
{
// Type string
"type": "domain",
// Name string
"name": "sokoban",
}
If you don’t supply name or tag the corresponding attribute is left unchanged. You can only change tags that you’ve created.
Delete a Tag¶
You can delete a tag by sending a DELETE request to /api/tags/{id}. This request requires Authentication. You can only delete tags that you’ve created. Deleting a tag removes it from all associated problems.
Planners¶
Planners can be listed, created, modified and deleted by sending requests to /api/planners/. The only information stored about a planner is its name and an optimal flag.
GET single Planner¶
Use a GET request for the URL /api/planners/{id}/ to retrieve information stored for the planner specified by id. The response is a JSON object that looks like this:
{
// Optimal flag, is this an optimal planner?
"optimal": false,
"id": 15,
// Planner name, any nice string
"name": "lama"
}
The planner name has to be globaly unique. You’ll get an error (status 403, forbidden) if you try to use a name that is already taken (e.g. by another user).
List Planners¶
A GET request for /api/planners/ lists all available tags. The response looks like this:
[
{
"optimal": false,
"id": 15,
"name": "lama"
},
{
"optimal": false,
"id": 55,
"name": "lama-2011"
},
// ...
]
If send an authenticated request and supply the additional query parameter own_only=1 only planners that you’ve write-access to are returned.
Change a Planner¶
You can change the name and optimal flag of a planner by sending a POST request to /api/planners/{id}. This request requires Authentication. The request body has to be a JSON-Object with one (or both) of the following attributes:
{
// Planner name
"name": "lama-2044",
// Optimal flag
"optimal": false
}
If you don’t supply name or optimal the corresponding attribute is left unchanged. You can only change planners that you’ve created.
Delete a Planner¶
You can delete a planner by sending a DELETE request to /api/planners/{id}. This request requires Authentication. You can only delete planners that you’ve created. Planners that do have associated ProblemResults cannot be deleted. You have to delete all its ProblemResults first.