curl --request POST \
--url https://api.nexspace365.com/api/staff/{id}/credentials \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"type": "certification",
"name": "Forklift Operator Certification",
"issuer": "National Safety Council",
"issueDate": "2024-06-01",
"expirationDate": "2027-06-01",
"fileUrl": "https://files.nexspace365.com/creds/7.pdf"
}
'import requests
url = "https://api.nexspace365.com/api/staff/{id}/credentials"
payload = {
"type": "certification",
"name": "Forklift Operator Certification",
"issuer": "National Safety Council",
"issueDate": "2024-06-01",
"expirationDate": "2027-06-01",
"fileUrl": "https://files.nexspace365.com/creds/7.pdf"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
type: 'certification',
name: 'Forklift Operator Certification',
issuer: 'National Safety Council',
issueDate: '2024-06-01',
expirationDate: '2027-06-01',
fileUrl: 'https://files.nexspace365.com/creds/7.pdf'
})
};
fetch('https://api.nexspace365.com/api/staff/{id}/credentials', 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.nexspace365.com/api/staff/{id}/credentials",
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([
'type' => 'certification',
'name' => 'Forklift Operator Certification',
'issuer' => 'National Safety Council',
'issueDate' => '2024-06-01',
'expirationDate' => '2027-06-01',
'fileUrl' => 'https://files.nexspace365.com/creds/7.pdf'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.nexspace365.com/api/staff/{id}/credentials"
payload := strings.NewReader("{\n \"type\": \"certification\",\n \"name\": \"Forklift Operator Certification\",\n \"issuer\": \"National Safety Council\",\n \"issueDate\": \"2024-06-01\",\n \"expirationDate\": \"2027-06-01\",\n \"fileUrl\": \"https://files.nexspace365.com/creds/7.pdf\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/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.nexspace365.com/api/staff/{id}/credentials")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"certification\",\n \"name\": \"Forklift Operator Certification\",\n \"issuer\": \"National Safety Council\",\n \"issueDate\": \"2024-06-01\",\n \"expirationDate\": \"2027-06-01\",\n \"fileUrl\": \"https://files.nexspace365.com/creds/7.pdf\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nexspace365.com/api/staff/{id}/credentials")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"certification\",\n \"name\": \"Forklift Operator Certification\",\n \"issuer\": \"National Safety Council\",\n \"issueDate\": \"2024-06-01\",\n \"expirationDate\": \"2027-06-01\",\n \"fileUrl\": \"https://files.nexspace365.com/creds/7.pdf\"\n}"
response = http.request(request)
puts response.read_body{
"id": 7,
"userId": 42,
"type": "certification",
"name": "Forklift Operator Certification",
"issuer": "National Safety Council",
"issueDate": "2024-06-01",
"expirationDate": "2027-06-01",
"status": "active",
"fileUrl": "https://files.nexspace365.com/creds/7.pdf"
}{
"error": {
"message": "<string>",
"code": "<string>",
"details": {},
"suggestion": "<string>",
"retryable": true
},
"requestId": "<string>"
}{
"error": {
"message": "Invalid or revoked API key",
"code": "UNAUTHENTICATED",
"suggestion": "Send a valid `Authorization: Bearer <token>` (nex_live_/nex_pat_ key, JWT, or OAuth access token).",
"retryable": false
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"details": {},
"suggestion": "<string>",
"retryable": true
},
"requestId": "<string>"
}{
"error": {
"message": "Rate limit exceeded for this API key",
"code": "API_KEY_RATE_LIMITED",
"suggestion": "Wait until X-RateLimit-Reset before retrying, or batch operations.",
"retryable": true
}
}Add a credential
Attach a new credential to a staff member. Required API-key scope: staff:write
curl --request POST \
--url https://api.nexspace365.com/api/staff/{id}/credentials \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"type": "certification",
"name": "Forklift Operator Certification",
"issuer": "National Safety Council",
"issueDate": "2024-06-01",
"expirationDate": "2027-06-01",
"fileUrl": "https://files.nexspace365.com/creds/7.pdf"
}
'import requests
url = "https://api.nexspace365.com/api/staff/{id}/credentials"
payload = {
"type": "certification",
"name": "Forklift Operator Certification",
"issuer": "National Safety Council",
"issueDate": "2024-06-01",
"expirationDate": "2027-06-01",
"fileUrl": "https://files.nexspace365.com/creds/7.pdf"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
type: 'certification',
name: 'Forklift Operator Certification',
issuer: 'National Safety Council',
issueDate: '2024-06-01',
expirationDate: '2027-06-01',
fileUrl: 'https://files.nexspace365.com/creds/7.pdf'
})
};
fetch('https://api.nexspace365.com/api/staff/{id}/credentials', 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.nexspace365.com/api/staff/{id}/credentials",
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([
'type' => 'certification',
'name' => 'Forklift Operator Certification',
'issuer' => 'National Safety Council',
'issueDate' => '2024-06-01',
'expirationDate' => '2027-06-01',
'fileUrl' => 'https://files.nexspace365.com/creds/7.pdf'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.nexspace365.com/api/staff/{id}/credentials"
payload := strings.NewReader("{\n \"type\": \"certification\",\n \"name\": \"Forklift Operator Certification\",\n \"issuer\": \"National Safety Council\",\n \"issueDate\": \"2024-06-01\",\n \"expirationDate\": \"2027-06-01\",\n \"fileUrl\": \"https://files.nexspace365.com/creds/7.pdf\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/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.nexspace365.com/api/staff/{id}/credentials")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"certification\",\n \"name\": \"Forklift Operator Certification\",\n \"issuer\": \"National Safety Council\",\n \"issueDate\": \"2024-06-01\",\n \"expirationDate\": \"2027-06-01\",\n \"fileUrl\": \"https://files.nexspace365.com/creds/7.pdf\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nexspace365.com/api/staff/{id}/credentials")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"certification\",\n \"name\": \"Forklift Operator Certification\",\n \"issuer\": \"National Safety Council\",\n \"issueDate\": \"2024-06-01\",\n \"expirationDate\": \"2027-06-01\",\n \"fileUrl\": \"https://files.nexspace365.com/creds/7.pdf\"\n}"
response = http.request(request)
puts response.read_body{
"id": 7,
"userId": 42,
"type": "certification",
"name": "Forklift Operator Certification",
"issuer": "National Safety Council",
"issueDate": "2024-06-01",
"expirationDate": "2027-06-01",
"status": "active",
"fileUrl": "https://files.nexspace365.com/creds/7.pdf"
}{
"error": {
"message": "<string>",
"code": "<string>",
"details": {},
"suggestion": "<string>",
"retryable": true
},
"requestId": "<string>"
}{
"error": {
"message": "Invalid or revoked API key",
"code": "UNAUTHENTICATED",
"suggestion": "Send a valid `Authorization: Bearer <token>` (nex_live_/nex_pat_ key, JWT, or OAuth access token).",
"retryable": false
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"details": {},
"suggestion": "<string>",
"retryable": true
},
"requestId": "<string>"
}{
"error": {
"message": "Rate limit exceeded for this API key",
"code": "API_KEY_RATE_LIMITED",
"suggestion": "Wait until X-RateLimit-Reset before retrying, or batch operations.",
"retryable": true
}
}Authorizations
JWT token authentication
Headers
Pin the request to a dated API version (e.g. 2026-05-10). Applied by app-level middleware to every /api route (server/routes/index.ts → apiVersionMiddleware), which echoes the resolved value back in the NexSpace-Version response header. Omit to get the latest version. Discover the catalog at GET /.well-known/api-versions.
^\d{4}-\d{2}-\d{2}$Replay guard for write requests. Applied by app-level middleware to every /api route (server/routes/index.ts → idempotencyMiddleware), which only acts on POST/PUT/PATCH — GET, DELETE and OPTIONS ignore the header. Re-sending the same key with an identical body within 24 hours replays the original response; the same key with a different body returns 409.
255Path Parameters
Staff ID
Body
Response
Credential created successfully
Unique credential identifier
ID of the user the credential belongs to
Credential type (e.g., license, certification, training)
Human-readable credential name
Issuing authority or organization
Date the credential was issued
Date the credential expires
Current verification/validity status
active, expiring, expired, pending, rejected URL to the uploaded credential document

