Integrate proofd.id.
Ship hash-first proof workflows.
Create timestamps, read status, and download OpenTimestamps evidence from a premium REST API. Clients hash files locally and send only SHA-256 fingerprints plus file metadata.
VERSION
1.0.0
AUTH
BEARER
INPUT
HASH ONLY
FORMAT
OPENAPI 3.1
RESPONSE ENVELOPE
Every response includes X-Request-Id. Errors always return a stable JSON envelope with code, message, and request_id.
Get from key to proof in four steps.
Generate an API key
Open Settings -> API access on a Pro or Business account and rotate a key. The full secret is shown once only.
Hash files locally
Compute SHA-256 on your side and keep the original file off the wire. proofd.id only receives the fingerprint and metadata.
Create with Idempotency-Key
POST the hash to /api/v1/timestamps with a unique Idempotency-Key for safe retries from job queues and integration workers.
Track status and download proof
Read the timestamp resource or list endpoint until status changes, then download the .ots proof from the OTS route when you need evidence.
Copy-ready integration snippets.
Use the same request model across CLI tools, browsers, and backend workers. The API is hash-only by design.
curl --request POST \
--url https://proofd.id/api/v1/timestamps \
--header 'Authorization: Bearer proofd_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: contract-msa-v3-2026-04-13' \
--data '{
"sha256_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"filename": "msa-v3.pdf",
"file_size_bytes": 248331,
"file_type": "application/pdf"
}'const response = await fetch('https://proofd.id/api/v1/timestamps', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.NEXT_PUBLIC_PROOFD_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
sha256_hash: '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
filename: 'msa-v3.pdf',
file_size_bytes: 248331,
file_type: 'application/pdf',
}),
})
const payload = await response.json()
if (!response.ok) throw new Error(payload.error.message)
console.log(payload.id, payload.certificate_url)const response = await fetch('https://proofd.id/api/v1/timestamps?status=pending&limit=10', {
headers: {
Authorization: 'Bearer ' + process.env.PROOFD_API_KEY,
},
})
const payload = await response.json()
if (!response.ok) throw new Error(payload.error.message)
for (const timestamp of payload.data) {
console.log(timestamp.id, timestamp.status, timestamp.ots_url)
}From local file to premium API proof.
This demo hashes the selected file in the browser, then sends only the SHA-256 fingerprint and metadata to /api/v1/timestamps with your Bearer key.
Live File-To-Proof Demo
Pick a local file, hash it in the browser, then call the premium API with your Bearer key. The original file never leaves the device.
The key is used only for this request from the current browser session. Store production keys in a server-side secret manager.
Optional. Use a stable value when you want safe retries for the same create request.
Local Hashing State
Select a file to compute its SHA-256 fingerprint in this browser.
Endpoint-by-endpoint contract.
/api/v1/timestampsCreate a timestamp record for a SHA-256 hash.
Creates an owner-scoped timestamp resource, reserves the same quota pool as the web app, and returns certificate and verification URLs immediately.
AuthorizationBearer tokenREQUIREDUse `Bearer proofd_live_...`.
Content-Typeapplication/jsonREQUIREDJSON payload for the hash and file metadata.
Idempotency-KeystringOptional but strongly recommended. Supports safe retries for job workers and webhooks.
sha256_hashstring (64 hex chars)REQUIREDClient-computed SHA-256 fingerprint of the file.
filenamestringREQUIREDDisplay filename stored with the timestamp record.
file_size_bytesintegerREQUIREDPositive file size in bytes.
file_typestringOptional MIME type such as `application/pdf`.
Returns the canonical timestamp resource. The initial status may be `pending` until blockchain confirmation completes.
- Idempotent replays return the original success response for the same payload and Idempotency-Key.
- A duplicate hash for the same owner returns `DUPLICATE_TIMESTAMP` with HTTP 409.
- Create traffic has its own tighter rate limits: 30 requests/minute per key and 60 requests/minute per IP backstop.
{
"id": "7b4d95f8-91cb-4e1c-b7d6-1eb9f0de4e8d",
"certificate_id": "TS-0K7M6X",
"sha256_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"filename": "msa-v3.pdf",
"file_size_bytes": 248331,
"file_type": "application/pdf",
"status": "pending",
"blockchain_tx": null,
"bitcoin_block": null,
"confirmed_at": null,
"created_at": "2026-04-13T18:42:11.000Z",
"thumbnail_url": null,
"branding_snapshot": null,
"certificate_url": "https://proofd.id/cert/TS-0K7M6X",
"verify_url": "https://proofd.id/verify/9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"ots_url": "/api/v1/timestamps/7b4d95f8-91cb-4e1c-b7d6-1eb9f0de4e8d/ots"
}/api/v1/timestampsList timestamps owned by the authenticated account.
Returns owner-scoped timestamps sorted by `created_at desc`. Use `before` for cursor pagination and `status` to filter active queues.
AuthorizationBearer tokenREQUIREDUse `Bearer proofd_live_...`.
statusall | confirmed | pending | failedOptional status filter. Defaults to `all`.
beforeISO-8601 timestampCursor for the next page, using the previous response `next_cursor`.
limitintegerOptional page size. The API caps the value at 50.
Returns a paginated list with `total_count` and an optional `next_cursor`.
- Sort order is fixed to newest first in v1.
- Only the authenticated owner sees records; there is no cross-account or public list access.
{
"data": [
{
"id": "7b4d95f8-91cb-4e1c-b7d6-1eb9f0de4e8d",
"certificate_id": "TS-0K7M6X",
"sha256_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"filename": "msa-v3.pdf",
"file_size_bytes": 248331,
"file_type": "application/pdf",
"status": "pending",
"blockchain_tx": null,
"bitcoin_block": null,
"confirmed_at": null,
"created_at": "2026-04-13T18:42:11.000Z",
"thumbnail_url": null,
"branding_snapshot": null,
"certificate_url": "https://proofd.id/cert/TS-0K7M6X",
"verify_url": "https://proofd.id/verify/9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"ots_url": "/api/v1/timestamps/7b4d95f8-91cb-4e1c-b7d6-1eb9f0de4e8d/ots"
}
],
"total_count": 1,
"next_cursor": "2026-04-13T18:42:11.000Z"
}/api/v1/timestamps/{id}Fetch a single timestamp resource by UUID.
Returns the canonical resource for an owner-scoped timestamp, including blockchain fields, verification URL, certificate URL, and OTS download path.
AuthorizationBearer tokenREQUIREDUse `Bearer proofd_live_...`.
Returns the same timestamp resource shape as the create response.
- The `id` path parameter must be a UUID.
- Unknown or cross-account IDs return `TIMESTAMP_NOT_FOUND`.
{
"id": "7b4d95f8-91cb-4e1c-b7d6-1eb9f0de4e8d",
"certificate_id": "TS-0K7M6X",
"sha256_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"filename": "msa-v3.pdf",
"file_size_bytes": 248331,
"file_type": "application/pdf",
"status": "pending",
"blockchain_tx": null,
"bitcoin_block": null,
"confirmed_at": null,
"created_at": "2026-04-13T18:42:11.000Z",
"thumbnail_url": null,
"branding_snapshot": null,
"certificate_url": "https://proofd.id/cert/TS-0K7M6X",
"verify_url": "https://proofd.id/verify/9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"ots_url": "/api/v1/timestamps/7b4d95f8-91cb-4e1c-b7d6-1eb9f0de4e8d/ots"
}/api/v1/timestamps/{id}/otsDownload the OpenTimestamps proof file for a timestamp.
Streams the owner-scoped `.ots` evidence as `application/octet-stream`. Use the timestamp resource to discover the route and filename context.
AuthorizationBearer tokenREQUIREDUse `Bearer proofd_live_...`.
Returns binary content with `Content-Disposition: attachment; filename="<safe-filename>.ots"`.
- The `id` path parameter must be a UUID.
- If no OTS payload is available yet, the route returns `OTS_NOT_FOUND`.
- The response body is binary rather than JSON.
This route returns binary content with application/octet-stream.
Stable codes and operational guidance.
AUTHENTICATION_REQUIREDNo Bearer token was provided.
Send `Authorization: Bearer <api_key>` on every request.
INVALID_API_KEYThe key does not match an active premium credential.
Rotate the key in Settings and update the integration secret store.
PLAN_NOT_ENTITLEDThe authenticated account is not on a premium plan with API access.
Upgrade the account to Pro or Business before retrying.
INVALID_JSONThe request body is not valid JSON.
Ensure the payload is valid JSON and `Content-Type` is `application/json`.
INVALID_SHA256_HASHThe supplied hash is not a 64-character hexadecimal SHA-256 fingerprint.
Recompute the hash locally and send the lowercase or uppercase hex digest.
INVALID_FILENAMEThe payload is missing a non-empty filename.
Send the original display filename alongside the hash.
INVALID_FILE_SIZEThe payload is missing a positive byte size.
Send `file_size_bytes` as a positive integer.
INVALID_FILE_TYPEThe optional MIME type is not a string.
Either omit `file_type` or send a string such as `application/pdf`.
INVALID_STATUSThe list filter includes an unsupported status.
Use only `all`, `confirmed`, `pending`, or `failed`.
INVALID_LIMITThe list limit is not a positive integer.
Send a positive integer and keep client expectations within the 50-item cap.
INVALID_CURSORThe `before` query parameter is not a valid ISO-8601 timestamp.
Use the `next_cursor` value returned by the previous page.
INVALID_IDThe timestamp path parameter is not a UUID.
Persist the timestamp `id` returned at creation and use it unchanged.
INVALID_IDEMPOTENCY_KEYThe provided Idempotency-Key is empty or too long.
Use a stable key between 1 and 200 characters.
IDEMPOTENCY_MISMATCHThe same Idempotency-Key was reused for a different create payload.
Reuse the key only for byte-for-byte identical create requests.
IDEMPOTENCY_IN_PROGRESSA previous request with the same Idempotency-Key is still processing.
Retry after a short delay instead of sending a new key immediately.
MONTHLY_LIMIT_REACHEDThe account exhausted its current monthly timestamp allowance.
Wait for quota renewal or upgrade the plan.
DUPLICATE_TIMESTAMPThe same owner already timestamped this hash.
Persist and reuse the original timestamp ID instead of creating a duplicate.
TIMESTAMP_NOT_FOUNDThe referenced UUID does not exist for the authenticated owner.
Check the stored timestamp ID and account context.
OTS_NOT_FOUNDNo OTS payload is currently available for the referenced timestamp.
Retry later after the timestamp progresses, or inspect the timestamp status first.
RATE_LIMITEDA rate-limit bucket was exceeded.
Honor `Retry-After` and the `X-RateLimit-*` headers before retrying.
OTS_PROVIDER_ERRORThe upstream OpenTimestamps creation step failed.
Retry with the same Idempotency-Key and escalate with the request ID if the error persists.
INTERNAL_ERRORThe platform failed while validating or serving the request.
Retry if appropriate and include `request_id` in support tickets.
Platform rules worth designing around.
RATE LIMITS
- 120 requests per minute per API key for general traffic.
- 30 create requests per minute per API key.
- 60 create requests per minute per source IP as a backstop.
- Throttle responses include `Retry-After` and `X-RateLimit-*` headers.
SECURITY MODEL
- Store the API key in a server-side secret manager, never in browser bundles.
- Rotate immediately if a credential leaks; the previous key stops working at once.
- Use Idempotency-Key for queued or retried create operations.
- Capture `X-Request-Id` in logs so support can trace failed calls.
PRODUCT RULES
- Premium API access is available on Pro and Business plans only.
- The API accepts SHA-256 hashes only. Original files never need to be uploaded to the API.
- API traffic consumes the same monthly timestamp quota as the web product for the owning account.
- A timestamp record is created immediately, while blockchain confirmation completes asynchronously later.
- Each account has one active API key in v1. Rotating a key revokes the previous credential immediately.