Skip to main content

Trust API — REST Reference

For applications that do not speak XRPC natively, Verak provides two read-only REST endpoints: a trust summary by handle or DID, and a label definitions catalogue. Both endpoints are CDN-cached, CORS-unrestricted, and require no API key.
These endpoints are a convenience layer over the AT Protocol labeler. If your stack can make XRPC calls, the native labeler path is the preferred integration — it removes Verak infrastructure as a dependency entirely.

Base URL

https://verak.app/api/v1/
All endpoints under /api/v1/ are versioned. Breaking changes (removed fields, changed semantics) will be released under /api/v2/. Additive changes (new optional fields) are non-breaking and may appear at any time.

Trust Summary Endpoint

GET /api/v1/trust/{subject}

Returns the trust state for a single subject. The subject can be an AT Protocol handle or a did:plc DID. Cache: s-maxage=300 (5 minutes at the CDN edge)
CORS: Access-Control-Allow-Origin: *
Authentication: None

Request examples

By handle
curl "https://verak.app/api/v1/trust/jasonbu.online"
By DID
curl "https://verak.app/api/v1/trust/did:plc:abc123exampleDID"
Both forms return an identical response shape. Handle-based queries resolve the DID via the PLC directory before querying the labeler; the resolved DID is always present in the response.

Response — 200 OK (verified member)

{
  "subject": {
    "did": "did:plc:abc123exampleDID",
    "handle": "jasonbu.online"
  },
  "verified": true,
  "tier": "pro",
  "labels": ["verak-verified", "verak-pro"],
  "credentialsIssued": 1,
  "resolvedAt": "2026-06-10T12:00:00.000Z"
}

Response — 200 OK (resolvable non-member)

A subject whose DID resolves via the PLC directory but who has no Verak labels returns 200 with verified: false. This is intentional — an unresolvable subject is a different failure mode from a resolved subject with no trust signals.
{
  "subject": {
    "did": "did:plc:xyz789exampleDID",
    "handle": "someone.bsky.social"
  },
  "verified": false,
  "tier": null,
  "labels": [],
  "credentialsIssued": 0,
  "resolvedAt": "2026-06-10T12:00:00.000Z"
}

Response — 404 Not Found

Returned when the subject cannot be resolved to a DID — either because the handle does not exist, the DID is malformed, or the PLC directory returned no result.
{
  "error": "subject_not_found",
  "message": "Could not resolve a DID for the given subject."
}

Field reference

FieldTypeDescription
subject.didstringResolved did:plc for the subject
subject.handlestringAT Protocol handle, resolved from the PDS at query time
verifiedbooleantrue if the subject carries an active verak-verified label
tierstring | null"pro" (Sovereign Pro), "free" (registered member, no Pro label), or null (not a Verak member)
labelsarray[string]Active label values from the Verak Labeler. Empty array if none.
credentialsIssuedintegerCount of public is.verak.passport.credential records on the member’s PDS. 0 if none or not a member.
resolvedAtstring (ISO 8601)Timestamp of when this response was computed. May reflect CDN cache age.

Definitions Endpoint

GET /api/v1/labels/definitions

Returns the catalogue of labels issued by the Verak Labeler with display metadata. Useful for building local label renderers without hardcoding label semantics. Cache: s-maxage=3600 (1 hour at the CDN edge)
CORS: Access-Control-Allow-Origin: *
Authentication: None

Request

curl "https://verak.app/api/v1/labels/definitions"

Response — 200 OK

{
  "labeler": "did:plc:upeagalqts3yutsgc6vo5tn3",
  "endpoint": "https://labeler.verak.app",
  "labels": [
    {
      "value": "verak-verified",
      "name": "Verified",
      "description": "Identity verified through human-reviewed evidence signals.",
      "earnedBy": "Manual review by Verak editors after the applicant submits verification evidence. Automated signals are inputs to the review, not a sufficient condition for issuance.",
      "revokedBy": "Manual revocation by Verak editors, or automatic downgrade on underlying credential expiry (Phase 2 roadmap)."
    },
    {
      "value": "verak-pro",
      "name": "Sovereign Pro",
      "description": "Active Sovereign Pro subscriber.",
      "earnedBy": "Issued automatically on subscription activation.",
      "revokedBy": "Negated automatically when the subscription lapses."
    },
    {
      "value": "verak-gander",
      "name": "Gander",
      "description": "Verified Gander network participant.",
      "earnedBy": "Gander ecosystem onboarding flow.",
      "revokedBy": "Manual removal or network exit."
    },
    {
      "value": "verak-eurosky",
      "name": "EuroSky",
      "description": "Verified EuroSky network participant.",
      "earnedBy": "EuroSky ecosystem onboarding flow.",
      "revokedBy": "Manual removal or network exit."
    },
    {
      "value": "verak-recruiter",
      "name": "Recruiter",
      "description": "Verified recruiter or hiring organisation.",
      "earnedBy": "Manual review by Verak editors.",
      "revokedBy": "Manual revocation."
    }
  ]
}

Field reference

FieldTypeDescription
labelerstringDID of the Verak Labeler
endpointstringLabeler XRPC endpoint
labels[].valuestringThe label value as it appears in AT Protocol label records
labels[].namestringHuman-readable display name
labels[].descriptionstringOne-sentence summary of what the label means
labels[].earnedBystringHow the label is issued
labels[].revokedBystringHow the label is revoked or negated
This endpoint returns only the allowlisted fields above. Internal metadata (review state, reviewer identity, applied signal weights) is never included.

CORS

Both endpoints are served with:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
CORS preflight (OPTIONS) requests succeed from any origin. Browser-based applications can call these endpoints directly without a proxy.

Data Boundary

To be explicit about what these endpoints will never return:
DataWhy it is excluded
Raw credibility score or dimension valuesScores are internal evidence signals used to inform human review, not a published claim. Publishing a score would create a gameable surface and misrepresent the human-reviewed nature of verification.
Blob references or media CIDsMedia assets live on the member’s PDS under their control. Verak has no right to redistribute references.
SIFA record contents (id.sifa.*)Career, education, and endorsement data belongs to the member and is readable directly from their PDS. Centralising it here would contradict the sovereignty architecture.
Email, phone, or contact informationVerak never collects or stores contact data in a form that could be returned here.
Reviewer identity or review notesInternal to Verak’s editorial process.
If a field you need is not in the response, it is not available via this API by design.

Fair Use

These endpoints are CDN-cached. There are no API keys, no rate-limit tiers, and no authentication. Cache behaviour means repeated identical requests within the cache window return the cached response at no additional cost to the origin. If you need bulk lookups, real-time streaming, or firehose-scale data, the right path is the AT Protocol labeler stream (com.atproto.label.subscribeLabels), not repeated calls to this API. See the labeler page →

Status Codes

CodeMeaning
200Request succeeded. verified may be true or false.
404Subject could not be resolved to a DID. Check the error field for details.
429Rate limit exceeded at the CDN edge. Back off and retry.
500Upstream error (labeler or PLC directory unavailable). Treat as a transient failure.
5xx errors are transient. Retry with exponential backoff. Do not surface 5xx as a negative trust signal — inability to query is not the same as verified: false.