Attestation report
curl --request GET \
--url https://tee.redpill.ai/v1/aci/attestation \
--header 'Authorization: Bearer <token>'import requests
url = "https://tee.redpill.ai/v1/aci/attestation"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://tee.redpill.ai/v1/aci/attestation', 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://tee.redpill.ai/v1/aci/attestation",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://tee.redpill.ai/v1/aci/attestation"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://tee.redpill.ai/v1/aci/attestation")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://tee.redpill.ai/v1/aci/attestation")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_bodyVerification
Attestation report
The gateway TEE attestation report, bound to a caller-supplied nonce.
GET
/
v1
/
aci
/
attestation
Attestation report
curl --request GET \
--url https://tee.redpill.ai/v1/aci/attestation \
--header 'Authorization: Bearer <token>'import requests
url = "https://tee.redpill.ai/v1/aci/attestation"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://tee.redpill.ai/v1/aci/attestation', 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://tee.redpill.ai/v1/aci/attestation",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://tee.redpill.ai/v1/aci/attestation"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://tee.redpill.ai/v1/aci/attestation")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://tee.redpill.ai/v1/aci/attestation")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_bodyReturns the gateway’s attestation report: the hardware-backed proof of which TEE workload is serving
the API, plus the public keys it signs with. Verify this report before trusting any
receipt. For what each field proves, see
Attestation report.
GET /v1/aci/attestation?nonce={nonce}
Request
string
Exactly 64 lowercase hex characters (32 random bytes). The gateway binds it into the quote’s
report_data so you can prove the report is not a replay.Response
200 OK, application/json. The bare attestation report.
Top-level fields
| Field | Type | Description |
|---|---|---|
api_version | string | ACI version token, for example aci/1. |
workload_keyset_digest | string | sha256:… digest over the published keyset. |
attestation | object | The attestation evidence and keyset (below). |
service_capabilities | object | supported_e2ee_versions and the serving mode. |
attestation object
| Field | Type | Description |
|---|---|---|
tee_type | string | TEE technology, for example tdx. |
report_data | string | Value bound into the quote. Commits to your nonce and the keyset. |
source_provenance | object | Workload-declared repo_url, repo_commit, image_digest, and image_provenance labels. |
workload_keyset | object | subject, not_after, receipt_signing_keys, e2ee_public_keys, and tls_public_keys. |
evidence | object | quote, quote_report_data, event_log, vm_config, key_custody. |
Example (long values truncated)
{
"api_version": "aci/1",
"workload_keyset_digest": "sha256:3eff0836cd104d8cb5f8e8ee361789cf9…",
"attestation": {
"tee_type": "tdx",
"report_data": "7b7daf62d7e9e31f5d17e70d32c010bda9ead273…",
"source_provenance": {
"repo_url": "https://github.com/Dstack-TEE/private-ai-gateway.git",
"repo_commit": "9d45c7e3d48d2f74c31cd85f1fb5c6cee1435ef3",
"image_digest": null,
"image_provenance": null
},
"workload_keyset": {
"subject": null,
"not_after": 1790498751,
"receipt_signing_keys": [ { "key_id": "receipt-v1", "algo": "ed25519", "public_key": "211c…" } ],
"e2ee_public_keys": [],
"tls_public_keys": [ { "spki_sha256": "943c…", "domain": "tee.redpill.ai" } ]
},
"evidence": { "quote": "040002008100…", "quote_report_data": "7b7daf…", "event_log": "[{…}]", "vm_config": "{…}", "key_custody": { "provider": "dstack-kms", "keys": [ … ] } }
},
"service_capabilities": { "supported_e2ee_versions": ["2"], "serving": "aggregator" }
}
Verifying the report
- Verify
attestation.evidence.quoteagainst Intel DCAP collateral, and confirm its report data binds yournonceand theworkload_keyset. - Recompute the JCS digest of
workload_keysetand compare it withworkload_keyset_digest. - Confirm
workload_keyset_digestmatches the receipts you verify. - Confirm
workload_keyset.not_afteris in the future. - Replay the event log to RTMR3 and confirm the measured compose hash equals
sha256(app_compose). - For reviewed-release enforcement, require that compose hash in an independently obtained
allowlist. Do not treat
source_provenanceas the trust anchor.
Legacy alias
GET /v1/attestation/report?nonce=… returns the same gateway attestation for clients written
against earlier API versions, with two differences: top-level signing_address, signing_algo, and
signing_public_key derived from the gateway keyset (?signing_algo=ecdsa, the default, or
ed25519 selects the key), and all_attestations collapsed to a single entry. Earlier API versions
returned the upstream model’s attestation here; the upstream verification for a response is now in
the receipt and the attested session. New
integrations should use /v1/aci/attestation.
Related
Get receipt
The signed per-response receipt.
Attestation report concept
What each field proves.
Was this page helpful?