Verify Attestation
curl --request POST \
--url https://api.truthlocks.com/v1/verify \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"attestation_id": "660e8400-e29b-41d4-a716-446655440001",
"payload_b64url": "eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0",
"document_hash_hex": "a1b2c3d4e5f6..."
}
'import requests
url = "https://api.truthlocks.com/v1/verify"
payload = {
"attestation_id": "660e8400-e29b-41d4-a716-446655440001",
"payload_b64url": "eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0",
"document_hash_hex": "a1b2c3d4e5f6..."
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
attestation_id: '660e8400-e29b-41d4-a716-446655440001',
payload_b64url: 'eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0',
document_hash_hex: 'a1b2c3d4e5f6...'
})
};
fetch('https://api.truthlocks.com/v1/verify', 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.truthlocks.com/v1/verify",
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([
'attestation_id' => '660e8400-e29b-41d4-a716-446655440001',
'payload_b64url' => 'eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0',
'document_hash_hex' => 'a1b2c3d4e5f6...'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.truthlocks.com/v1/verify"
payload := strings.NewReader("{\n \"attestation_id\": \"660e8400-e29b-41d4-a716-446655440001\",\n \"payload_b64url\": \"eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0\",\n \"document_hash_hex\": \"a1b2c3d4e5f6...\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.truthlocks.com/v1/verify")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"attestation_id\": \"660e8400-e29b-41d4-a716-446655440001\",\n \"payload_b64url\": \"eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0\",\n \"document_hash_hex\": \"a1b2c3d4e5f6...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.truthlocks.com/v1/verify")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"attestation_id\": \"660e8400-e29b-41d4-a716-446655440001\",\n \"payload_b64url\": \"eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0\",\n \"document_hash_hex\": \"a1b2c3d4e5f6...\"\n}"
response = http.request(request)
puts response.read_body{
"verdict": "VALID",
"valid": true,
"details": {
"issuer_id": "550e8400-e29b-41d4-a716-446655440000",
"issuer_name": "Acme University",
"log_index": 42
}
}Verification
Verify Attestation
Performs a full cryptographic and status verification of an attestation.
Verdict Truth Table
| Verdict | Valid | Description |
|---|---|---|
| VALID | true | Signature correct, attestation active |
| REVOKED | false | Attestation explicitly revoked |
| SUPERSEDED | false | Replaced by newer attestation |
| ALTERED | false | Signature verification failed |
| UNKNOWN | false | Attestation not found |
POST
/
v1
/
verify
Verify Attestation
curl --request POST \
--url https://api.truthlocks.com/v1/verify \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"attestation_id": "660e8400-e29b-41d4-a716-446655440001",
"payload_b64url": "eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0",
"document_hash_hex": "a1b2c3d4e5f6..."
}
'import requests
url = "https://api.truthlocks.com/v1/verify"
payload = {
"attestation_id": "660e8400-e29b-41d4-a716-446655440001",
"payload_b64url": "eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0",
"document_hash_hex": "a1b2c3d4e5f6..."
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
attestation_id: '660e8400-e29b-41d4-a716-446655440001',
payload_b64url: 'eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0',
document_hash_hex: 'a1b2c3d4e5f6...'
})
};
fetch('https://api.truthlocks.com/v1/verify', 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.truthlocks.com/v1/verify",
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([
'attestation_id' => '660e8400-e29b-41d4-a716-446655440001',
'payload_b64url' => 'eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0',
'document_hash_hex' => 'a1b2c3d4e5f6...'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.truthlocks.com/v1/verify"
payload := strings.NewReader("{\n \"attestation_id\": \"660e8400-e29b-41d4-a716-446655440001\",\n \"payload_b64url\": \"eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0\",\n \"document_hash_hex\": \"a1b2c3d4e5f6...\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.truthlocks.com/v1/verify")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"attestation_id\": \"660e8400-e29b-41d4-a716-446655440001\",\n \"payload_b64url\": \"eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0\",\n \"document_hash_hex\": \"a1b2c3d4e5f6...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.truthlocks.com/v1/verify")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"attestation_id\": \"660e8400-e29b-41d4-a716-446655440001\",\n \"payload_b64url\": \"eyJzdWJqZWN0IjoiZGlkOnRydXRobG9jazoxMjMiLCJ2ZXJpZmllZCI6dHJ1ZX0\",\n \"document_hash_hex\": \"a1b2c3d4e5f6...\"\n}"
response = http.request(request)
puts response.read_body{
"verdict": "VALID",
"valid": true,
"details": {
"issuer_id": "550e8400-e29b-41d4-a716-446655440000",
"issuer_name": "Acme University",
"log_index": 42
}
}Performs a comprehensive multi-step verification of an attestation. The pipeline resolves the attestation, checks document integrity, validates status (revoked, superseded, expired), resolves issuer governance metadata, verifies the cryptographic signature against the issuer’s public key, checks the transparency log inclusion proof, and evaluates platform policies. Returns a single verdict with detailed reasons, transparency log data, and full issuer governance context including both current and snapshot-at-mint values. This endpoint is publicly accessible and does not require authentication.
To verify the latest version, make a second request using the
Parameters
string
required
The UUID of the attestation to verify. This is the unique identifier returned
when the attestation was originally minted.
string
Base64url-encoded payload for signature verification. If provided, the system
verifies that the SHA-256 hash of this payload matches the stored
payload_hash. Use this to confirm you hold the exact original content that was
attested.
string
SHA-256 hex hash of the original document for integrity verification. If
provided, compared against the stored document_hash. Use this when you want to
verify a file’s integrity without sending the full payload over the wire.
The comparison is case-insensitive.
Document hash verification
When you includedocument_hash_hex in your verification request, the platform compares it against the document_hash stored at mint time. Two additional reason codes may appear in the reasons array of the response:
| Reason | Verdict | Description |
|---|---|---|
document_hash_mismatch | ALTERED | The provided hash does not match the stored document hash. The content has been modified since it was protected. |
document_hash_not_stored | (continues verification) | The attestation was minted without a document hash, so the check cannot be performed. Verification continues with signature and log checks. |
The
document_hash is set automatically during minting. The platform resolves
it from three sources in priority order: an embedded claims.document.sha256
in the payload, an explicit document_hash field in the mint request, or an
auto-computed SHA-256 of the payload bytes.Verdict reference
Every verification request returns exactly oneverdict value.
| Verdict | Description |
|---|---|
VALID | Cryptographically valid and trusted |
ALTERED | Document hash mismatch — the content has been modified |
REVOKED | Explicitly revoked by the issuer |
SUPERSEDED | A newer version of this attestation exists. Follow superseded_by_attestation_id in the response to find the replacement. |
EXPIRED | The attestation has passed its validity period |
INVALID | Cryptographic signature verification failed |
NOT_FOUND | No attestation exists with the given ID |
UNKNOWN_ISSUER | The issuer could not be resolved or is no longer trusted |
Superseded attestations
When an attestation has been replaced by a newer version, the verdict isSUPERSEDED and the response includes a superseded_by_attestation_id field pointing to the replacement. Use this to follow the version chain:
{
"verdict": "SUPERSEDED",
"superseded_by_attestation_id": "880e8400-e29b-41d4-a716-446655440003",
"reasons": ["attestation_superseded"]
}
superseded_by_attestation_id value as the attestation_id.
Billing and rate limits
API verification requests are metered against your organization’s billing plan. The consumer portal at verify.truthlocks.com provides unlimited free verification for end-users.| Channel | Auth required | Metered | Rate limit |
|---|---|---|---|
POST /v1/verify (API) | No | Yes — counted against the issuer’s plan quota | Plan-dependent |
| verify.truthlocks.com (Portal) | No | No — free and unlimited | Fair-use rate limiting only |
When the issuer’s API verification quota is exhausted, the endpoint returns HTTP
402 with the BILLING_LIMIT error code. Upgrade your plan or wait for the quota to reset at the start of the next billing cycle.402 — Quota exhausted
{
"code": "BILLING_LIMIT",
"message": "API verification quota exhausted for the current billing cycle. Upgrade your plan or use the free consumer portal at verify.truthlocks.com.",
"http_status": 402
}
For most use cases, share a verification link instead of calling the API directly. Portal verifications are free and provide a rich UI with issuer branding, governance details, and document integrity checks.Verification link format:
https://verify.truthlocks.com/a/{attestation_id}Authorizations
API key for machine-to-machine authentication
Body
application/json
The unique identifier of the attestation to verify.
Base64url-encoded payload for signature verification. If provided, the system verifies that the SHA-256 hash of this payload matches the stored payload_hash. Use this to confirm you hold the exact original content that was attested.
SHA-256 hex hash of the original document for integrity verification. If provided, compared against the stored document_hash. Use this when you want to verify a file's integrity without sending the full payload over the wire.
Response
200 - application/json
Verification result
- VALID: Signature verified and attestation is active
- REVOKED: Attestation was explicitly revoked
- SUPERSEDED: Attestation replaced by a newer version
- ALTERED: Signature verification failed (tampered)
- INVALID: General validation failure
- UNKNOWN: Attestation not found
Available options:
VALID, INVALID, REVOKED, ALTERED, SUPERSEDED, UNKNOWN Show child attributes
Show child attributes

