What is HIP?FeaturesIntegrityPricingAPIAccountGet Started
⚙ Developer API

Build on HIP

Integrate human-verified provenance into your platform. Verify attestations, check content authenticity, and connect your tools to the HIP registry with a simple REST API.

Base URL https://hipprotocol.org

Overview

The HIP API provides programmatic access to the Human Integrity Protocol's proof registry. Content that has been attested through HIP can be verified by anyone — no account or API key required for read-only verification.

Privacy by design: HIP never stores file contents or file names. The API works exclusively with SHA-256 content hashes — cryptographic fingerprints computed locally on the creator's device. Your files never leave your hands.

How it works

When a creator attests content through HIPKit, the app computes a SHA-256 hash of the file locally, then registers that hash with the HIP registry along with a classification, timestamp, and cryptographic signature. The verify endpoint lets anyone check whether a given content hash has been attested.

Source documentation: This page is a rendered reference. The canonical Markdown source — covering authentication, endpoints, error codes, rate limits, and credits — lives at github.com/tadortot/hipkit-docs. HIP imposes no requirement that products document themselves this way; the docs repo demonstrates the DP-5 pattern in practice.

Authentication

The POST /api/attest endpoint requires API key authentication via the X-API-Key header. API keys are bound to a HIP credential and inherit its tier-based rate limits.

Generating & managing keys: Open the Keys tab in the HIPKit app to create, list, and revoke your API keys. The full key is shown once at creation — copy it into a password manager or secret store and never commit it to version control or client-side code. If lost, revoke the key and create a new one.
Example Header
curl -X POST https://hipprotocol.org/api/attest \ -H "Content-Type: application/json" \ -H "X-API-Key: your_api_key_here" \ -d '{ ... }'

Programmatic key management (AppAuth)

The Keys tab in the app is the easiest way to manage keys. SDK authors who want to integrate the same management endpoints directly can call them via AppAuth — credential-holder authentication using an Ed25519 signature over a fixed canonical string.

AppAuth canonical: HIPKIT|{endpoint_path}|{credential_id}|{timestamp_iso8601}
Sign the UTF-8 bytes of that string with the credential's Ed25519 private key. POST a JSON body containing credential_id, public_key (64-char hex), timestamp (ISO-8601 second precision, e.g. 2026-04-22T21:30:15Z), signature (base64), plus any per-endpoint extras. Timestamp must be within ±5 minutes of server time. The server verifies the signature and that SHA-256(public_key) === credential_id.
Endpoints
MethodPathExtrasReturns
POST /api/keys/create label? (string ≤60) { api_key, key_id, label, created_at }api_key shown once
POST /api/keys/list { keys: [{ key_id, label, created_at, last_used, active }] } (newest first; api_key never returned)
POST /api/keys/deactivate key_id (8-char hex) { key_id, deactivated_at } or { already_deactivated: true } (idempotent)

Limits: 10 key creations per credential per 24 hours; hard cap 100 keys per credential. Errors: rate_limited (429), key_limit_reached (409), key_not_found (404), ambiguous_key_id (409), key_not_owned_by_credential (403), plus shared AppAuth errors (signature_invalid, key_binding_failed, superseded, etc.).

Platform admin endpoint (escape hatch — not for integration): POST /api/admin/keys with Authorization: Bearer <ADMIN_KEY> exists for platform support and bootstrap edge cases (for example, minting an initial key when no client capable of signing AppAuth is yet available). It is not a customer-facing endpoint, has no UI, and is not intended for SDK or application integration. Use the Keys tab in-app, or the AppAuth endpoints above, for all normal usage.

Verify Attestation

Check whether a piece of content has been attested through HIP. Provide the SHA-256 hash of the file and get back a verification result with attestation details.

GET /api/verify/{content_hash} Live

Returns whether the content hash has been attested and, if so, the attestation record including classification, credential tier, timestamp, and proof link.

Parameters
ParameterTypeDescription
content_hash string 64-character lowercase hexadecimal SHA-256 hash of the file content Required
Success Response — Attested Content
{ "verified": true, "record": { "content_hash": "a7c3e19f...82b", "classification": "CompleteHumanOrigin", "credential_tier": 1, "attested_at": "2026-04-01T12:00:00Z", "registered_at": "2026-04-01T12:00:01Z", "short_id": "xK7mQ2pL", "proof_url": "https://hipprotocol.org/proof.html?hash=a7c3e19f...82b", "short_url": "https://hipprotocol.org/p/xK7mQ2pL", "sealed": false } }
Response — Not Attested
{ "verified": false, "content_hash": "e52d80c4...9c17" }
Response — Sealed Record
// The content has been attested, but the creator has sealed the proof details { "verified": true, "record": { "content_hash": "3f91b2...d04a", "sealed": true, "registered_at": "2026-03-15T09:30:00Z" }, "message": "This content has been attested but the proof details are sealed by its creator." }

Response Fields

FieldTypeDescription
verifiedbooleanWhether the content hash has a registered attestation
record.content_hashstringThe SHA-256 hash that was queried
record.classificationstringHIP classification: CompleteHumanOrigin, HumanOriginAssisted, or HumanDirectedCollaborative
record.credential_tierintegerCredential tier of the attester (1, 2, or 3)
record.attested_atstringISO 8601 UTC timestamp of when the creator attested the content
record.registered_atstringISO 8601 UTC timestamp of when the proof was registered in the HIP registry
record.short_idstring8-character short ID for the proof link
record.proof_urlstringFull URL to the proof card on hipprotocol.org
record.short_urlstringShort URL for sharing (hipprotocol.org/p/{short_id})
record.sealedbooleanWhether the proof details have been sealed by the creator

Classifications

ValueMeaning
CompleteHumanOriginEntirely created by a human with no AI assistance
HumanOriginAssistedHuman-created with AI-assisted editing or enhancement
HumanDirectedCollaborativeHuman-directed work with significant AI collaboration

Error Responses

StatusConditionBody
400Invalid hash format{ "verified": false, "error": "Invalid content hash..." }
Note: A verified: false response uses HTTP 200, not 404. The request succeeded — the content simply has not been attested. Reserve error codes for actual errors (malformed hashes, server issues).

Submit Attestation

Register a new attestation through the API. Requires API key authentication. The content hash is computed locally — your files never leave your hands.

POST /api/attest Live

Submit a content hash with classification and cryptographic signature to register an attestation. Returns the registered proof record with permalink.

Headers
HeaderRequiredDescription
X-API-KeyRequiredYour API key
Content-TypeRequiredapplication/json
Request Body
FieldTypeDescription
content_hashstring64-character lowercase hex SHA-256 hash. Required
classificationstringHIP classification value. Required
signaturestringEd25519 signature from your credential. Required
attested_atstringISO 8601 UTC timestamp. Optional, defaults to current time
sealedbooleanSeal proof details from public view. Optional, defaults to false
public_keystring64-char hex Ed25519 public key. Optional
Success Response
{ "success": true, "content_hash": "a7c3e19f...82b", "classification": "CompleteHumanOrigin", "credential_tier": 1, "attested_at": "2026-04-13T12:00:00Z", "registered_at": "2026-04-13T12:00:01Z", "proof_url": "https://hipprotocol.org/proof.html?hash=a7c3e19f...82b", "short_id": "xK7mQ2pL", "short_url": "https://hipprotocol.org/p/xK7mQ2pL", "sealed": false }
Error Responses
StatusConditionBody (summarized)
400Missing/invalid fields{ "error": "..." }
401Missing X-API-Key{ "error": "Missing X-API-Key header..." }
403Unrecognized API key (no matching record){ "error": "Invalid API key" }
403API key deactivated (user-revoked, or cascade-revoked when its credential was retired){ "error": "API key has been deactivated" }
409Hash already attested{ "error": "conflict", "message": "...", "existing_record": {...} }
429Rate limit exceeded{ "error": "Rate limit exceeded...", "limit": N, "current": N }
Code Examples
curl -X POST https://hipprotocol.org/api/attest \ -H "Content-Type: application/json" \ -H "X-API-Key: your_api_key" \ -d '{ "content_hash": "a7c3e19f...", "classification": "CompleteHumanOrigin", "signature": "ed25519_sig...", "sealed": false '
async function submitAttestation(hash, classification, signature) { const res = await fetch( "https://hipprotocol.org/api/attest", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.HIP_API_KEY, }, body: JSON.stringify({ content_hash: hash, classification: classification, signature: signature, sealed: false, }), } ); const data = await res.json(); if (data.success) { console.log("Attestation registered:", data.short_url); } }
import requests, os, hashlib def submit_attestation(content_hash, classification, signature): api_key = os.getenv("HIP_API_KEY") payload = { "content_hash": content_hash, "classification": classification, "signature": signature, "sealed": False } resp = requests.post( "https://hipprotocol.org/api/attest", json=payload, headers={ "X-API-Key": api_key, "Content-Type": "application/json" } ) data = resp.json() if data.get("success"): print(f"Proof: {data['short_url']}") else: print(f"Error: {data['error']}")
Rate limits: Rate limits are shared between app and API attestations. A Tier 1 credential can submit up to 50 attestations per 24-hour window across all channels.

Series Writes

HIP series are open, append-only streams of attestations bound to a single credential (SERIES-SPEC-v1). Series endpoints live on the HIP protocol surface at hipprotocol.org, not under hipkit.net/api, because series are a protocol primitive — anyone can write to them with a valid credential + Ed25519 signature, no API key required.

HIPKit's own client (the Series tab in app.html) writes to these same endpoints. The only HIPKit-specific detail on the wire is the hipkit_originated flag described below.

Endpoints (summary)

MethodPathPurpose
POST/register-seriesCreate a new series (signed manifest)
POST/register-series-memberAdd a member (signed event over an existing proof hash)
POST/close-seriesClose a series (signed event; no more members accepted)
GET/api/series/{id}Read series record + signature
GET/api/series/{id}/eventsRead all add/close events (500 cap)
GET/api/creator/{id}/seriesList a creator's series (500 cap)
GET/s/{id}302 redirect to the public series page

Full reference — request/response shapes, canonicals, error codes — lives in the hipkit-docs endpoints.md Series section.

The hipkit_originated flag

HIPKit-originated writes stamp hipkit_originated: true as a top-level body field on POST /register-series and POST /register-series-membernot inside the signed manifest or event payload. The flag is a record-shape hint used for surface-side filtering (portfolio views, HIPKit-specific analytics) and has no effect on signature verification or the write's authorization.

// Example body for POST /register-series-member { "event": { /* signed payload — see hipkit-docs */ }, "signature": "BASE64_ED25519", "hipkit_originated": true }
ValueHandlingRecord shape
trueAccepted; stamped on the stored recordIncludes hipkit_originated: true
false or absentAccepted; treated as "not HIPKit-originated"Field is absent — not false
any other typeRejected400 {"error":"invalid_field","field":"hipkit_originated"}
Posture parallel. The flag lives outside the signed payload for the same reason as original_hash (S102), attested_copy_hash (S103), and file_name (S88) on /register-proof — it's a surface-provenance hint, not a claim the credential holder signs. Changing the flag after the fact would not invalidate any signature.
Credits. Series creation and member-add each consume 1 HIPKit credit when made from hipkit.net with a Tier 1 credential, metered via /api/credits/consume (AppAuth-gated, independent of /register-series*). Close is free. Tier 2 and Tier 3 credentials use server-tracked trial credits. See SERIES-SPEC-v1 §5.3.

Integration Examples

Quick examples in common languages. All examples compute the SHA-256 hash of a local file and check it against the HIP registry.

# Compute SHA-256 hash of a file HASH=$(shasum -a 256 photo.jpg | awk '{print $1}') # Verify against HIP registry curl "https://hipprotocol.org/api/verify/$HASH"
async function verifyWithHIP(file) { // Compute SHA-256 hash const buffer = await file.arrayBuffer(); const hashBuf = await crypto.subtle.digest("SHA-256", buffer); const hash = Array.from(new Uint8Array(hashBuf)) .map(b => b.toString(16).padStart(2, "0")).join(""); // Verify against HIP registry const res = await fetch( `https://hipprotocol.org/api/verify/${hash}` ); const data = await res.json(); if (data.verified) { console.log("Attested:", data.record.classification); console.log("Proof:", data.record.proof_url); } else { console.log("Not attested through HIP"); } }
import hashlib, requests def verify_with_hip(file_path): # Compute SHA-256 hash sha256 = hashlib.sha256() with open(file_path, "rb") as f: for chunk in iter(lambda: f.read(8192), b""): sha256.update(chunk) content_hash = sha256.hexdigest() # Verify against HIP registry resp = requests.get( f"https://hipprotocol.org/api/verify/{content_hash}" ) data = resp.json() if data["verified"]: record = data["record"] print(f"Attested: {record['classification']}") print(f"Proof: {record['proof_url']}") else: print("Not attested through HIP") verify_with_hip("photo.jpg")

Rate Limits

The verification endpoint is designed for high availability. Standard rate limits apply to prevent abuse.

EndpointLimitWindow
GET /api/verify/{hash}1,000 requestsPer IP, per hour
POST /api/attestTier-basedPer credential, per 24h

Attestation Rate Limits by Tier

TierAttestations per 24h
Tier 150
Tier 225
Tier 310
Need higher limits? If you're building a high-volume integration, reach out and we'll work with you on appropriate rate limits for your use case.

API Roadmap

Verification and authenticated attestation endpoints are live. Portfolio query is in development.

GET /api/verify/{content_hash} Live

Public read-only verification. Check if any content hash has been attested through HIP.

POST /api/attest Live

Submit attestations programmatically via API key. Register content hashes with classification, timestamp, and cryptographic signature. Requires authenticated credential.

GET /api/portfolio/{credential_id} Coming Soon

Query all attestations for a given credential. Supports pagination and filtering by classification. Requires API key authentication.