curl --request POST \
--url https://api.ctrl-hub.com/v3/exports \
--header 'Content-Type: application/vnd.api+json' \
--header 'X-Session-Token: <api-key>' \
--data '
{
"data": {
"type": "<string>",
"attributes": {
"subject_type": "competency-holders"
},
"relationships": {
"organisation": {
"data": {
"type": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
},
"subjects": {
"data": [
{
"type": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
]
}
}
}
}
'import requests
url = "https://api.ctrl-hub.com/v3/exports"
payload = { "data": {
"type": "<string>",
"attributes": { "subject_type": "competency-holders" },
"relationships": {
"organisation": { "data": {
"type": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
} },
"subjects": { "data": [
{
"type": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
] }
}
} }
headers = {
"X-Session-Token": "<api-key>",
"Content-Type": "application/vnd.api+json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Session-Token': '<api-key>', 'Content-Type': 'application/vnd.api+json'},
body: JSON.stringify({
data: {
type: '<string>',
attributes: {subject_type: 'competency-holders'},
relationships: {
organisation: {data: {type: '<string>', id: '3c90c3cc-0d44-4b50-8888-8dd25736052a'}},
subjects: {data: [{type: '<string>', id: '3c90c3cc-0d44-4b50-8888-8dd25736052a'}]}
}
}
})
};
fetch('https://api.ctrl-hub.com/v3/exports', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ctrl-hub.com/v3/exports",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
'type' => '<string>',
'attributes' => [
'subject_type' => 'competency-holders'
],
'relationships' => [
'organisation' => [
'data' => [
'type' => '<string>',
'id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
],
'subjects' => [
'data' => [
[
'type' => '<string>',
'id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/vnd.api+json",
"X-Session-Token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.ctrl-hub.com/v3/exports"
payload := strings.NewReader("{\n \"data\": {\n \"type\": \"<string>\",\n \"attributes\": {\n \"subject_type\": \"competency-holders\"\n },\n \"relationships\": {\n \"organisation\": {\n \"data\": {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n },\n \"subjects\": {\n \"data\": [\n {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n ]\n }\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Session-Token", "<api-key>")
req.Header.Add("Content-Type", "application/vnd.api+json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.ctrl-hub.com/v3/exports")
.header("X-Session-Token", "<api-key>")
.header("Content-Type", "application/vnd.api+json")
.body("{\n \"data\": {\n \"type\": \"<string>\",\n \"attributes\": {\n \"subject_type\": \"competency-holders\"\n },\n \"relationships\": {\n \"organisation\": {\n \"data\": {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n },\n \"subjects\": {\n \"data\": [\n {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n ]\n }\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ctrl-hub.com/v3/exports")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Session-Token"] = '<api-key>'
request["Content-Type"] = 'application/vnd.api+json'
request.body = "{\n \"data\": {\n \"type\": \"<string>\",\n \"attributes\": {\n \"subject_type\": \"competency-holders\"\n },\n \"relationships\": {\n \"organisation\": {\n \"data\": {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n },\n \"subjects\": {\n \"data\": [\n {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n ]\n }\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>",
"attributes": {
"subject_type": "competency-holders",
"error": "<string>",
"artifact": {
"filename": "<string>",
"content_type": "<string>",
"size_bytes": 1
}
},
"meta": {
"requested_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z"
},
"relationships": {
"organisation": {
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
},
"requester": {
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
},
"subjects": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
}
}
},
"jsonapi": {
"version": "<string>"
},
"included": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>",
"attributes": {
"name": "<string>",
"slug": "<string>",
"sandbox": true,
"description": "<string>",
"settings": {
"teams": {
"customer_representatives": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
]
}
}
},
"meta": {
"v3": true,
"status": "active",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"features": [
{
"name": "<string>",
"enabled": true,
"limit": 123
}
]
},
"relationships": {
"users": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
},
"service_accounts": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
},
"groups": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
},
"teams": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
},
"nomenclature": {
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
}
}
}
]
}{
"id": "98ca4a78-b66f-4234-9719-aaf832ee6669",
"status": "400",
"title": "A validation error was encountered",
"source": {
"parameter": "include"
},
"meta": {
"resource": "wrong_value"
}
}{
"id": "05fc9c8d-73b9-4697-9337-57f7a567a48f",
"status": "401",
"title": "You are not authorised to access this resource",
"detail": "In order to access this resource, you need the 'admin' role.",
"code": "AUTH.001"
}{
"id": "fe9d9a69-f0a7-4fdc-bb2c-176027f316c5",
"status": "500",
"title": "Internal Server Error",
"detail": "An unexpected error occurred on the server."
}Request an export
Ask for generated documents covering one or more subjects.
The request is recorded and returns immediately; the documents are produced afterwards and the requester is told when they are ready. A single-subject request takes the same path as a bulk one.
subject_type says what kind of records are being exported, and it is what decides how the
request is authorised. Every subject has to belong to the organisation named on the request,
since that is the organisation whose name the document prints.
At most fifty subjects, enforced here as well as in the console.
Authorised by the same view grants that govern reading the records: there is no separate export permission, so if you can see the records you can export them. Every subject is checked individually, and a subject the caller cannot view fails the whole request rather than being quietly dropped, because a document that looks complete and is not is worse than an error.
Subjects shared across organisations are exported the same way they are viewed. The organisation on the request owns the records, and a customer-organisation caller reaches it through a grant there.
curl --request POST \
--url https://api.ctrl-hub.com/v3/exports \
--header 'Content-Type: application/vnd.api+json' \
--header 'X-Session-Token: <api-key>' \
--data '
{
"data": {
"type": "<string>",
"attributes": {
"subject_type": "competency-holders"
},
"relationships": {
"organisation": {
"data": {
"type": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
},
"subjects": {
"data": [
{
"type": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
]
}
}
}
}
'import requests
url = "https://api.ctrl-hub.com/v3/exports"
payload = { "data": {
"type": "<string>",
"attributes": { "subject_type": "competency-holders" },
"relationships": {
"organisation": { "data": {
"type": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
} },
"subjects": { "data": [
{
"type": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
] }
}
} }
headers = {
"X-Session-Token": "<api-key>",
"Content-Type": "application/vnd.api+json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Session-Token': '<api-key>', 'Content-Type': 'application/vnd.api+json'},
body: JSON.stringify({
data: {
type: '<string>',
attributes: {subject_type: 'competency-holders'},
relationships: {
organisation: {data: {type: '<string>', id: '3c90c3cc-0d44-4b50-8888-8dd25736052a'}},
subjects: {data: [{type: '<string>', id: '3c90c3cc-0d44-4b50-8888-8dd25736052a'}]}
}
}
})
};
fetch('https://api.ctrl-hub.com/v3/exports', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ctrl-hub.com/v3/exports",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
'type' => '<string>',
'attributes' => [
'subject_type' => 'competency-holders'
],
'relationships' => [
'organisation' => [
'data' => [
'type' => '<string>',
'id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
],
'subjects' => [
'data' => [
[
'type' => '<string>',
'id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/vnd.api+json",
"X-Session-Token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.ctrl-hub.com/v3/exports"
payload := strings.NewReader("{\n \"data\": {\n \"type\": \"<string>\",\n \"attributes\": {\n \"subject_type\": \"competency-holders\"\n },\n \"relationships\": {\n \"organisation\": {\n \"data\": {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n },\n \"subjects\": {\n \"data\": [\n {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n ]\n }\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Session-Token", "<api-key>")
req.Header.Add("Content-Type", "application/vnd.api+json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.ctrl-hub.com/v3/exports")
.header("X-Session-Token", "<api-key>")
.header("Content-Type", "application/vnd.api+json")
.body("{\n \"data\": {\n \"type\": \"<string>\",\n \"attributes\": {\n \"subject_type\": \"competency-holders\"\n },\n \"relationships\": {\n \"organisation\": {\n \"data\": {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n },\n \"subjects\": {\n \"data\": [\n {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n ]\n }\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ctrl-hub.com/v3/exports")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Session-Token"] = '<api-key>'
request["Content-Type"] = 'application/vnd.api+json'
request.body = "{\n \"data\": {\n \"type\": \"<string>\",\n \"attributes\": {\n \"subject_type\": \"competency-holders\"\n },\n \"relationships\": {\n \"organisation\": {\n \"data\": {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n },\n \"subjects\": {\n \"data\": [\n {\n \"type\": \"<string>\",\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n ]\n }\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>",
"attributes": {
"subject_type": "competency-holders",
"error": "<string>",
"artifact": {
"filename": "<string>",
"content_type": "<string>",
"size_bytes": 1
}
},
"meta": {
"requested_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z"
},
"relationships": {
"organisation": {
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
},
"requester": {
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
},
"subjects": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
}
}
},
"jsonapi": {
"version": "<string>"
},
"included": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>",
"attributes": {
"name": "<string>",
"slug": "<string>",
"sandbox": true,
"description": "<string>",
"settings": {
"teams": {
"customer_representatives": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
]
}
}
},
"meta": {
"v3": true,
"status": "active",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"features": [
{
"name": "<string>",
"enabled": true,
"limit": 123
}
]
},
"relationships": {
"users": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
},
"service_accounts": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
},
"groups": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
},
"teams": {
"data": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
]
},
"nomenclature": {
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>"
}
}
}
}
]
}{
"id": "98ca4a78-b66f-4234-9719-aaf832ee6669",
"status": "400",
"title": "A validation error was encountered",
"source": {
"parameter": "include"
},
"meta": {
"resource": "wrong_value"
}
}{
"id": "05fc9c8d-73b9-4697-9337-57f7a567a48f",
"status": "401",
"title": "You are not authorised to access this resource",
"detail": "In order to access this resource, you need the 'admin' role.",
"code": "AUTH.001"
}{
"id": "fe9d9a69-f0a7-4fdc-bb2c-176027f316c5",
"status": "500",
"title": "Internal Server Error",
"detail": "An unexpected error occurred on the server."
}Authorizations
Session token for authentication.
Body
The export to request.
The requester is taken from the authenticated principal rather than accepted here, so an export can never be attributed to somebody else.
Show child attributes
Show child attributes
Response
An individual export.
JSON API response object
One request for generated documents, and the artefact that answered it.
Exports are retained as evidence of what was handed over, so the record and its file both outlive any later change to the underlying data.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Related resources that can be included when an export is returned.
An organisation
- Option 1
- Option 2
Show child attributes
Show child attributes