Create a scoped API key
Use least-privilege scopes. Candidate reads need candidates:read, score lookups need scores:read, webhook registration needs webhooks:write, and private agent reports need agent-decisions:write.
Manage API keysDeveloper docs
Use Humanproof's public API, sandbox fixtures, and signed webhooks to plug a credit score for your skills into search, profile, marketplace, and agent workflows.
A practical order for getting from dashboard setup to a production integration.
Use least-privilege scopes. Candidate reads need candidates:read, score lookups need scores:read, webhook registration needs webhooks:write, and private agent reports need agent-decisions:write.
Manage API keysUse fictional candidate and score payloads before touching live metered endpoints. The sandbox is not billed and mirrors the public response envelopes.
Open sandboxSend your API key as a bearer token. Include Humanproof-Version when you want explicit version pinning.
Open OpenAPIRegister an HTTPS endpoint, store the one-time signing secret, send a test event, then monitor recent delivery attempts.
Manage webhooksPOST private decision reports with an idempotency key, then review the account-level audit trail in the dashboard.
View reportsThe OpenAPI document is the source of truth for route schemas. This table is the operator view.
/api/v1/candidates/searchcandidates:read or x402Search public candidate previews by skill, display name, title, or handle.
/api/v1/candidates/{username}candidates:read or x402Read one public candidate profile. Private evidence and worker ids are never returned.
/api/v1/scores/{scoreId}scores:read or x402Read one active public score envelope for an onboarded public profile.
/api/v1/score-vc/verifypublic, optional scores:readVerify a presented Score VC with issuer pinning, Ed25519 signature checks, and revocation lookup.
/api/v1/agent-decisionsagent-decisions:writeReport a private decision or outcome after an agent uses candidate or score data.
/api/v1/webhooks/endpointswebhooks:writeCreate an HTTPS webhook endpoint and receive the one-time signing secret.
/api/v1/webhooks/endpoints/{endpointId}webhooks:writeDisable a webhook endpoint. Disabled endpoints stop receiving future deliveries.
Copy these shapes into your client, then swap in your saved API key and endpoint URL.
Bearer auth works across paid v1 reads. Version pinning is optional, but recommended for production clients.
curl "https://humanproof.io/api/v1/candidates/search?q=react&limit=5" \ -H "Authorization: Bearer hp_live_..." \ -H "Humanproof-Version: 2026-05-14"
Use an idempotency key when creating endpoints. Store the returned signing secret immediately.
curl "https://humanproof.io/api/v1/webhooks/endpoints" \
-X POST \
-H "Authorization: Bearer hp_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: endpoint-prod-001" \
-d '{
"url": "https://api.example.com/humanproof/webhooks",
"description": "Production events",
"events": ["score.updated", "score.revised"]
}'Use this after an agent shortlists, rejects, contacts, or otherwise acts on Humanproof data.
curl "https://humanproof.io/api/v1/agent-decisions" \
-X POST \
-H "Authorization: Bearer hp_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: decision-req-frontend-123" \
-d '{
"subject": { "kind": "candidate", "username": "maya-chen" },
"decision": "shortlisted",
"outcome": "pending",
"agentName": "Talent routing agent",
"jobRef": "req-frontend-123",
"reasonCodes": ["react_match", "verified_score"]
}'Every event has a stable id, type, creation timestamp, and event-specific data.
{
"schemaVersion": "humanproof.webhook_event.v1",
"id": "evt_score_test_00001",
"type": "score.updated",
"createdAt": "2026-06-01T00:00:00.000Z",
"data": {
"workerId": "00000000-0000-4000-8000-00000000f001",
"snapshotId": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"score": 742,
"confidenceLow": 710,
"confidenceHigh": 774,
"evidenceCount": 12,
"sourceCount": 4,
"scoreVcSha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"scoreVcStatusToken": "status_test_0001",
"issuedAt": "2026-06-01T00:00:00.000Z"
}
}Compute HMAC SHA-256 over timestamp.rawBody and compare it with the v1 signature.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyHumanproofWebhook(rawBody, signatureHeader, secret) {
if (typeof rawBody !== 'string' || typeof signatureHeader !== 'string') return false;
if (signatureHeader.trim() === '' || typeof secret !== 'string' || secret === '') return false;
const parts = Object.fromEntries(
signatureHeader.split(',').map((part) => {
const [key, value] = part.split('=');
return [key, value];
}),
);
const timestamp = parts.t;
const received = parts.v1;
if (!timestamp || !received) return false;
const timestampSeconds = Number(timestamp);
if (!Number.isFinite(timestampSeconds)) return false;
if (!/^[0-9a-f]+$/i.test(received)) return false;
if (Math.abs(Date.now() / 1000 - timestampSeconds) > 300) return false;
const expected = createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
const expectedBytes = Buffer.from(expected, 'hex');
const receivedBytes = Buffer.from(received, 'hex');
return expectedBytes.length === receivedBytes.length
&& timingSafeEqual(expectedBytes, receivedBytes);
}Humanproof signs every delivery. Your endpoint should verify the signature before processing event data.
score.updatedA worker score has a new issued value.
score.revisedA previously issued score was corrected or replaced.
evidence.revokedA source record was removed from the active evidence set.
dispute.openedA worker opened a review or score dispute.
dispute.resolvedA dispute reached a terminal decision.
candidate.consent_changedA candidate sharing permission changed.
Humanproof-Webhook-IdStable event id. Use it for idempotent processing.
Humanproof-Webhook-EventEvent type, for example score.updated.
Humanproof-Webhook-DeliveryUnique delivery attempt row id.
Humanproof-Webhook-TimestampUnix timestamp used in the signed payload.
Humanproof-Webhook-SignatureHMAC header in the form t=<timestamp>,v1=<hex digest>.