Manage Data
Machinable's main feature is the ability to perform CRUD (Create, Read, Update, Delete) operations on your project's API Resource endpoints. API Resources provide data validation based on the JSON schema.
Note
See API Resources for more information about data validation with JSON Schema.
All examples will be using the Pet Demo
project, which has the following project URL:
https://pet-demo.machinable.io
Authentication
Note
If your project authentication policy is disabled, you do not need to provide an Authorization header in your requests. The examples on this page do not make use of an Authorization header.
Depending on how you are accessing your project's data, you may need to authenticate your requests.
API Keys
To make authenticated requests with an API Key , add the Authorization
header with the apikey
text to each request:
Authorization: apikey { api_key_string}
Users
User authenticated requests require a bit more work.
First, the user will need to acquire a session. To do that, make an HTTP Basic authentication request to your project's /sessions
endpoint. This will return an access_token
and a refresh_token
in the form of JSON Web Tokens :
Bash
# base64 encode username|password to make HTTP Basic authn request
$ echo "testUser:hunter2" | base64
dGVzdFVzZXI6aHVudGVyMgo =
# POST credentials to /sessions/ endpoint to recieve access token
$ curl -X POST \
https://pet-demo.machinable.io/sessions/ \
-H 'authorization: Basic dGVzdFVzZXI6aHVudGVyMg=='
Python
import requests
url = "https://pet-demo.machinable.io/sessions/"
headers = {
'authorization' : "Basic dGVzdFVzZXI6aHVudGVyMg=="
}
response = requests . request ( "POST" , url , headers = headers )
print ( response . text )
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var data = null ;
var xhr = new XMLHttpRequest ();
xhr . withCredentials = true ;
xhr . addEventListener ( "readystatechange" , function () {
if ( this . readyState === 4 ) {
console . log ( this . responseText );
}
});
xhr . open ( "POST" , "https://pet-demo.machinable.io/sessions/" );
xhr . setRequestHeader ( "authorization" , "Basic dGVzdFVzZXI6aHVudGVyMg==" );
xhr . send ( data );
Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main () {
url := "https://pet-demo.machinable.io/sessions/"
req , _ := http . NewRequest ( "POST" , url , nil )
req . Header . Add ( "authorization" , "Basic dGVzdFVzZXI6aHVudGVyMg==" )
res , _ := http . DefaultClient . Do ( req )
defer res . Body . Close ()
body , _ := ioutil . ReadAll ( res . Body )
fmt . Println ( res )
fmt . Println ( string ( body ))
}
Successful response:
{
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTIzMjI4MTksInByb2plY3RzIjp7InBldC1kZW1vIjp0cnVlfSwidXNlciI6eyJhY3RpdmUiOnRydWUsImlkIjoiNWM4NjhkNDBhNzc0OGJiMjI0ODMzZjRiIiwibmFtZSI6InRlc3RVc2VyIiwicmVhZCI6dHJ1ZSwidHlwZSI6InByb2plY3QiLCJ3cml0ZSI6dHJ1ZX19.93H4H3FyPGrzOGb3WHRO7RLUGezpYxbVki7oGqdyA6E" ,
"message" : "Successfully logged in" ,
"refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTI1ODExMTksInNlc3Npb25faWQiOiI1Yzg2OGQ3ZmE3NzQ4YmIyMjQ4MzNmNGMiLCJ1c2VyX2lkIjoiNWM4NjhkNDBhNzc0OGJiMjI0ODMzZjRiIn0.wWyb-nNff3RBw73D1hqN9k8U8_pKMHWGShMwA9YvSAc" ,
"session_id" : "5c868d7fa7748bb224833f4c"
}
Once the user has a session, authenticated requests can be made by adding the Authorization
header with the bearer
text and access_token
to each request:
Authorization: bearer { access_token}
Info
Access tokens have a limited lifetime of 5 minutes. They then need to be exchanged for a new Access token using the refresh token. Refer to Project Users for more information about refreshing an access token.
Create
Create and store a new object in a specific API Resource.
Note
These examples are managing data within an API Resource called dogs
at /api/dogs
, given the correct JSON schema is defined.
Bash
$ curl -X POST \
https://pet-demo.machinable.io/api/dogs \
-d '{"name":"Murphy", "age":2, "breed": "French Bulldog"}'
Python
import requests
url = "https://pet-demo.machinable.io/api/dogs"
payload = "{ \" name \" : \" Murphy \" , \" age \" :2, \" breed \" : \" French Bulldog \" }"
headers = {}
response = requests . request ( "POST" , url , data = payload , headers = headers )
print ( response . text )
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13var data = "{\"name\":\"Murphy\", \"age\":2, \"breed\": \"French Bulldog\"}" ;
var xhr = new XMLHttpRequest ();
xhr . addEventListener ( "readystatechange" , function () {
if ( this . readyState === 4 ) {
console . log ( this . responseText );
}
});
xhr . open ( "POST" , "https://pet-demo.machinable.io/api/dogs" );
xhr . send ( data );
Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main () {
url := "https://pet-demo.machinable.io/api/dogs"
payload := strings . NewReader ( "{\"name\":\"Murphy\", \"age\":2, \"breed\": \"French Bulldog\"}" )
req , _ := http . NewRequest ( "POST" , url , payload )
res , _ := http . DefaultClient . Do ( req )
defer res . Body . Close ()
body , _ := ioutil . ReadAll ( res . Body )
fmt . Println ( res )
fmt . Println ( string ( body ))
}
Successful response:
1
2
3
4
5
6
7
8
9
10
11
12
13< HTTP/ 1.1 201 Created
{
"_metadata" : {
"created" : 1552323811 ,
"creator" : "anonymous" ,
"creator_type" : "anonymous"
},
"age" : 2 ,
"breed" : "French Bulldog" ,
"id" : "5c8694e3a7748bb224833f51" ,
"name" : "Murphy"
}
Read
Retrieve a single object from a resource or list all objects that exist (paginated).
Retrieve single object
To retrieve a single object, make a GET
request to the resource with the ID of the object as the last path parameter.
Successful response:
1
2
3
4
5
6
7
8
9
10
11
12
13< HTTP/ 1.1 200 OK
{
"_metadata" : {
"created" : 1552326051 ,
"creator" : "anonymous" ,
"creator_type" : "anonymous"
},
"age" : 7 ,
"breed" : "German Shephard" ,
"id" : "5c869da3a7748bb224833f5c" ,
"name" : "Max"
}
List objects
To retrieve a paginated list of objects for this resource, make a GET
request to the resource.
Successful response:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32< HTTP/ 1.1 200 OK
{
"count" : 2 ,
"items" : [
{
"_metadata" : {
"created" : 1552323811 ,
"creator" : "anonymous" ,
"creator_type" : "anonymous"
},
"age" : 2 ,
"breed" : "French Bulldog" ,
"id" : "5c8694e3a7748bb224833f51" ,
"name" : "Murphy"
},
{
"_metadata" : {
"created" : 1552326051 ,
"creator" : "anonymous" ,
"creator_type" : "anonymous"
},
"age" : 7 ,
"breed" : "German Shephard" ,
"id" : "5c869da3a7748bb224833f5c" ,
"name" : "Max"
}
],
"links" : {
"self" : "https://pet-demo.machinable.io/api/dogs?_limit=10&_offset=0"
}
}
Notice the resource objects are returned as a list in the items
key. A maximum of 10 objects will be returned by default.
See Pagination for more information regarding the page limit as well as the other keys in the root of the response JSON.
Update
Update a single object's values.
Bash
curl -X PUT \
https://pet-demo.machinable.io/api/dogs/5c869da3a7748bb224833f5c \
-d '{
"age": 9,
"name": "Maximilian"
}'
Python
import requests
url = "https://pet-demo.machinable.io/api/dogs/5c869da3a7748bb224833f5c"
payload = "{ \n \" age \" : 9, \n \" name \" : \" Maximilian \"\n }"
headers = {}
response = requests . request ( "PUT" , url , data = payload , headers = headers )
print ( response . text )
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13var data = "{\n \"age\": 9,\n \"name\": \"Maximilian\"\n}" ;
var xhr = new XMLHttpRequest ();
xhr . addEventListener ( "readystatechange" , function () {
if ( this . readyState === 4 ) {
console . log ( this . responseText );
}
});
xhr . open ( "PUT" , "https://pet-demo.machinable.io/api/dogs/5c869da3a7748bb224833f5c" );
xhr . send ( data );
Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main () {
url := "https://pet-demo.machinable.io/api/dogs/5c869da3a7748bb224833f5c"
payload := strings . NewReader ( "{\n \"age\": 9,\n \"name\": \"Maximilian\"\n}" )
req , _ := http . NewRequest ( "PUT" , url , payload )
res , _ := http . DefaultClient . Do ( req )
defer res . Body . Close ()
body , _ := ioutil . ReadAll ( res . Body )
fmt . Println ( res )
fmt . Println ( string ( body ))
}
Successful response:
1
2
3
4
5
6
7
8
9
10
11
12
13< HTTP/ 1.1 200 OK
{
"_metadata" : {
"created" : 1552326051 ,
"creator" : "anonymous" ,
"creator_type" : "anonymous"
},
"age" : 9 ,
"breed" : "German Shephard" ,
"id" : "5c869da3a7748bb224833f5c" ,
"name" : "Maximilian"
}
Delete
Permanently remove an object.
Successful response:
< HTTP/ 1.1 204 No Content