Skip to content

QUICKSTART

Sign and verify your first manifest

End-to-end in under 5 minutes. You will create an account, get an API key, sign a file via POST /v1/sign, then verify the resulting manifest. Both cURL and TypeScript paths are shown side-by-side.

1. Create an account and an API key

Sign up at hashproof.ai/sign-up (Free tier, no card). Then go to Dashboard / API Keys and create a key. The key is shown once at creation; copy it now.

For local experiments, export the key into your shell:

export HASHPROOF_API_KEY="hpsk_live_xxxxxxxxxxxx"

2. Sign a file

The signing endpoint takes a multipart file upload and returns a stored manifest with a unique manifestId. The signature uses ES256 plus a post-quantum hybrid (ML-DSA-65) on every tier.

cURL

curl -X POST https://api.hashproof.ai/v1/sign \
  -H "x-api-key: $HASHPROOF_API_KEY" \
  -F "file=@./photo.jpg" \
  -F "title=Field photo, Reykjavik 2026"

# => {
#   "manifestId": "ce29...c4f1",
#   "manifest": { … },
#   "message": "Asset signed and manifest stored successfully"
# }

TypeScript

import { Hashproof } from '@hashproof/sdk';

const client = new Hashproof({ apiKey: process.env.HASHPROOF_API_KEY! });

const file = await fetch('./photo.jpg').then((r) => r.blob());
const result = await client.sign(file, {
  title: 'Field photo, Reykjavik 2026',
});

console.log(result.manifestId);

3. Verify a file

The verify endpoint is public (no API key required) so any consumer of your content can confirm it. Upload the same file (or a copy) and Hashproof checks embedded C2PA, hard binding (SHA-256), then soft binding (perceptual hash) before returning a structured trust result.

cURL

curl -X POST https://api.hashproof.ai/v1/verify \
  -F "file=@./photo.jpg"

# => {
#   "hasProvenance": true,
#   "source": "embedded",
#   "manifest": { … },
#   "validation": { "status": "valid", "signerTrusted": true, … },
#   "trustStatus": "trusted"
# }

TypeScript

import { Hashproof } from '@hashproof/sdk';

const client = new Hashproof();
const file = await fetch('./photo.jpg').then((r) => r.blob());
const result = await client.verify(file);

if (result.trustStatus === 'trusted') {
  console.log('Provenance valid. Signed by:', result.manifest?.signatureInfo.subject);
} else {
  console.warn('Untrusted or no provenance found.');
}

4. Resolve when the file has been re-encoded

Real-world distribution strips C2PA metadata. Resolve takes a file (or pre-computed perceptual hash) and finds the original manifest via soft binding. Useful when content has been re-uploaded, cropped, or transcoded.

cURL

curl -X POST https://api.hashproof.ai/v1/resolve \
  -H "x-api-key: $HASHPROOF_API_KEY" \
  -F "file=@./photo-reencoded.jpg" \
  -F "algorithm=phash-dct-64"

# => {
#   "matches": [{ "manifestId": "ce29...c4f1", "similarity": 0.97 }],
#   "query": { "algorithm": "phash-dct-64" },
#   "c2pa": { "version": "2.1", "resolution_results": [...] }
# }

TypeScript

const matches = await client.resolve(file, { algorithm: 'phash-dct-64' });

if (matches.matches.length > 0) {
  const top = matches.matches[0];
  console.log('Soft-bound to', top.manifestId, 'at similarity', top.similarity);
}

Next steps