Programming Model
The Programming Model
The GO API generally follows the REST principles for HTTP-based interfaces. This means:
- Functionality is organized around a set of resource types, e.g. Projects and Users, with
resource endpoints named accordingly, e.g./projects
and/users
. - Functions that operate on the resources are implemented with the four HTTP verbs:
GET
(read),
POST
(create),PUT
(update), andDELETE
. - Each resource object in the system, such as a particular Project or AOI, is uniquely
represented by anid
string. - For operations which return results, the HTTP response payloads are always formatted as JSON
objects. - For operations which require input data, the HTTP request payloads are also always formatted as
JSON objects. - All operations require a user token to authenticate you to the Go API.
In the next sections, we will demonstrate each of the four HTTP verbs using the Project resource
type and its associated /projects
endpoint.
POST
POST
In the GO API, a Project represents work to be performed, such as "count the number of cars in
downtown San Francisco for every month in 2018". Projects will be described in more detail in a
later section, but for now we're going to just create a simple, empty project with no detection
algorithm, area of interest, or other parameters.
To create resources, we always use the POST
verb. We will use the curl
command to POST
a JSON-formatted request payload to the GO API's /projects
endpoint. The payload will just
contain the name of our project and a short description; we put this data a file named
http/post_project_body.json
:
{
"name": "looking_glass",
"description": "the looking glass project"
}
The curl
command to execute is:
curl -s -S \
-H "Content-Type: application/json" \
-H "X-Orbitalinsight-Auth-Token: $GO_API_TOKEN" \
--data @http/post_project_body.json \
-X POST \
$GO_API_URL/projects
That operation will return a response payload similar to this:
{
"data": {
"algorithm_ids": [],
"collaborator_ids": [],
"created_ts": "2019-08-12T15:54:07.931000+00:00",
"description": "the looking glass project",
"id": "wc79nf6R1E-190812",
"name": "looking_glass",
"owner_id": "alice",
"parent_project_id": null,
"stage": "NOT_STARTED",
"version_ids": [
"wc79nf6R1E-190812-1.0.0"
]
},
"status": 201
}
(Again, here and in subsequent outputs, for clarity of exposition some fields are not shown.)
That returned JSON object contains a status
field with the HTTP code of the operation
(201
/OK), and a data
field containing the new resource.
All GO API operations follow the convention of "wrapping" the actual resource data inside of a
larger object that contains certain metadata, like the status of the operation. We will have more
to say about wrapped objects in a later section; for now, just observe that your project was
created with the correct name (data.name
) and description (data.description
) and was
assigned an id (data.id
).
GET
GET
As seen in the previous section, the POST
operation returned the resource object to us, but
let's assume we want to retrieve the object from the server again anyway. We use the GET
verb
to retrieve resource objects. In this case, we will do a GET
operation on the Project resource
endpoint, qualified with our project's id:
curl -s -S \
-H "Content-Type: application/json" \
-H "X-Orbitalinsight-Auth-Token: $GO_API_TOKEN" \
-X GET \
$GO_API_URL/projects/wc79nf6R1E-190812
The result is again a wrapped Project object, with the data
field containing the same
information we got when we created the project:
{
"data": {
"algorithm_ids": [],
"collaborator_ids": [],
"created_ts": "2019-08-12T15:54:07.931000+00:00",
"description": "the looking glass project",
"id": "wc79nf6R1E-190812",
"name": "looking_glass",
"owner_id": "alice",
"parent_project_id": null,
"stage": "NOT_STARTED",
"version_ids": [
"wc79nf6R1E-190812-1.0.0"
]
},
"status": 200
}
We can also execute a command to retrieve all of our projects by using GET
on the /projects
endpoint, with no qualifying id given:
curl -s -S \
-H "Content-Type: application/json" \
-H "X-Orbitalinsight-Auth-Token: $GO_API_TOKEN" \
-X GET \
$GO_API_URL/projects
The result will look like this:
{
"data": [
{
"algorithm_ids": [
"CAR_DETECTOR_ANALYSIS"
],
"collaborator_ids": [],
"created_ts": "2019-08-09T18:57:06.435000+00:00",
"description": "the looking glass project",
"id": "2M_JkbCs08-190809",
"name": "looking_glass",
"owner_id": "alice",
"parent_project_id": null,
"stage": "NOT_STARTED",
"version_ids": [
"2M_JkbCs08-190809-1.0.0"
]
},
"..."
],
"list_attributes": {
"limit": 100,
"offset": 0,
"total": 14
},
"status": 200
}
That wrapped result is a little different than the previous one. The data
field contains a
list of Project objects (shortened here for clarity). The result also contains a
list_attributes
field, which will be explained shortly.
PUT
PUT
To modify a resource, we use the PUT
verb. Let's modify the description of our project using
PUT
and our project's endpoint. First we create our payload file,
http/put_project_body.json
:
{
"description": "what she found there"
}
and then execute the curl
command:
curl -s -S \
-H "Content-Type: application/json" \
-H "X-Orbitalinsight-Auth-Token: $GO_API_TOKEN" \
--data @http/put_project_body.json \
-X PUT \
$GO_API_URL/projects/wc79nf6R1E-190812
The operation returns our project resource, with an appropriately updated description
field:
{
"data": {
"algorithm_ids": [],
"collaborator_ids": [],
"created_ts": "2019-08-12T15:54:07.931000+00:00",
"description": "what she found there",
"id": "wc79nf6R1E-190812",
"name": "looking_glass",
"owner_id": "alice",
"parent_project_id": null,
"stage": "NOT_STARTED",
"version_ids": [
"wc79nf6R1E-190812-1.0.0"
]
},
"status": 200
}
DELETE
DELETE
We are now done with our first project, so let's delete it from the system using the DELETE
verb and our project's endpoint:
curl -s -S \
-H "Content-Type: application/json" \
-H "X-Orbitalinsight-Auth-Token: $GO_API_TOKEN" \
-X DELETE \
$GO_API_URL/projects/wc79nf6R1E-190812
This operation returns a success status code but no data:
{
"data": {},
"status": 200
}
Now if we try to retrieve our project:
curl -s -S \
-H "Content-Type: application/json" \
-H "X-Orbitalinsight-Auth-Token: $GO_API_TOKEN" \
-X GET \
$GO_API_URL/projects/wc79nf6R1E-190812
we will get an error:
{
"error": "InvalidRequest",
"message": "Failed to fetch projects.",
"status": 400
}
The Data Model
We've now seen enough examples that we can describe how to interpret wrapped response objects from
the GO API. The wrapper's format is:
{
"status": "(integer)",
"data": "(object or list of objects)",
"list_attributes": {
"limit": "(integer)",
"offset": "(integer)",
"total": "(integer)"
},
"error": "(string)",
"message": "(string)"
}
First, all returned objects will contain a status
field which will be an integer corresponding
to one of the standard HTTP response codes.
Second, if the status code indicates success (2xx
), there will be a data
field in the
object. When a single resource object is being returned, it will be the value of that data
field. When multiple resource objects are being returned, as in our GET /projects
example, the
value of the data
field will be a list containing the object resources.
Third, if a list is being returned in the data
field, a list_attributes
field will also be
present. The list_attributes
object describes the list being returned in a way that allows you
to do “paginated” HTTP requests, e.g. “give me the first 50 Projects” and then “give me the next
50 Projects”. Pagination is discussed in a later section of this Guide.
Fourth, if the status code indicates an error has occurred (4xx
or 5xx
), the returned
object may have two additional, optional fields. The error
field will be a short string
containing the error type. The message
field will be human-readable description of the error.
In pseudo-code, wrapped response objects should be handled similar to this:
result = { ... } # returned object from some HTTP operation
if result.status >= 200 and result.status <= 299:
if type(result.data) == list:
for item in result.data:
print(item)
else:
print(result.data)
else:
print(result.status)
print(result.error)
print(result.message)
HTTP Operation Notation
For the remainder of this document, we will not spell out the complete curl
command lines and
instead use a more traditional, language-independent notation. The HTTP operations in the preceding
sections would be written like this:
POST /projects
GET /projects/$P
GET /projects
PUT /projects/$P
DELETE /projects/$P
Observe that we shorten the URL to only show the resource path, excluding the host name, and that
we use $
placeholders for the resource ids.
Updated over 3 years ago