From original file
to structured finding.
Submit case-linked images, preserve evidence context, run forensic analysis, and return review-ready findings to your claims or legal system.
Create your first intake
Each logical intake should carry a unique idempotency key. A timeout can be retried with the same key and body without creating duplicate evidence.
curl -X POST https://www.imgfact.com/api/v1/evidence \
-H "Authorization: Bearer $IMGFACT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: claim-4821-upload-07" \
-d '{
"items": [{
"filename": "rear-impact.jpg",
"file_type": "image/jpeg",
"file_size": 1843920,
"external_reference": "CLAIM-4821-PHOTO-07",
"claim_description": "Rear bumper damage after collision."
}]
}'upload_url. PUT the original directly to that private URL, then confirm receipt.API access requires the $99/month Firms & SIU plan. Free, Starter, and Pro do not include API access. Your plan is checked on every authenticated request.
Use a scoped bearer key
Create keys inside the Firms workspace. The full secret is shown once; ImgFact stores only its SHA-256 digest.
Authorization: Bearer imgf_live_<secret>evidence:write- Intake, confirm, analyze
evidence:read- Evidence and batch results
Four explicit handoffs
The original moves directly into private storage. Each API step remains visible in the workspace audit ledger.
- IntakeCreate records and signed upload URLs.
- UploadPUT each original to its private URL.
- ConfirmRecord receipt and custody context.
- AnalyzeRun analysis, then retrieve structured results.
Endpoints
All v1 routes accept and return JSON, except the signed storage URL used for the original-file upload.
/api/v1/evidenceCreate a batch and signed upload URLsevidence:write/api/v1/evidence/confirmRecord receipt of the uploaded originalevidence:write/api/v1/evidence/analyzeRun forensic and provenance analysisevidence:write/api/v1/evidence/{scan_id}Read status and structured evidence reviewevidence:read/api/v1/batches/{batch_id}Read aggregate batch statusevidence:readVerify every delivery
ImgFact signs <timestamp>.<raw-request-body> with HMAC-SHA256. Reject stale timestamps and compare signatures in constant time before processing the event.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyImgFact(rawBody, signature, secret) {
const fields = Object.fromEntries(
signature.split(",").map((part) => part.split("="))
);
const age = Math.abs(Date.now() / 1000 - Number(fields.t));
if (!Number.isFinite(age) || age > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${fields.t}.${rawBody}`)
.digest();
const received = Buffer.from(fields.v1 ?? "", "hex");
return received.length === expected.length &&
timingSafeEqual(received, expected);
}ImgFact-EventEvent typeImgFact-DeliveryUnique delivery UUIDImgFact-Signaturet=…,v1=…Errors and limits
Error responses include a stable error code and a human-readable message.
401 / 403- Key or scope problem
409- State or idempotency conflict
429- Hourly or monthly limit
- 20 images
- Per intake request
- 20 MB
- Per image
- 5 endpoints
- Per webhook workspace
Integration checklist
A production integration should be retry-safe, signature-aware, and explicit about which identifiers belong to ImgFact and which belong to your system.
- Store API and webhook secrets in a secrets manager.
- Generate one idempotency key per logical intake.
- Persist
batch_id,scan_id, and yourexternal_reference. - Confirm uploads before starting analysis.
- Verify webhook signatures against the raw body.
- Make webhook processing idempotent by delivery or event ID.
- Handle
Retry-Afterand the documented 409 states. - Keep ImgFact findings subject to qualified human review.