# Content provenance

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

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 the web tool at
[openai.com/verify](https://openai.com/verify/).

For request parameters and response schemas, see the
[Content provenance API reference](https://developers.openai.com/api/reference/resources/content_provenance_checks/methods/create).

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 with the OpenAI SDK. The SDK
builds the multipart request and reads your API key from the `OPENAI_API_KEY`
environment variable:

Verify an image

```python
from openai import OpenAI

client = OpenAI()

with open("./example.png", "rb") as image:
    result = client.content_provenance_checks.create(
        file=("example.png", image, "image/png"),
    )

print(result)
```

```go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/openai/openai-go/v3"
)

func main() {
	client := openai.NewClient()

	image, err := os.Open("./example.png")
	if err != nil {
		panic(err)
	}
	defer image.Close()

	result, err := client.ContentProvenanceChecks.New(
		context.Background(),
		openai.ContentProvenanceCheckNewParams{
			File: openai.File(image, "example.png", "image/png"),
		},
	)
	if err != nil {
		panic(err)
	}

	fmt.Println(result)
}
```

```ruby
require "openai"
require "pathname"

client = OpenAI::Client.new
image = OpenAI::FilePart.new(Pathname("./example.png"), content_type: "image/png")
result = client.content_provenance_checks.create(file: image)

puts result
```

```bash
curl https://api.openai.com/v1/content_provenance_checks \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F "file=@./example.png;type=image/png"
```


Use these OpenAI SDK versions or later: Python 2.52.0, Go 3.49.0, and Ruby
0.75.0.

To verify Opus audio, use the same endpoint and set the uploaded file's media
type to `audio/ogg`:

```bash
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:

```json
{
  "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](https://developers.openai.com/api/docs/guides/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:

```json
{
  "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:

- `outcome` indicates whether OpenAI-issued AI-generation credentials were
  `detected` or `not_detected`.
- `validation_state` indicates whether the manifest is `trusted`, `valid`,
  `invalid`, or `not_present`.
- `issuer` identifies the manifest issuer when that information is available.
- `model` identifies the generating model when that information is available.
- `generated_at` identifies 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:

```json
{
  "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](https://developers.openai.com/api/docs/guides/your-data#zero-data-retention).

Strict rate limits help protect the API against misuse. Organizations can
[apply for higher limits](https://openai.com/form/content-provenance-api/), 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](https://developers.openai.com/api/docs/guides/rate-limits) for general retry guidance.

## Use verification results responsibly

Use verification results as evidence in a broader review process:

- Treat `detected` as evidence of a specific supported signal, not a complete
  history of a file.
- Treat `not_detected` as 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](https://openai.com/policies/services-agreement/).

For information about platform-wide monitoring and retention settings, see
[data controls](https://developers.openai.com/api/docs/guides/your-data).