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.
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.
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.
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.
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.
| Method | Path | Extras | Returns |
|---|---|---|---|
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.).
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.
Returns whether the content hash has been attested and, if so, the attestation record including classification, credential tier, timestamp, and proof link.
| Parameter | Type | Description |
|---|---|---|
content_hash |
string | 64-character lowercase hexadecimal SHA-256 hash of the file content Required |
Response Fields
| Field | Type | Description |
|---|---|---|
verified | boolean | Whether the content hash has a registered attestation |
record.content_hash | string | The SHA-256 hash that was queried |
record.classification | string | HIP classification: CompleteHumanOrigin, HumanOriginAssisted, or HumanDirectedCollaborative |
record.credential_tier | integer | Credential tier of the attester (1, 2, or 3) |
record.attested_at | string | ISO 8601 UTC timestamp of when the creator attested the content |
record.registered_at | string | ISO 8601 UTC timestamp of when the proof was registered in the HIP registry |
record.short_id | string | 8-character short ID for the proof link |
record.proof_url | string | Full URL to the proof card on hipprotocol.org |
record.short_url | string | Short URL for sharing (hipprotocol.org/p/{short_id}) |
record.sealed | boolean | Whether the proof details have been sealed by the creator |
Classifications
| Value | Meaning |
|---|---|
CompleteHumanOrigin | Entirely created by a human with no AI assistance |
HumanOriginAssisted | Human-created with AI-assisted editing or enhancement |
HumanDirectedCollaborative | Human-directed work with significant AI collaboration |
Error Responses
| Status | Condition | Body |
|---|---|---|
| 400 | Invalid hash format | { "verified": false, "error": "Invalid content hash..." } |
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.
Submit a content hash with classification and cryptographic signature to register an attestation. Returns the registered proof record with permalink.
| Header | Required | Description |
|---|---|---|
X-API-Key | Required | Your API key |
Content-Type | Required | application/json |
| Field | Type | Description |
|---|---|---|
content_hash | string | 64-character lowercase hex SHA-256 hash. Required |
classification | string | HIP classification value. Required |
signature | string | Ed25519 signature from your credential. Required |
attested_at | string | ISO 8601 UTC timestamp. Optional, defaults to current time |
sealed | boolean | Seal proof details from public view. Optional, defaults to false |
public_key | string | 64-char hex Ed25519 public key. Optional |
| Status | Condition | Body (summarized) |
|---|---|---|
| 400 | Missing/invalid fields | { "error": "..." } |
| 401 | Missing X-API-Key | { "error": "Missing X-API-Key header..." } |
| 403 | Unrecognized API key (no matching record) | { "error": "Invalid API key" } |
| 403 | API key deactivated (user-revoked, or cascade-revoked when its credential was retired) | { "error": "API key has been deactivated" } |
| 409 | Hash already attested | { "error": "conflict", "message": "...", "existing_record": {...} } |
| 429 | Rate limit exceeded | { "error": "Rate limit exceeded...", "limit": N, "current": N } |
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)
| Method | Path | Purpose |
|---|---|---|
| POST | /register-series | Create a new series (signed manifest) |
| POST | /register-series-member | Add a member (signed event over an existing proof hash) |
| POST | /close-series | Close a series (signed event; no more members accepted) |
| GET | /api/series/{id} | Read series record + signature |
| GET | /api/series/{id}/events | Read all add/close events (500 cap) |
| GET | /api/creator/{id}/series | List 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-member — not 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.
| Value | Handling | Record shape |
|---|---|---|
true | Accepted; stamped on the stored record | Includes hipkit_originated: true |
false or absent | Accepted; treated as "not HIPKit-originated" | Field is absent — not false |
| any other type | Rejected | 400 {"error":"invalid_field","field":"hipkit_originated"} |
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.
/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.
Rate Limits
The verification endpoint is designed for high availability. Standard rate limits apply to prevent abuse.
| Endpoint | Limit | Window |
|---|---|---|
GET /api/verify/{hash} | 1,000 requests | Per IP, per hour |
POST /api/attest | Tier-based | Per credential, per 24h |
Attestation Rate Limits by Tier
| Tier | Attestations per 24h |
|---|---|
| Tier 1 | 50 |
| Tier 2 | 25 |
| Tier 3 | 10 |
API Roadmap
Verification and authenticated attestation endpoints are live. Portfolio query is in development.
Public read-only verification. Check if any content hash has been attested through HIP.
Submit attestations programmatically via API key. Register content hashes with classification, timestamp, and cryptographic signature. Requires authenticated credential.
Query all attestations for a given credential. Supports pagination and filtering by classification. Requires API key authentication.