curl --request POST \
--url https://api.humanos.tech/agents/keys/regrade/{did}/{keyId} \
--header 'Content-Type: application/json' \
--data '
{
"assurance": "pop",
"binding": "self",
"reason": "attestation root distrusted",
"root": "<string>"
}
'import requests
url = "https://api.humanos.tech/agents/keys/regrade/{did}/{keyId}"
payload = {
"assurance": "pop",
"binding": "self",
"reason": "attestation root distrusted",
"root": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
assurance: 'pop',
binding: 'self',
reason: 'attestation root distrusted',
root: '<string>'
})
};
fetch('https://api.humanos.tech/agents/keys/regrade/{did}/{keyId}', 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.humanos.tech/agents/keys/regrade/{did}/{keyId}",
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([
'assurance' => 'pop',
'binding' => 'self',
'reason' => 'attestation root distrusted',
'root' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"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.humanos.tech/agents/keys/regrade/{did}/{keyId}"
payload := strings.NewReader("{\n \"assurance\": \"pop\",\n \"binding\": \"self\",\n \"reason\": \"attestation root distrusted\",\n \"root\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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.humanos.tech/agents/keys/regrade/{did}/{keyId}")
.header("Content-Type", "application/json")
.body("{\n \"assurance\": \"pop\",\n \"binding\": \"self\",\n \"reason\": \"attestation root distrusted\",\n \"root\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.humanos.tech/agents/keys/regrade/{did}/{keyId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"assurance\": \"pop\",\n \"binding\": \"self\",\n \"reason\": \"attestation root distrusted\",\n \"root\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true
}{
"statusCode": 400,
"message": "fold_failed:regrade_raises: ASSURANCE_UPDATED cannot be recorded for did:web:humanos.tech:agent:2f8b6c41-9d37-4e5a-8b02-6c1d9e7a4f35 (§5.2)",
"error": "Bad Request"
}{
"statusCode": 404,
"message": "unknown key did:web:humanos.tech:agent:2f8b6c41-9d37-4e5a-8b02-6c1d9e7a4f35#key-9",
"error": "Not Found"
}Regrade Key
Lower one key’s rung, writing ASSURANCE_UPDATED (v0.3 §5, §9.1bis): for when a root the key was graded under is distrusted or the evidence behind it is withdrawn
Downgrade only: a rung is earned by evidence at registration or renewal, never asserted
The agent’s summary follows the floor across its usable keys. Mandates pinned to the key are evaluated at the new rung from their next use
curl --request POST \
--url https://api.humanos.tech/agents/keys/regrade/{did}/{keyId} \
--header 'Content-Type: application/json' \
--data '
{
"assurance": "pop",
"binding": "self",
"reason": "attestation root distrusted",
"root": "<string>"
}
'import requests
url = "https://api.humanos.tech/agents/keys/regrade/{did}/{keyId}"
payload = {
"assurance": "pop",
"binding": "self",
"reason": "attestation root distrusted",
"root": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
assurance: 'pop',
binding: 'self',
reason: 'attestation root distrusted',
root: '<string>'
})
};
fetch('https://api.humanos.tech/agents/keys/regrade/{did}/{keyId}', 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.humanos.tech/agents/keys/regrade/{did}/{keyId}",
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([
'assurance' => 'pop',
'binding' => 'self',
'reason' => 'attestation root distrusted',
'root' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"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.humanos.tech/agents/keys/regrade/{did}/{keyId}"
payload := strings.NewReader("{\n \"assurance\": \"pop\",\n \"binding\": \"self\",\n \"reason\": \"attestation root distrusted\",\n \"root\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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.humanos.tech/agents/keys/regrade/{did}/{keyId}")
.header("Content-Type", "application/json")
.body("{\n \"assurance\": \"pop\",\n \"binding\": \"self\",\n \"reason\": \"attestation root distrusted\",\n \"root\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.humanos.tech/agents/keys/regrade/{did}/{keyId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"assurance\": \"pop\",\n \"binding\": \"self\",\n \"reason\": \"attestation root distrusted\",\n \"root\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true
}{
"statusCode": 400,
"message": "fold_failed:regrade_raises: ASSURANCE_UPDATED cannot be recorded for did:web:humanos.tech:agent:2f8b6c41-9d37-4e5a-8b02-6c1d9e7a4f35 (§5.2)",
"error": "Bad Request"
}{
"statusCode": 404,
"message": "unknown key did:web:humanos.tech:agent:2f8b6c41-9d37-4e5a-8b02-6c1d9e7a4f35#key-9",
"error": "Not Found"
}Headers
Pin request, response, and webhook shapes to a specific dated API version (YYYY-MM-DD). Omit to use the version pinned to your API key (set when the key is created; new keys default to the latest version). New integrations should target the latest version.
^\d{4}-\d{2}-\d{2}$"2026-10-16"
Path Parameters
The agent's DID, URL-encoded.
"did:web:humanos.tech:agent:2f8b6c41-9d37-4e5a-8b02-6c1d9e7a4f35"
The key id (<did>#key-<n>), URL-encoded: its # sent as %23.
"did:web:humanos.tech:agent:2f8b6c41-9d37-4e5a-8b02-6c1d9e7a4f35#key-1"
Body
The key's assurance from now on: its current one or lower.
pop, device, hardware "pop"
The key's binding from now on: its current one or lower.
self, custodial, attested "self"
Why the key is downgraded, recorded on the agent's chain.
"attestation root distrusted"
The key's current root, if any: a regrade never moves a key to another root.
Response
Returns a confirmation that the key is regraded.
Whether the operation was successful
true