---
title: "Agentic verification search"
method: GET
path: "/verify/search"
tags: ["AI Intelligence", "Verification"]
---

# Agentic verification search

`GET /verify/search`

## Request

- Base URL: `https://app.arkova.ai/api/v1`
- URL: `https://app.arkova.ai/api/v1/verify/search`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Search returning frozen verification schema results. Designed for AI agents, ATS systems, and background check integrations. Requires API key (not JWT). SCRUM-3906: this route now answers with EITHER a semantic (embedding + cosine-similarity) match OR a lexical (ILIKE substring) match — `search_mode` on the response says which. Semantic is used when ENABLE_SEMANTIC_SEARCH is on and the embed+match RPC succeeds; the route falls back to lexical, never a 503, when the flag is off or that RPC/embedding call fails. Only the semantic path costs an AI credit or emits `similarity`; `issuer_name`, `issued_date`, `expiry_date` and `anchor_timestamp` are omitted (never null) on a lexical result — that path does not query them. Semantic results always include `anchor_timestamp`: the Network Observed Time, or null when no network observation is available; creation time is never substituted.

## Query parameters

- `q` string, required
- `threshold` number
- `limit` integer

## Response `200`

Verification results. `search_mode` (`semantic_vector` | `lexical_substring`) tells the caller which path answered — see the operation description.

- object
  - `query` string
  - `results` VerificationResult[]
    - `verified` boolean, required
    - `status` 'ACTIVE' | 'REVOKED' | 'SUPERSEDED' | 'EXPIRED' | 'PENDING' | 'SUBMITTED'
    - `issuer_name` string
    - `recipient_identifier` string: Hashed identifier, never raw PII
    - `credential_type` string
    - `issued_date` string, date-time, nullable
    - `expiry_date` string, date-time, nullable
    - `anchor_timestamp` string, date-time, nullable: Network Observed Time: the moment the Bitcoin network observed this anchor. Measured from the confirmed block, NOT the time the record was created in Arkova (the two differ by the confirmation interval). Semantic search retains this key with null when no observation exists; exact-id verification omits it in that case. Not asserted: anything about the content, authenticity, or legal effect of the underlying document.
    - `bitcoin_block` integer, nullable
    - `network_receipt_id` string, nullable
    - `merkle_proof_hash` string, nullable
    - `record_uri` string, uri
    - `jurisdiction` string: Omitted when null, never returned as null
    - `description` string: Immutable credential description, omitted when not present
    - `proof_availability` 'per_document' | 'root_only': SCRUM-2575. Whether a per-document proof can actually be retrieved for this record. `per_document` = a per-document inclusion branch is stored and GET /verify/{publicId}/proof returns it. `root_only` = no per-document branch is stored; the fingerprint is committed on-chain via the referenced anchor receipt, but no self-contained offline proof bundle is available. Measured from stored proof data — never derived from status. Omitted (never null) for records that have not reached a settled on-chain state (PENDING / SUBMITTED). Additive field (Constitution 1.8); no API version change.
    - `proof_availability_note` string: SCRUM-2575. Omitted when not applicable, never returned as null. Present exactly when proof_availability is. States what is measured, what is asserted, and what is NOT asserted for that class (Constitution 1.5) — in particular, for root_only records, that no self-contained per-document offline proof is available, and that its absence is not evidence the record is invalid.
    - `source` object: SCRUM-4507. Which connected document source this record originated from. OMITTED (never null, never an empty object) when the record carries no recognised connector marker — absence means "not stated", NOT "uploaded by a person". Carries the provider label and NOTHING ELSE: no file, folder, shared-drive or revision identifier and no deep link into the source system. This endpoint answers anonymously, so a source identifier here would let any holder of a public record id probe the source system for that object; those identifiers are shown only to the record owner on the authenticated record page. Not asserted: that the document still exists in the source system, is unchanged there, or is reachable by the caller — see fingerprint_rederivability for what the fingerprint does and does not commit. Additive field (Constitution 1.8); no API version change.
      - `provider` 'connector' | 'docusign' | 'google_drive' | 'microsoft_365': The connected system this record's document was retrieved from.
    - `compliance_controls` string[], nullable: API-RICH-01 regulatory control IDs mapped to this anchor. Informational metadata only — see compliance_controls_note, which is always present alongside this field and states what these identifiers do NOT assert. OMITTED for records that are not a current anchored credential (REVOKED / EXPIRED / SUPERSEDED / not yet anchored): these identifiers describe a live compliance posture, so listing them for such a record would assert something Arkova does not hold (BUG-2026-06-24-007). Absence is not a statement that the record was never anchored — the anchor receipt fields are unaffected.
    - `compliance_controls_note` string: SCRUM-2227. Omitted when not applicable, never returned as null. Present whenever compliance_controls is present, absent otherwise. States that control identifiers are a credential-type mapping and NOT an audit, certification, conformity assessment, or attestation — in particular that no identifier asserts qualified status under eIDAS. Additive nullable field (Constitution 1.8); no API version change.
    - `chain_confirmations` integer, nullable: API-RICH-01 Bitcoin block confirmations at anchor time.
    - `parent_public_id` string, nullable: API-RICH-01 public ID of the parent anchor; internal UUIDs are never exposed.
    - `version_number` integer, nullable: API-RICH-01 version in this anchor lineage; omitted when equal to 1.
    - `revocation_tx_id` string, nullable: API-RICH-01 Bitcoin transaction ID of the revocation when status is REVOKED.
    - `revocation_block_height` integer, nullable: API-RICH-01 Bitcoin block height at which revocation was anchored.
    - `file_mime` string, nullable: API-RICH-01 source document MIME type.
    - `file_size` integer, nullable: API-RICH-01 source document size in bytes.
    - `confidence_scores` object, nullable: API-RICH-02 per-field confidence scores from the latest extraction manifest.
    - `sub_type` string, nullable: API-RICH-02 fine-grained credential subtype from anchors.sub_type.
    - `error` string
  - `count` integer
  - `threshold` number: Echoes the request threshold; not applied on the lexical path.
  - `search_mode` 'semantic_vector' | 'lexical_substring'

## Other responses

- `400`: Invalid request
- `401`: Authentication required
- `402`: No AI credits remaining for the semantic path (flag on, RPC not yet attempted). Retry to get a lexical result instead is NOT automatic on this status — insufficient credits is a distinct condition from a semantic RPC failure.
- `429`: Rate limit exceeded
- `503`: ENABLE_VERIFICATION_API is off (worker-wide gate, applies to all of /api/v1/*). No longer returned for ENABLE_SEMANTIC_SEARCH off — see the operation description.

---

[API](https://skmtc.dev/arkova/apis/arkova-verification-api.md) · [All operations](https://skmtc.dev/arkova/apis/arkova-verification-api/llms.txt) · [OpenAPI document](https://skmtc.dev/arkova/apis/arkova-verification-api/revisions/a14858d1efd4?raw)
