curl --request POST \
--url https://api.rootkey.ai/api-v1/agent-step-ups \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"vaultAddress": "<string>"
}
'import requests
url = "https://api.rootkey.ai/api-v1/agent-step-ups"
payload = { "vaultAddress": "<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({vaultAddress: '<string>'})
};
fetch('https://api.rootkey.ai/api-v1/agent-step-ups', 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.rootkey.ai/api-v1/agent-step-ups",
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([
'vaultAddress' => '<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.rootkey.ai/api-v1/agent-step-ups"
payload := strings.NewReader("{\n \"vaultAddress\": \"<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.rootkey.ai/api-v1/agent-step-ups")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"vaultAddress\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rootkey.ai/api-v1/agent-step-ups")
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 \"vaultAddress\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"url": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}{
"id": "<string>",
"url": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}{
"error": {
"requestId": "<string>",
"message": "<string>",
"errorCode": "<string>",
"docUrl": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"error": {
"requestId": "<string>",
"message": "<string>",
"errorCode": "<string>",
"docUrl": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"error": {
"requestId": "<string>",
"message": "<string>",
"errorCode": "<string>",
"docUrl": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"error": {
"requestId": "<string>",
"message": "<string>",
"errorCode": "<string>",
"docUrl": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}Ask for access to RESTRICTED data
An agent asks the person it acts for to open ONE RESTRICTED vault or table for a short time. It is the answer to agent_step_up_required, which an agent gets only in an organization that allows it (allowRestrictedStepUp on GET /organization). The answer has a url: give it to the person. They open it in ROOTKey and approve with a fresh second factor (or deny). Once approved, the same connection may read and write that vault or table until the approval ends (a few minutes), and never delete anything in it. Follow the request with GET /agent-step-ups/{stepUpId}. Asking again while the request waits, or while an approval runs, answers 200 with the same request. Everything else still applies: scopes, the organization’s mode, the user’s role and teams. The vault is named in the body only. Only a personal access token or an app connected through the hosted connector can call it; it needs the rootkey.read scope and a role that may read vaults (for a table, also tables).
curl --request POST \
--url https://api.rootkey.ai/api-v1/agent-step-ups \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"vaultAddress": "<string>"
}
'import requests
url = "https://api.rootkey.ai/api-v1/agent-step-ups"
payload = { "vaultAddress": "<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({vaultAddress: '<string>'})
};
fetch('https://api.rootkey.ai/api-v1/agent-step-ups', 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.rootkey.ai/api-v1/agent-step-ups",
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([
'vaultAddress' => '<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.rootkey.ai/api-v1/agent-step-ups"
payload := strings.NewReader("{\n \"vaultAddress\": \"<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.rootkey.ai/api-v1/agent-step-ups")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"vaultAddress\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rootkey.ai/api-v1/agent-step-ups")
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 \"vaultAddress\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"url": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}{
"id": "<string>",
"url": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}{
"error": {
"requestId": "<string>",
"message": "<string>",
"errorCode": "<string>",
"docUrl": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"error": {
"requestId": "<string>",
"message": "<string>",
"errorCode": "<string>",
"docUrl": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"error": {
"requestId": "<string>",
"message": "<string>",
"errorCode": "<string>",
"docUrl": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"error": {
"requestId": "<string>",
"message": "<string>",
"errorCode": "<string>",
"docUrl": "<string>",
"timestamp": "2023-11-07T05:31:56Z"
}
}Authorizations
Personal access token of a ROOTKey user, sent as Authorization: Bearer rk_pat_.... A token acts as the user who created it, in the organization named by the X-RootKey-Organization header, and never with more access than that user has in the ROOTKey app: the organization's agent policy, the user's own role and teams, and the token's scopes (rootkey.read, rootkey.write, rootkey.delete) all apply. A missing, malformed, unknown, revoked or expired token gets the same 401. Send either an x-api-key or a bearer token, never both: a request with both gets conflicting_credentials. See Authentication.
Headers
The organization a personal access token acts in: the id of one of the organizations that GET /organizations lists. Required with a personal access token on every endpoint that works inside an organization; without it the request gets organization_header_required. Ignored with an API key, which belongs to exactly one organization.
Whether a personal access token works on live data (false, the default) or on test data (true). Only this header decides, never a query string or a body field. An API key is itself a test or a live key and works on that data.
true, false Body
The RESTRICTED vault or table, from GET /vaults or GET /tables.
Response
This connection already has a live request for that vault or table: the same one, nothing new.
The request. GET /agent-step-ups/{stepUpId} reports its state.
The page in ROOTKey where the person approves or denies it. Give it to the person; it names nothing else.
Until when the person can approve it; for an approval that is running, when it ends.
Was this page helpful?

