Detect
The detect endpoint takes one media file and returns the provenance markers that the API finds in it. Every request to this endpoint costs one API call, whatever the number of checks it runs.
The result model
Each check returns one result object. The result field has one of three values.
- Name
found- Description
- The marker is present in the file.
- Name
not_found- Description
The check ran on the file and did not find the marker.
- Name
unavailable- Description
The check could not run. The
reasonfield says why. Common reasons are a media type that the check does not support, and a check that is planned but not available yet.
Result properties
- Name
check- Type
- string
- Description
The check name. Read the detectors page for the full list.
- Name
result- Type
- string
- Description
found,not_found, orunavailable.
- Name
confidence- Type
- number
- Description
A value from 0 to 1. How sure the check is about
result. A parsed C2PA manifest gives 1. An EXIF signal gives less, because EXIF data can be edited.
- Name
issuer- Type
- string
- Description
Who signed or produced the marker, when the marker names them. Only present for
found.
- Name
claims- Type
- object
- Description
Details that depend on the check. For C2PA, this includes the claim generator, the title, the assertion labels, and the signer certificate names.
- Name
reason- Type
- string
- Description
Why the check could not run. Only present for
unavailable.
Check a file
Send exactly one media source. If checks is absent, the API runs every check.
Media source, send one
- Name
url- Type
- string
- Description
A public
httporhttpsURL. The API downloads the file. The limit is 25 MB and 15 seconds. Private and local addresses are refused.
- Name
media- Type
- string
- Description
The file as base64 text. A
data:prefix is allowed. The limit is 4 MB.
- Name
upload- Type
- string
- Description
The path returned by
POST /v1/uploads, for files up to 25 MB. Read the section below.
- Name
file- Type
- file
- Description
For
multipart/form-datarequests only. The file part. The limit is 4 MB.
Optional attributes
- Name
checks- Type
- array
- Description
The checks to run. If absent, every check runs. In a multipart request, send a comma separated string.
Response headers
Every response carries the quota and rate limit headers described on the rate limits page, and an X-Request-Id header. Quote the request id when you contact support.
Request
curl -X POST https://api.provenance.pixellab.nz/v1/detect \
-H "Authorization: Bearer pv_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/photo.jpg",
"checks": ["c2pa", "apple_reference"]
}'
Response
{
"id": "chk_01J5K3W9M2ZC7Q0V4A8B6N1DXY",
"media": {
"type": "image/jpeg",
"bytes": 184320,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
},
"matches": [
{
"check": "c2pa",
"result": "found",
"confidence": 1.0,
"issuer": "OpenAI",
"claims": {
"manifest_count": 1,
"claim_generator": "ChatGPT",
"title": "photo.jpg",
"format": "image/jpeg",
"assertions": ["c2pa.actions", "c2pa.hash.data"],
"signer": {
"common_name": "OpenAI",
"organization": "OpenAI",
"country": "US",
"certificate_issuer": "Truepic"
},
"signature_verified": false
}
},
{
"check": "apple_reference",
"result": "not_found",
"confidence": 0.8,
"claims": { "exif": false }
}
],
"checks_run": ["c2pa", "apple_reference"],
"duration_ms": 412
}
Response properties
- Name
id- Type
- string
- Description
The request id. It starts with
chk_. It is also in theX-Request-Idheader.
- Name
media.type- Type
- string
- Description
The media type that the API read from the first bytes of the file, for example
image/jpeg.
- Name
media.bytes- Type
- integer
- Description
The file size in bytes.
- Name
media.sha256- Type
- string
- Description
The SHA-256 hash of the file, as hex.
- Name
matches- Type
- array
- Description
One result object per check. Read the result model above.
- Name
checks_run- Type
- array
- Description
The check names that ran, in the order requested.
- Name
duration_ms- Type
- integer
- Description
Time spent on the request, in milliseconds. It includes the download.
Upload a large file
Inline media and multipart requests are limited to 4 MB. For larger files, up to 25 MB, use a direct upload. The flow has three steps.
- Call
POST /v1/uploadsto get a signed upload URL. This call does not cost an API call. - Send the file to that URL with
PUT. The URL is valid for two hours. - Call
POST /v1/detectwith theuploadpath from step 1.
The API deletes the uploaded file after it reads it. Each upload path can be used once.
Optional attributes
- Name
filename- Type
- string
- Description
The file name. Only the extension is kept.
- Name
content_type- Type
- string
- Description
The media type to send with the
PUTrequest. Defaults toapplication/octet-stream.
Request
# Step 1: get an upload URL
curl -X POST https://api.provenance.pixellab.nz/v1/uploads \
-H "Authorization: Bearer pv_live_..." \
-H "Content-Type: application/json" \
-d '{"filename": "clip.mp4", "content_type": "video/mp4"}'
# Step 2: upload the file
curl -X PUT "<upload.url>" \
-H "Content-Type: video/mp4" \
--data-binary @clip.mp4
# Step 3: run the checks
curl -X POST https://api.provenance.pixellab.nz/v1/detect \
-H "Authorization: Bearer pv_live_..." \
-H "Content-Type: application/json" \
-d '{"upload": "<upload.path>"}'
Response
{
"upload": {
"path": "8f1c.../up_01J5K3....mp4",
"url": "https://....supabase.co/storage/v1/object/upload/sign/uploads/...",
"method": "PUT",
"headers": { "Content-Type": "video/mp4" },
"max_bytes": 26214400,
"expires_in": 7200
},
"next": {
"method": "POST",
"endpoint": "/v1/detect",
"body": { "upload": "8f1c.../up_01J5K3....mp4" }
}
}