curl --request POST \
--url https://api.nexspace365.com/api/approvals/{approvalId}/approve \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"reason": "<string>"
}
'import requests
url = "https://api.nexspace365.com/api/approvals/{approvalId}/approve"
payload = { "reason": "<string>" }
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({reason: '<string>'})
};
fetch('https://api.nexspace365.com/api/approvals/{approvalId}/approve', 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/approvals/{approvalId}/approve",
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([
'reason' => '<string>'
]),
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/approvals/{approvalId}/approve"
payload := strings.NewReader("{\n \"reason\": \"<string>\"\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/approvals/{approvalId}/approve")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nexspace365.com/api/approvals/{approvalId}/approve")
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 \"reason\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"outcome": "resolved",
"approvalId": 123,
"decision": "approve",
"runId": "<string>",
"runResumed": true,
"runRejected": true,
"execution": {
"success": true,
"error": "<string>"
}
}Approve a pending agent action (and resume its run)
Approve a require_approval action raised by one of your headless runs.
The deferred tool executes with the ORIGINAL requester’s scope, its
result is appended to the run’s conversation, and once ALL of the run’s
approvals are terminal the run resumes (full continuation, bounded by the
agent’s maxIterations). Requires the agents:approve scope and ownership
of the owning run. Consequential — writes an audit entry.
Two gates, not one. Owning the run is what lets you see the
approval — it does not make you a valid approver. Because your own run
raised the action, every decision here is by definition a
self-approval, so the credential’s bound user ALSO needs the
ai.approve_actions RBAC permission (held by a facility admin scoped to
the approval’s facility, or an internal operator). A credential with
agents:approve whose user lacks ai.approve_actions gets 403
SELF_APPROVAL_FORBIDDEN.
curl --request POST \
--url https://api.nexspace365.com/api/approvals/{approvalId}/approve \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"reason": "<string>"
}
'import requests
url = "https://api.nexspace365.com/api/approvals/{approvalId}/approve"
payload = { "reason": "<string>" }
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({reason: '<string>'})
};
fetch('https://api.nexspace365.com/api/approvals/{approvalId}/approve', 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/approvals/{approvalId}/approve",
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([
'reason' => '<string>'
]),
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/approvals/{approvalId}/approve"
payload := strings.NewReader("{\n \"reason\": \"<string>\"\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/approvals/{approvalId}/approve")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nexspace365.com/api/approvals/{approvalId}/approve")
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 \"reason\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"outcome": "resolved",
"approvalId": 123,
"decision": "approve",
"runId": "<string>",
"runResumed": true,
"runRejected": true,
"execution": {
"success": true,
"error": "<string>"
}
}Authorizations
API key or personal access token (NEX-1042). Send as
Authorization: Bearer <token>. Token format:
nex_live_…— live API key (server-to-server)nex_test_…— sandbox API keynex_pat_…— personal access token (acts as the issuing user)
Authorization is decided by the key's scopes array, not the
owning user's RBAC role. See POST /api/api-keys to mint a key.
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
Body
2000Response
Approval resolved
Result of resolving (approving/rejecting) a pending agent action.
resolved approve, reject The headless run this approval belongs to.
True when the owning run was re-driven (all its approvals now terminal).
True when the owning run was terminated as rejected.
Outcome of executing the deferred tool (approve only).
Show child attributes
Show child attributes

