curl --request POST \
--url https://api.nexspace365.com/api/shifts/{id}/unassign \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"staffIds": [
123
]
}
'import requests
url = "https://api.nexspace365.com/api/shifts/{id}/unassign"
payload = { "staffIds": [123] }
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({staffIds: [123]})
};
fetch('https://api.nexspace365.com/api/shifts/{id}/unassign', 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/shifts/{id}/unassign",
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([
'staffIds' => [
123
]
]),
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/shifts/{id}/unassign"
payload := strings.NewReader("{\n \"staffIds\": [\n 123\n ]\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/shifts/{id}/unassign")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"staffIds\": [\n 123\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nexspace365.com/api/shifts/{id}/unassign")
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 \"staffIds\": [\n 123\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": 1024,
"facilityId": 1,
"title": "Evening Fulfillment",
"date": "2026-05-20",
"startTime": "16:00",
"endTime": "23:59",
"department": "Fulfillment",
"specialty": "Forklift Operator",
"requiredWorkers": 3,
"assignedStaffIds": [
42,
58
],
"status": "open",
"urgency": "high",
"rate": 32,
"notes": "Peak-season surge coverage",
"createdAt": "2026-05-10T12:00:00Z",
"updatedAt": "2026-05-11T08:15:00Z"
}{
"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": "Insufficient API key scope",
"code": "INSUFFICIENT_SCOPE",
"suggestion": "Mint or rotate a key that includes the required scope, or grant a wildcard like `resource:*`.",
"retryable": false
}
}{
"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
}
}Unassign staff from shift
Remove staff member assignments from a shift. Required API-key scope: shifts:assign
curl --request POST \
--url https://api.nexspace365.com/api/shifts/{id}/unassign \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"staffIds": [
123
]
}
'import requests
url = "https://api.nexspace365.com/api/shifts/{id}/unassign"
payload = { "staffIds": [123] }
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({staffIds: [123]})
};
fetch('https://api.nexspace365.com/api/shifts/{id}/unassign', 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/shifts/{id}/unassign",
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([
'staffIds' => [
123
]
]),
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/shifts/{id}/unassign"
payload := strings.NewReader("{\n \"staffIds\": [\n 123\n ]\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/shifts/{id}/unassign")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"staffIds\": [\n 123\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nexspace365.com/api/shifts/{id}/unassign")
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 \"staffIds\": [\n 123\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": 1024,
"facilityId": 1,
"title": "Evening Fulfillment",
"date": "2026-05-20",
"startTime": "16:00",
"endTime": "23:59",
"department": "Fulfillment",
"specialty": "Forklift Operator",
"requiredWorkers": 3,
"assignedStaffIds": [
42,
58
],
"status": "open",
"urgency": "high",
"rate": 32,
"notes": "Peak-season surge coverage",
"createdAt": "2026-05-10T12:00:00Z",
"updatedAt": "2026-05-11T08:15:00Z"
}{
"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": "Insufficient API key scope",
"code": "INSUFFICIENT_SCOPE",
"suggestion": "Mint or rotate a key that includes the required scope, or grant a wildcard like `resource:*`.",
"retryable": false
}
}{
"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
Shift ID
Body
Array of staff IDs to unassign
Response
Staff unassigned successfully
Unique shift identifier
Facility where the shift takes place
Shift title or description
Shift date
Shift start time
Shift end time
Department for the shift
Required specialty
Number of workers needed
IDs of assigned staff members
Current shift status
open, assigned, in_progress, completed, cancelled Shift urgency level
low, medium, high, critical Pay rate for the shift
Additional notes or requirements

