Use the Content Provenance API to check whether an image or audio file contains
supported OpenAI provenance signals. Send a file to
POST /v1/content_provenance_checks to receive the completed verification
results in the same response. Use these signals in content review,
fact-checking, labeling, and trust and safety workflows.
To check a file in your browser, use our web tool at openai.com/verify.
For request parameters and response schemas, see the Content provenance API reference.
A not_detected result means the tool didn’t find supported signals in the
uploaded file. Content may still have been generated by OpenAI if its metadata
was stripped or shows evidence of tampering, its watermark was degraded, it
came from a legacy generation model, or it was created before provenance
signals were available. The tool doesn’t currently detect content generated by
another company’s AI model, so a not_detected result doesn’t rule that out
either.
What content provenance checks
Content provenance checks supported files for the following signals:
| Signal | Applies to | What it checks |
|---|---|---|
| C2PA Content Credentials | Images | Signed metadata with issuer and AI-use details |
| SynthID | Images and audio | A watermark embedded directly in supported media |
C2PA metadata provides more context about a file’s origin. Editing, converting, or sharing a file can remove its metadata. A SynthID watermark is part of the image or audio itself and may survive some transformations.
The API checks for supported OpenAI signals. It isn’t a general-purpose AI detector and doesn’t identify content generated by every AI system. Visible watermarks and labels are separate from the provenance signals checked by the API.
Verify a file
Send an image or audio file as the file field in a multipart/form-data
request. Authenticate with your OpenAI API key:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os
import requests
with open("./example.png", "rb") as image:
response = requests.post(
"https://api.openai.com/v1/content_provenance_checks",
headers={"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"},
files={"file": ("example.png", image, "image/png")},
timeout=600,
)
response.raise_for_status()
print(response.json())The Python example uses requests. The JavaScript example uses Node.js built-in
fetch.
To verify Opus audio, use the same endpoint and set the uploaded file’s media
type to audio/ogg:
1
2
3
curl https://api.openai.com/v1/content_provenance_checks \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F "file=@./example.opus;type=audio/ogg"The response contains the completed result. For example, an image returns:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"object": "content_provenance_check",
"created_at": 1778000000,
"results": [
{
"type": "c2pa",
"outcome": "detected",
"validation_state": "trusted",
"issuer": "OpenAI OpCo, LLC",
"model": "gpt-image",
"generated_at": "2026-07-27T18:34:12Z"
},
{
"type": "synthid",
"outcome": "not_detected",
"model": null,
"generated_at": null
}
]
}The object field identifies the response, and created_at is the check’s
creation time as a Unix timestamp in seconds. The entries in results depend on
the uploaded file: images include C2PA and SynthID results, and audio includes a
SynthID result. The API omits checks that don’t apply instead of returning
not_detected.
The API completes verification before it returns. You don’t need to create a background job, poll another endpoint, or upload the file to the Files API.
If a request fails, check the HTTP status and error.code when available. A
malformed, unsupported, or blocked file returns 400; an organization without
access receives 404; and requests over the rate limit return 429. Retry only
transient failures, such as rate limits or server errors. For general guidance,
see API error codes.
Understand verification results
Read each applicable entry in results independently. Image results include
C2PA and SynthID entries, while audio results include a SynthID entry. The
response doesn’t include a top-level outcome.
C2PA results
A C2PA result describes the state of an image’s Content Credentials:
1
2
3
4
5
6
7
8
{
"type": "c2pa",
"outcome": "detected",
"validation_state": "trusted",
"issuer": "OpenAI OpCo, LLC",
"model": "gpt-image",
"generated_at": "2026-07-27T18:34:12Z"
}Use the fields as follows:
outcomeindicates whether OpenAI-issued AI-generation credentials weredetectedornot_detected.validation_stateindicates whether the manifest istrusted,valid,invalid, ornot_present.issueridentifies the manifest issuer when that information is available.modelidentifies the generating model when that information is available.generated_atidentifies the content’s generation time when that information is available.
The outcome is detected only when a trusted or valid manifest identifies
OpenAI as its issuer and includes an AI-generation action. A third-party
manifest, a manifest without an AI-generation action, an invalid manifest, or
a not_present manifest produces not_detected. The issuer and
validation_state can still describe a manifest even when the outcome is
not_detected.
Don’t treat an invalid manifest as reliable provenance evidence. A
not_present result means the image has no available C2PA manifest.
SynthID results
A SynthID result describes whether the verifier detected a supported watermark in an image or audio file:
1
2
3
4
5
6
{
"type": "synthid",
"outcome": "detected",
"model": null,
"generated_at": null
}An outcome of detected means the file contains a recognized watermark. An
outcome of not_detected means the verifier didn’t detect that watermark. It
doesn’t rule out AI-generated or AI-modified content. model and
generated_at provide the generating model and generation time when available;
either field can be null.
Supported formats and availability
The API supports the following file formats:
- Images: PNG, JPEG, and WebP.
- Audio: MP3, Opus, AAC, FLAC, WAV, and PCM.
Limit each uploaded file to 50 MiB. Audio must be 60 seconds or shorter after decoding.
Set the uploaded file part’s media type. For example, use image/png for a PNG
image or audio/ogg for Opus audio. Don’t add a separate type field or
manually set the multipart/form-data request header. The curl -F option
sets the request content type and multipart boundary. Send one file per request.
Content provenance checks aren’t eligible for Zero Data Retention.
Strict rate limits help protect the API against misuse. Organizations can apply for higher limits, and OpenAI reviews each application on a case-by-case basis.
If the API returns 429 rate_limit_exceeded, reduce your request rate and
honor the Retry-After header when present. See
rate limits for general retry guidance.
Use verification results responsibly
Use verification results as evidence in a broader review process:
- Treat
detectedas evidence of a specific supported signal, not a complete history of a file. - Treat
not_detectedas an absence of detected evidence, not proof that the content is human-created or wasn’t generated with OpenAI. - Check the C2PA issuer before attributing an image to a particular provider.
- Verify the original file when possible. Compression, cropping, screenshots, metadata removal, and format conversions can erase or weaken a signal.
- Account for the originating product, model, file format, and creation date. Not all OpenAI-generated content contains a supported signal.
- Pair automated decisions with human review in high-stakes workflows.
- Don’t use repeated queries to reverse-engineer, remove, or evade a watermark.
- Don’t infer a prompt, account, or individual creator from a verification result.
Using the Content Provenance API is subject to the OpenAI Services Agreement.
For information about platform-wide monitoring and retention settings, see data controls.