curl --request POST \
--url https://api.truthlocks.com/v1/attestations/mint \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-API-Key: <api-key>' \
--data '
{
"issuer_id": "550e8400-e29b-41d4-a716-446655440000",
"kid": "es256-key-1"
}
'const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-API-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({issuer_id: '550e8400-e29b-41d4-a716-446655440000', kid: 'es256-key-1'})
};
fetch('https://api.truthlocks.com/v1/attestations/mint', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.truthlocks.com/v1/attestations/mint"
payload = {
"issuer_id": "550e8400-e29b-41d4-a716-446655440000",
"kid": "es256-key-1"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.truthlocks.com/v1/attestations/mint"
payload := strings.NewReader("{\n \"issuer_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"kid\": \"es256-key-1\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
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))
}{
"attestation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"issuer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"version": "<string>",
"status": "<string>",
"issued_at_unix": 123,
"payload_hash": "<string>",
"signature": {
"alg": "<string>",
"kid": "<string>",
"value": "<string>"
},
"log": {
"log_id": "<string>",
"leaf_index": 123,
"leaf_hash": "<string>",
"proof_url": "<string>"
},
"governance": {}
}{
"code": "AUTH_REQUIRED",
"message": "Authentication required",
"http_status": 401
}{
"code": "PAYLOAD_TOO_LARGE",
"message": "Request body exceeds maximum size of 1MB",
"http_status": 413
}{
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"http_status": 429,
"retry_after_ms": 60000
}Mint Attestation
Legacy alias for POST /v1/attestations.
Kept for backward compatibility and rewritten by the gateway.
curl --request POST \
--url https://api.truthlocks.com/v1/attestations/mint \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-API-Key: <api-key>' \
--data '
{
"issuer_id": "550e8400-e29b-41d4-a716-446655440000",
"kid": "es256-key-1"
}
'const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-API-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({issuer_id: '550e8400-e29b-41d4-a716-446655440000', kid: 'es256-key-1'})
};
fetch('https://api.truthlocks.com/v1/attestations/mint', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.truthlocks.com/v1/attestations/mint"
payload = {
"issuer_id": "550e8400-e29b-41d4-a716-446655440000",
"kid": "es256-key-1"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.truthlocks.com/v1/attestations/mint"
payload := strings.NewReader("{\n \"issuer_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"kid\": \"es256-key-1\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
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))
}{
"attestation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"issuer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"version": "<string>",
"status": "<string>",
"issued_at_unix": 123,
"payload_hash": "<string>",
"signature": {
"alg": "<string>",
"kid": "<string>",
"value": "<string>"
},
"log": {
"log_id": "<string>",
"leaf_index": 123,
"leaf_hash": "<string>",
"proof_url": "<string>"
},
"governance": {}
}{
"code": "AUTH_REQUIRED",
"message": "Authentication required",
"http_status": 401
}{
"code": "PAYLOAD_TOO_LARGE",
"message": "Request body exceeds maximum size of 1MB",
"http_status": 413
}{
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"http_status": 429,
"retry_after_ms": 60000
}Choose a record type
For a structured record, chooseschema from the record-type dropdown and enter a JSON object in claims. Leave payload_b64url empty. The server serializes these fields into the signed JSON payload. This identifies the record type; it does not independently establish that the claims are true.
Choose a verification pack
Verification packs belong to your workspace. Use the selector below with the same environment and API key as Try it, then copy the selected ID intopack_id. Omit that field for a standalone record. You can also use List verification packs or Mint in Console.
Use an existing payload
If you already have the exact bytes to sign, omitschema and claims. Encode the original bytes as unpadded base64url in payload_b64url. For JSON, serialize the object first. Application fields such as subject, claims, and schema belong inside those encoded bytes; use them either through the structured input above or inside the encoded bytes, never both. This endpoint does not independently verify the truth of submitted claims or validate arbitrary credential schemas.
Use the key’s kid and matching alg. Public-key registration alone does not make a private signing key available. See issuer keys.
Retry safely
Idempotency-Key is required. Generate one value per intended mint and retain it with the original request for retries. Do not reuse it for different content.
Document integrity
The stored document hash is selected in this order:claims.document.sha256inside a JSON payload.- The request’s
document_hash. - SHA-256 of the decoded payload bytes.
document_hash_hex to verification to compare a file hash. Keep the original payload for payload-integrity verification.
Response and delivery
HTTP 201 returnsattestation_id, issued_at_unix, signature, and log. The log position is log.leaf_index, not a top-level log_index.
recipient_email requests asynchronous notification. HTTP 201 confirms minting, not email delivery. Omit it when distributing the record yourself.
See the quickstart for a request using the actual input and response fields.
Record-type field guide
These fields are suggested claim structures, not a claim-validation or identity-check guarantee.| Schema ID | Name | Category | Claim Fields |
|---|---|---|---|
verifiable-id | Verifiable ID | Identity | full_name, employee_id, department, title, start_date |
passport | Passport | Identity | full_name, nationality, passport_number, date_of_birth, expiry_date, issuing_country |
drivers-license | Driver’s License | Identity | full_name, license_number, state, class, expiry_date, date_of_birth |
government-id | Government ID | Identity | full_name, id_number, id_type, issuing_authority, country, expiry_date |
self-sovereign-id | Self-Sovereign ID | Identity | did, display_name, created_at |
employment-verification | Employment Verification | Employment | employee_name, employer, position, department, employment_type, start_date, end_date |
professional-role | Professional Role | Employment | full_name, title, organization, department, effective_date |
membership-card | Membership Card | Employment | member_name, organization, membership_id, tier, valid_from, valid_to |
professional-certification | Professional Certification | Employment | holder_name, certification_name, issuing_body, certification_id, issued_date, expiry_date |
license | License | Employment | holder_name, license_type, license_number, issuing_authority, jurisdiction, issued_date, expiry_date |
accreditation | Accreditation | Employment | entity_name, accreditation_body, standard, scope, valid_from, valid_to |
degree | Degree | Education | student_name, institution, degree_type, field_of_study, graduation_date, honors |
completion-cert | Completion Certificate | Education | participant_name, program_name, institution, completion_date, hours |
course-credit | Course Credit | Education | student_name, course_name, institution, credits, grade, semester |
transcript | Transcript | Education | student_name, institution, program, gpa, total_credits, issue_date |
micro-credential | Micro-Credential | Education | earner_name, credential_name, issuer, skills, earned_date |
training-completion | Training Completion | Education | trainee_name, training_program, provider, completion_date, score, certificate_id |
medical-license | Medical License | Healthcare | practitioner_name, license_number, specialty, state, issued_date, expiry_date |
dea-registration | DEA Registration | Healthcare | registrant_name, dea_number, schedules, business_activity, expiry_date |
board-certification | Board Certification | Healthcare | physician_name, board, specialty, certification_date, expiry_date |
health-credential | Health Credential | Healthcare | patient_name, credential_type, provider, date, details |
vaccination-record | Vaccination Record | Healthcare | patient_name, vaccine_name, manufacturer, lot_number, date_administered, dose_number, site |
aml-kyc | AML/KYC Check | Compliance | entity_name, check_type, result, risk_level, verified_by, verified_at |
security-clearance | Security Clearance | Compliance | holder_name, clearance_level, granting_agency, granted_date, expiry_date |
sam-gov | SAM.gov Registration | Compliance | entity_name, cage_code, uei, registration_status, expiry_date |
jurisdiction-approval | Jurisdiction Approval | Compliance | entity_name, jurisdiction, approval_type, approved_date, conditions |
attestation-of-will | Attestation of Will | Compliance | declarant_name, declaration, witness, date |
bank-verification | Bank Verification | Financial | account_holder, bank_name, account_type, routing_number_last4, verified_date |
credit-attestation | Credit Attestation | Financial | entity_name, credit_score_range, reporting_agency, assessment_date |
income-verification | Income Verification | Financial | individual_name, employer, annual_income_range, verification_date, tax_year |
skill-badge | Skill Badge | Skills & Training | earner_name, skill_name, proficiency_level, assessed_by, earned_date |
competency | Competency Attestation | Skills & Training | individual_name, competency, level, assessor, assessment_date |
industry-cert | Industry Certification | Skills & Training | holder_name, certification, issuing_body, cert_id, issued_date, expiry_date |
product-authenticity | Product Authenticity | Supply Chain | product_name, sku, serial_number, manufacturer, manufactured_date, origin_country |
chain-of-custody | Chain of Custody | Supply Chain | item_description, from_entity, to_entity, transfer_date, location, condition |
origin-verification | Origin Verification | Supply Chain | product_name, origin_country, origin_region, certifying_body, verified_date |
custom | Custom | Other | subject, type, details |
attestation | Generic Attestation | Other | subject, claim, evidence |
Authorizations
API key for machine-to-machine authentication
Headers
Retain the same value and request body when retrying one mint.
Body
Choose either raw payload_b64url or the structured schema and claims fields. Never send both formats.
The UUID of the issuer creating the attestation
"550e8400-e29b-41d4-a716-446655440000"
Key identifier for the signing key
"es256-key-1"
Must match the selected issuer signing key.
Ed25519, ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384, PS512 MIME type of the original bytes, such as application/json, application/pdf or image/png. Structured schema/claims input requires application/json.
"application/json"
Optional hexadecimal SHA-256 document hash. An embedded claims.document.sha256 takes precedence; otherwise this field is used, then the decoded payload hash.
Optional workspace verification-pack UUID. Use List verification packs with the same API key to select an existing active pack; omit for a standalone record.
Unpadded base64url of the exact bytes to sign. Use this OR schema plus claims.
Email address of the credential recipient. When provided, the platform sends a notification email with a link to view the attestation on the consumer portal (verify.truthlocks.com). If the recipient does not have a consumer portal account, they receive an invitation to sign up. This enables B2C credential delivery workflows.
Record type for structured input. Provide claims and omit payload_b64url. This label does not independently validate the truth of claims.
verifiable-id, passport, drivers-license, government-id, self-sovereign-id, employment-verification, professional-role, membership-card, professional-certification, license, accreditation, degree, completion-cert, course-credit, transcript, micro-credential, training-completion, medical-license, dea-registration, board-certification, health-credential, vaccination-record, aml-kyc, security-clearance, sam-gov, jurisdiction-approval, attestation-of-will, bank-verification, credit-attestation, income-verification, skill-badge, competency, industry-cert, product-authenticity, chain-of-custody, origin-verification, custom, attestation "verifiable-id"
Structured record fields. Required with schema; cannot be combined with payload_b64url.
{
"full_name": "Example recipient",
"employee_id": "QA-001"
}

