Arkova Python SDK
Typed Python client for the Arkova Verification APIs.
Install
pip install arkova
Python 3.10 or newer is supported.
Supported methods
anchor(data=None, *, fingerprint=None)anchor_bulk(inputs, *, dry_run=None, duplicate_strategy=None, batch_id=None)fingerprint(data)search(q, type="all", cursor=None, limit=50)verify(public_id)verify_fingerprint(fingerprint)get_anchor(public_id)list_orgs()
Quick start
import os
from arkova import Arkova
with Arkova(api_key=os.environ["ARKOVA_API_KEY"]) as arkova:
results = arkova.search("registered nurse", type="record", limit=5)
for item in results.results:
print(item.public_id, item.snippet)
Anchor a document (HAKI-REQ-02)
anchor() fingerprints data client-side (SHA-256, in-process — the raw
content is never sent, only the 64-char hex fingerprint) and submits it for
network anchoring. Pass a pre-computed fingerprint instead if you already
hashed the document elsewhere.
from arkova import Arkova
with Arkova(api_key="ak_live_...") as arkova:
# Raw content — fingerprinted in-process before anything is sent.
receipt = arkova.anchor("document content goes here")
print(receipt.public_id, receipt.status) # "PENDING" -> "SUBMITTED" -> "SECURED"
# Or: you already have the fingerprint.
receipt = arkova.anchor(fingerprint="a" * 64)
The same fingerprint always returns the same public_id — anchoring
identical content twice is a no-op.
Bulk-anchor documents (HAKI-REQ-02)
anchor_bulk() anchors up to BULK_ANCHOR_MAX_ROWS (1000) documents in one
call. Each BulkAnchorInput row provides exactly one of fingerprint (a
pre-computed 64-char hex SHA-256) or data (raw content, fingerprinted
client-side the same way anchor() does it) — you can mix both forms across
rows in one call.
from arkova import Arkova, BulkAnchorInput
with Arkova(api_key="ak_live_...") as arkova:
with open("contract.pdf", "rb") as f:
contract_bytes = f.read()
result = arkova.anchor_bulk(
[
# Already hashed elsewhere — send the fingerprint directly.
BulkAnchorInput(fingerprint="a" * 64, external_id="invoice-001"),
# Raw content — the SDK hashes it for you before it's ever sent.
BulkAnchorInput(
data=contract_bytes,
credential_type="CONTRACT_PRESIGNING",
document_type="contract",
matter_or_case_ref="CASE-42",
),
],
duplicate_strategy="skip",
batch_id="nightly-2026-07-28",
)
print(result.queued, result.duplicates, result.errors)
for anchor in result.anchors or []:
print(anchor.public_id, anchor.status)
Options: dry_run=True validates every row (including dedup checks)
without queuing or deducting credits — result.anchors is None on a dry
run. duplicate_strategy controls what happens when a fingerprint already
exists in-batch or in your org; the server default is "fail" (raises
ArkovaError(code="duplicate_fingerprints") on any duplicate — pass
"skip", "supersede", or "link" to proceed instead). batch_id is your
own correlation ID, echoed back and surfaced in audit events.
Limits: empty input returns a zero-row response immediately, no network
call. More than 1000 rows raises ArkovaError(code="batch_too_large") — the
SDK does not auto-chunk (splitting a logical batch across requests would
let a duplicate fingerprint slip past the cheaper intra-batch check and
would deduct credits per chunk instead of atomically for the whole batch;
split manually and correlate with a shared batch_id if you need more than
1000 rows). A row with neither fingerprint nor data (or with both)
raises ArkovaError(code="invalid_request"), checked before any network
call.
Verify a fingerprint
from arkova import Arkova
fingerprint = "a" * 64
with Arkova(api_key="ak_live_...") as arkova:
result = arkova.verify_fingerprint(fingerprint)
print(result.verified, result.public_id)
Verify a public ID
from arkova import Arkova
with Arkova(api_key="ak_live_...") as arkova:
result = arkova.verify("ARK-2026-ABC")
print(result.verified, result.description, result.confidence_scores)
verify() returns the rich v1 verification shape, including API-RICH-01 fields
such as compliance_controls, chain_confirmations, parent_public_id,
version_number, file_mime, and file_size, plus API-RICH-02 fields
confidence_scores and sub_type when the API response includes them.
The same optional rich fields are typed on v2 verify_fingerprint() and
get_anchor() responses, so newer API payloads are not silently hidden by the
SDK model layer.
Async client
import asyncio
from arkova import AsyncArkova
async def main() -> None:
async with AsyncArkova(api_key="ak_live_...") as arkova:
orgs = await arkova.list_orgs()
print([org.display_name for org in orgs.organizations])
asyncio.run(main())
Errors and retries
ArkovaError preserves the API v2 RFC 7807 problem document and the Retry-After
header when present. code carries the machine-readable error code — from the
plain-JSON error field on v1 write-path errors (anchor() / anchor_bulk()
codes include "insufficient_credits", "duplicate_fingerprints",
"batch_too_large", "invalid_request"), or the RFC 7807 type slug on v2
problem documents.
from arkova import Arkova, ArkovaError
try:
with Arkova(api_key="ak_live_...") as arkova:
arkova.get_anchor("ARK-DOC-MISSING")
except ArkovaError as exc:
print(exc.status_code, exc.code, exc.problem.type if exc.problem else None)
The client retries 429 and 5xx responses by default and respects Retry-After.
Pass retries=0 to disable retries.
Offline proof verification (no network, no API key)
verify_bundle verifies an exported Arkova proof package entirely offline —
an independent re-derivation of the documented bundle format (Merkle
recompute with the CVE-2012-2459 structural guard, fixed-offset on-chain
payload decode, 80-byte header rules, timestamp honesty, Ed25519 signed
bundles). It makes zero network calls and never contacts Arkova; on-chain
confirmation runs only against canned or caller-supplied independent-node
responses.
import json
from arkova import verify_bundle
packet = json.load(open("proof.json"))
outcome = verify_bundle(packet) # recompute-only
print(outcome.verdict, outcome.reason_code) # "VERIFIED" / None, or a frozen code
Every NOT-VERIFIED outcome carries one frozen machine reason code
(arkova.REASON_CODES), kept in lockstep with the TypeScript reference
verifier via a cross-runtime parity gate in the Arkova repo. A passing
signature never substitutes for the cryptographic recompute; a failing
explicitly-requested signature check fails the verdict closed.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arkova-2.2.0.tar.gz.
File metadata
- Download URL: arkova-2.2.0.tar.gz
- Upload date:
- Size: 39.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0394375289c520e70666b14349c04132b61e3d69f106332b9c91d7680a450639
|
|
| MD5 |
e830e68e9da260a9cee99c0b0148d9a7
|
|
| BLAKE2b-256 |
44b1d973ececaa33799d6fbb83868406b163cf787f6d7d12cfa10048bcc0b11e
|
Provenance
The following attestation bundles were made for arkova-2.2.0.tar.gz:
Publisher:
publish-python-sdk.yml on carson-see/ArkovaCarson
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arkova-2.2.0.tar.gz -
Subject digest:
0394375289c520e70666b14349c04132b61e3d69f106332b9c91d7680a450639 - Sigstore transparency entry: 2312791831
- Sigstore integration time:
-
Permalink:
carson-see/ArkovaCarson@8818d3af3b7568ee65a525b95f6f969763d15d25 -
Branch / Tag:
refs/tags/arkova-py-v2.2.0 - Owner: https://github.com/carson-see
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python-sdk.yml@8818d3af3b7568ee65a525b95f6f969763d15d25 -
Trigger Event:
push
-
Statement type:
File details
Details for the file arkova-2.2.0-py3-none-any.whl.
File metadata
- Download URL: arkova-2.2.0-py3-none-any.whl
- Upload date:
- Size: 28.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d8825d0870ee32836f0e141b4bd18178ceaa376728b157a19d338592c4c4a44
|
|
| MD5 |
3344dc07f4a97f718d0de74488d0ef5b
|
|
| BLAKE2b-256 |
7cc57e997e0e609627fd2c24af2d319056c44d9d766cc4b508dcf17f01cfb20a
|
Provenance
The following attestation bundles were made for arkova-2.2.0-py3-none-any.whl:
Publisher:
publish-python-sdk.yml on carson-see/ArkovaCarson
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arkova-2.2.0-py3-none-any.whl -
Subject digest:
9d8825d0870ee32836f0e141b4bd18178ceaa376728b157a19d338592c4c4a44 - Sigstore transparency entry: 2312791838
- Sigstore integration time:
-
Permalink:
carson-see/ArkovaCarson@8818d3af3b7568ee65a525b95f6f969763d15d25 -
Branch / Tag:
refs/tags/arkova-py-v2.2.0 - Owner: https://github.com/carson-see
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python-sdk.yml@8818d3af3b7568ee65a525b95f6f969763d15d25 -
Trigger Event:
push
-
Statement type: