Studio API v1.0.0
Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.
Mariana Tek's Studio API provides a set of purpose-built endpoints to make creating tools for managing studio configurations a breeze. The focused scope and utility of the Studio API endpoints encourages the use of our other APIs for goals like managing the finer details of existing objects or diving deep into their data for analytics.
Email: Support
Authentication
- HTTP Authentication, scheme: bearer
The Studio API uses an API Key as the bearer token to authenticate requests that modify data. To receive an API Key, please reach out to the Integrations team at Mariana Tek via email. For more information on authenticating with MT, check out our authentication documentation.
Layouts
Retrieve and manage First-Come-First-Serve and Pick-A-Spot Layouts.
Create Layout
Code samples
# You can also use wget
curl -X POST /api/studio/v1/layouts \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
POST /api/studio/v1/layouts HTTP/1.1
Content-Type: application/json
Accept: application/json
const inputBody = '{
"name": "Cool PAS Layout",
"is_active": true,
"classroom": {
"id": "123"
},
"capacity": 3,
"is_pick_a_spot": true,
"spots": [
{
"name": "F1",
"x_position": "3.5",
"y_position": "2.1",
"spot_type": {
"id": "3"
},
"is_default_held": true
},
{
"name": "F2",
"x_position": "5.25",
"y_position": "2.5",
"spot_type": {
"id": "3"
},
"is_default_held": false
},
{
"name": "B1",
"x_position": "1.5",
"y_position": "1",
"spot_type": {
"id": "2"
},
"is_default_held": false
}
]
}';
const headers = {
'Content-Type':'application/json',
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/api/studio/v1/layouts',
{
method: 'POST',
body: inputBody,
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.post '/api/studio/v1/layouts',
params: {
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.post('/api/studio/v1/layouts', headers = headers)
print(r.json())
'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('POST','/api/studio/v1/layouts', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
URL obj = new URL("/api/studio/v1/layouts");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("POST", "/api/studio/v1/layouts", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
POST /api/studio/v1/layouts
Creates a new layout
Body parameter
{
"name": "Cool PAS Layout",
"is_active": true,
"classroom": {
"id": "123"
},
"capacity": 3,
"is_pick_a_spot": true,
"spots": [
{
"name": "F1",
"x_position": "3.5",
"y_position": "2.1",
"spot_type": {
"id": "3"
},
"is_default_held": true
},
{
"name": "F2",
"x_position": "5.25",
"y_position": "2.5",
"spot_type": {
"id": "3"
},
"is_default_held": false
},
{
"name": "B1",
"x_position": "1.5",
"y_position": "1",
"spot_type": {
"id": "2"
},
"is_default_held": false
}
]
}
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
body | body | any | true | Layout to create |
Example responses
201 Response
{
"id": "101",
"name": "Cool PAS Layout",
"is_active": true,
"classroom": {
"id": "123",
"name": "Neat Classroom"
},
"capacity": 3,
"is_pick_a_spot": true,
"spots": [
{
"id": "11",
"name": "F1",
"x_position": "3.5",
"y_position": "2.1",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": true
},
{
"id": "12",
"name": "F2",
"x_position": "5.25",
"y_position": "2.5",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": false
},
{
"id": "13",
"name": "B1",
"x_position": "1.5",
"y_position": "1",
"spot_type": {
"id": "2",
"name": "Bike",
"is_secondary": true
},
"is_default_held": false
}
]
}
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
201 | Created | Layout created successfully. | Layout |
401 | Unauthorized | Authorization information is missing or invalid. | None |
403 | Forbidden | The authenticated user does not have permission to perform this request. | None |
422 | Unprocessable Entity | Request is invalid. | None |
List Layouts
Code samples
# You can also use wget
curl -X GET /api/studio/v1/layouts \
-H 'Accept: application/json'
GET /api/studio/v1/layouts HTTP/1.1
Accept: application/json
const headers = {
'Accept':'application/json'
};
fetch('/api/studio/v1/layouts',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json'
}
result = RestClient.get '/api/studio/v1/layouts',
params: {
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json'
}
r = requests.get('/api/studio/v1/layouts', headers = headers)
print(r.json())
'application/json',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('GET','/api/studio/v1/layouts', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
URL obj = new URL("/api/studio/v1/layouts");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("GET", "/api/studio/v1/layouts", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
GET /api/studio/v1/layouts
Returns a list of layouts along with their spot data
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | query | string | false | filter by layout ID |
classroom | query | string | false | filter by a classroom ID |
is_pick_a_spot | query | boolean | false | filter by layout format |
page | query | integer | false | specific page number to return records from |
page_size | query | integer | false | maximum number of records to return per page |
Example responses
200 Response
{
"results": [
{
"id": "101",
"name": "Cool PAS Layout",
"is_active": true,
"classroom": {
"id": "123",
"name": "Neat Classroom"
},
"capacity": 3,
"is_pick_a_spot": true,
"spots": [
{
"id": "11",
"name": "F1",
"x_position": "3.5",
"y_position": "2.1",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": true
},
{
"id": "12",
"name": "F2",
"x_position": "5.25",
"y_position": "2.5",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": false
},
{
"id": "13",
"name": "B1",
"x_position": "1.5",
"y_position": "1",
"spot_type": {
"id": "2",
"name": "Bike",
"is_secondary": true
},
"is_default_held": false
}
]
}
],
"meta": {
"pagination": {
"count": 1,
"pages": 1,
"page": 1
}
}
}
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Search results matching criteria. | LayoutList |
404 | Not Found | The specified resource cannot be found. | None |
422 | Unprocessable Entity | Request is invalid. | None |
Retrieve Layout
Code samples
# You can also use wget
curl -X GET /api/studio/v1/layouts/{layout_id} \
-H 'Accept: application/json'
GET /api/studio/v1/layouts/{layout_id} HTTP/1.1
Accept: application/json
const headers = {
'Accept':'application/json'
};
fetch('/api/studio/v1/layouts/{layout_id}',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Accept' => 'application/json'
}
result = RestClient.get '/api/studio/v1/layouts/{layout_id}',
params: {
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Accept': 'application/json'
}
r = requests.get('/api/studio/v1/layouts/{layout_id}', headers = headers)
print(r.json())
'application/json',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('GET','/api/studio/v1/layouts/{layout_id}', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
URL obj = new URL("/api/studio/v1/layouts/{layout_id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("GET", "/api/studio/v1/layouts/{layout_id}", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
GET /api/studio/v1/layouts/{layout_id}
View details of one particular layout
Example responses
200 Response
{
"id": "202",
"name": "Fun FCFS Layout",
"is_active": true,
"classroom": {
"id": "123",
"name": "Neat Classroom"
},
"capacity": 5,
"is_pick_a_spot": false,
"spots": null
}
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Success. | Layout |
404 | Not Found | The specified resource cannot be found. | None |
Update Layout
Code samples
# You can also use wget
curl -X PATCH /api/studio/v1/layouts/{layout_id} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
PATCH /api/studio/v1/layouts/{layout_id} HTTP/1.1
Content-Type: application/json
Accept: application/json
const inputBody = '{
"name": "Cool PAS Layout",
"is_active": false,
"spots": [
{
"id": "11",
"name": "F1",
"x_position": "3.5",
"y_position": "2.1"
},
{
"id": "12",
"name": "F2",
"x_position": "5.25",
"y_position": "2.5"
}
]
}';
const headers = {
'Content-Type':'application/json',
'Accept':'application/json',
'Authorization':'Bearer {access-token}'
};
fetch('/api/studio/v1/layouts/{layout_id}',
{
method: 'PATCH',
body: inputBody,
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
require 'rest-client'
require 'json'
headers = {
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}'
}
result = RestClient.patch '/api/studio/v1/layouts/{layout_id}',
params: {
}, headers: headers
p JSON.parse(result)
import requests
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}
r = requests.patch('/api/studio/v1/layouts/{layout_id}', headers = headers)
print(r.json())
'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer {access-token}',
);
$client = new \GuzzleHttp\Client();
// Define array of request body.
$request_body = array();
try {
$response = $client->request('PATCH','/api/studio/v1/layouts/{layout_id}', array(
'headers' => $headers,
'json' => $request_body,
)
);
print_r($response->getBody()->getContents());
}
catch (\GuzzleHttp\Exception\BadResponseException $e) {
// handle exception or api errors.
print_r($e->getMessage());
}
// ...
URL obj = new URL("/api/studio/v1/layouts/{layout_id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PATCH");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
package main
import (
"bytes"
"net/http"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer {access-token}"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := http.NewRequest("PATCH", "/api/studio/v1/layouts/{layout_id}", data)
req.Header = headers
client := &http.Client{}
resp, err := client.Do(req)
// ...
}
PATCH /api/studio/v1/layouts/{layout_id}
Update an existing layout
Body parameter
{
"name": "Cool PAS Layout",
"is_active": false,
"spots": [
{
"id": "11",
"name": "F1",
"x_position": "3.5",
"y_position": "2.1"
},
{
"id": "12",
"name": "F2",
"x_position": "5.25",
"y_position": "2.5"
}
]
}
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
body | body | object | true | Layout details to update. On layouts, only the "name" and "is_active" properties can be modified. For Pick-A-Spot layouts, you can additionally update some spot-specific properties ("name", "x_position", and "y_position" only). |
Example responses
200 Response
{
"id": "101",
"name": "Cool PAS Layout",
"is_active": false,
"classroom": {
"id": "123",
"name": "Neat Classroom"
},
"capacity": 3,
"is_pick_a_spot": true,
"spots": [
{
"id": "11",
"name": "F1",
"x_position": "3.5",
"y_position": "2.1",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": true
},
{
"id": "12",
"name": "F2",
"x_position": "5.25",
"y_position": "2.5",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": false
},
{
"id": "13",
"name": "B1",
"x_position": "1.5",
"y_position": "1",
"spot_type": {
"id": "2",
"name": "Bike",
"is_secondary": true
},
"is_default_held": false
}
]
}
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Updated successfully. | Layout |
401 | Unauthorized | Authorization information is missing or invalid. | None |
403 | Forbidden | The authenticated user does not have permission to perform this request. | None |
404 | Not Found | The specified resource cannot be found. | None |
422 | Unprocessable Entity | Request is invalid. | None |
Schemas
LayoutList
{
"results": [
{
"id": "101",
"name": "Cool PAS Layout",
"is_active": true,
"classroom": {
"id": "123",
"name": "Neat Classroom"
},
"capacity": 3,
"is_pick_a_spot": true,
"spots": [
{
"id": "11",
"name": "F1",
"x_position": "3.5",
"y_position": "2.1",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": true
},
{
"id": "12",
"name": "F2",
"x_position": "5.25",
"y_position": "2.5",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": false
},
{
"id": "13",
"name": "B1",
"x_position": "1.5",
"y_position": "1",
"spot_type": {
"id": "2",
"name": "Bike",
"is_secondary": true
},
"is_default_held": false
}
]
}
],
"meta": {
"pagination": {
"count": 1,
"pages": 1,
"page": 1
}
}
}
Properties
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
results | [Layout] | false | read-only | A list of Layouts |
meta | Meta | false | none | Pagination metadata. |
Layout
{
"id": "101",
"name": "Cool PAS Layout",
"is_active": true,
"classroom": {
"id": "123",
"name": "Neat Classroom"
},
"capacity": 3,
"is_pick_a_spot": true,
"spots": [
{
"id": "11",
"name": "F1",
"x_position": "3.5",
"y_position": "2.1",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": true
},
{
"id": "12",
"name": "F2",
"x_position": "5.25",
"y_position": "2.5",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": false
},
{
"id": "13",
"name": "B1",
"x_position": "1.5",
"y_position": "1",
"spot_type": {
"id": "2",
"name": "Bike",
"is_secondary": true
},
"is_default_held": false
}
]
}
Properties
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
id | string | true | read-only | none |
name | string | true | none | none |
is_active | boolean | true | none | Only Active Layouts can be used in Classes. |
classroom | Classroom | true | none | none |
capacity | integer | true | none | If is_pick_a_spot=true, capacity must match length of spots array with a Maximum of 100. If is_pick_a_spot=false, capacity will set number of spots in First-Come-First-Serve layout with a Maximum of 1000. |
is_pick_a_spot | boolean | true | none | Determines whether the Layout format consists of discrete spots on a map (Pick-A-Spot) or a simple roster (First-Come-First-Serve). |
spots | [Spot]¦null | true | none | If is_pick_a_spot=false, then spots=null. |
Classroom
{
"id": "123",
"name": "Neat Classroom"
}
Properties
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
id | string | true | none | none |
name | string | false | read-only | none |
Spot
{
"id": "11",
"name": "F1",
"x_position": "3.5",
"y_position": "2.1",
"spot_type": {
"id": "3",
"name": "Floor",
"is_secondary": false
},
"is_default_held": true
}
Properties
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
id | string | true | read-only | none |
name | string | true | none | none |
x_position | string(decimal) | true | none | Stringified decimal representation of X position on map. Up to 5 digits total, and 2 decimal places. Spots should be at least 1.0 apart to avoid overlapping |
y_position | string(decimal) | true | none | Stringified decimal representation of Y position on map. Up to 5 digits total, and 2 decimal places. Spots should be at least 1.0 apart to avoid overlapping |
spot_type | SpotType | true | none | none |
is_default_held | boolean | false | none | none |
SpotType
{
"id": "3",
"name": "Floor",
"is_secondary": false
}
Properties
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
id | string | true | none | none |
name | string | false | read-only | none |
is_secondary | boolean | false | read-only | If is_default_held=true, the spot won't be available for booking unless the hold is released for a particular class. |
Meta
{
"pagination": {
"count": 1,
"pages": 1,
"page": 1
}
}
Pagination metadata.
Properties
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
pagination | object | false | none | Pagination information. |
» count | integer | false | read-only | The total number of items. |
» pages | integer | false | read-only | The total number of pages. |
» page | integer | false | none | The current page. |