> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.resemble.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.resemble.ai/_mcp/server.

# Detect Watermark

Detect a watermark in an audio, image, or video file. Audio detection checks both Perth v1 and Perth v2; image/video detection is reported as Perth v2. All three modalities also receive an auxiliary SynthID check.

`POST https://app.resemble.ai/api/v2/watermark/detect`

## Request parameters

| Field            | Type   | Required | Description                                                                                                            |
| ---------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `url`            | string | Yes      | Public HTTPS URL to the audio, image, or video file.                                                                   |
| `custom_message` | string | No       | Message used when applying an image/video watermark, up to 64 characters. Defaults to `resembleai`; ignored for audio. |

For image/video, use the same `custom_message` that was used when the watermark was applied. Images can be PNG, JPEG, WebP, AVIF, or another common image format.

## Headers

| Header          | Value                   | Description                                                                                                           |
| --------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `Authorization` | `Bearer YOUR_API_TOKEN` | Required. Your API token.                                                                                             |
| `Content-Type`  | `application/json`      | Required.                                                                                                             |
| `Prefer`        | `wait`                  | Optional. Wait for Resemble watermark detection and the SynthID attempt, then return metrics in the initial response. |

## Examples

### Detect an audio watermark

```bash
curl --request POST 'https://app.resemble.ai/api/v2/watermark/detect' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{
    "url": "https://example.com/audio/suspect.wav"
  }'
```

### Detect an image watermark synchronously

```bash
curl --request POST 'https://app.resemble.ai/api/v2/watermark/detect' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Prefer: wait' \
  --data '{
    "url": "https://example.com/images/suspect.png",
    "custom_message": "resembleai"
  }'
```

### Detect a video watermark

```bash
curl --request POST 'https://app.resemble.ai/api/v2/watermark/detect' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{
    "url": "https://example.com/videos/suspect.mp4"
  }'
```

## Initial response

Without `Prefer: wait`, the API returns the queued job with `metrics` set to `null`.

```json
{
  "success": true,
  "item": {
    "uuid": "JOB_UUID",
    "media_type": "audio",
    "operation_type": "detect",
    "status": "pending",
    "source_media_url": "https://example.com/audio/suspect.wav",
    "metrics": null,
    "watermarked_media": null,
    "created_at": "2026-07-22T12:00:00.000Z",
    "updated_at": "2026-07-22T12:00:00.000Z"
  }
}
```

Audio detect jobs do not have a single top-level `model_version`; each checked version is reported in `metrics.model_results`. Image/video detect jobs include `model_version: "perth_v2"`.

## Fetch detection result

Retrieve the current detection result using its UUID.

`GET https://app.resemble.ai/api/v2/watermark/detect/{uuid}/result`

```bash
curl --request GET 'https://app.resemble.ai/api/v2/watermark/detect/JOB_UUID/result' \
  -H 'Authorization: Bearer YOUR_API_TOKEN'
```

## Audio detection response

The following result detected a Perth v1 watermark and received a successful negative result from Perth v2:

```json
{
  "success": true,
  "item": {
    "uuid": "JOB_UUID",
    "media_type": "audio",
    "operation_type": "detect",
    "status": "completed",
    "source_media_url": "https://example.com/audio/suspect.wav",
    "metrics": {
      "overall_status": "present",
      "detected_model_versions": ["perth_v1"],
      "coverage_complete": true,
      "has_watermark": {
        "channel_0": true
      },
      "confidence": 0.97,
      "synthid": false,
      "model_results": [
        {
          "model_version": "perth_v1",
          "status": "succeeded",
          "detected": true,
          "has_watermark": {
            "channel_0": true
          },
          "confidence": 0.97
        },
        {
          "model_version": "perth_v2",
          "status": "succeeded",
          "detected": false,
          "has_watermark": {
            "channel_0": false
          },
          "confidence": 0.02
        }
      ]
    },
    "watermarked_media": null,
    "created_at": "2026-07-22T12:00:00.000Z",
    "updated_at": "2026-07-22T12:00:05.000Z"
  }
}
```

### Interpret the audio verdict

| `overall_status` | Meaning                                                                |
| ---------------- | ---------------------------------------------------------------------- |
| `present`        | At least one Perth version detected a watermark.                       |
| `absent`         | Both versions completed successfully and neither detected a watermark. |
| `inconclusive`   | Neither version detected a watermark and one version was unavailable.  |

`coverage_complete` is `true` only when both versions completed successfully. A positive result remains `present` if the other detector is unavailable, but `coverage_complete` will be `false`.

`synthid` is an independent boolean returned by SynthID. It does not change `overall_status`, `coverage_complete`, or the Perth results. If the SynthID request is unavailable or does not return a valid boolean, the field is omitted; clients must not treat omission as `false`.

Temporary timeout, connection, rate-limit, and server errors are retried once per detector. If a detector is still unavailable, its model result has this shape:

```json
{
  "model_version": "perth_v1",
  "status": "failed",
  "detected": null,
  "error": "Detector unavailable"
}
```

If both audio detectors are unavailable, the job fails. A successful detector is not repeated when only the other detector needs a retry.

## Image/video detection response

Image and video detection returns one public model result identified as `perth_v2`.

```json
{
  "success": true,
  "item": {
    "uuid": "JOB_UUID",
    "media_type": "image",
    "operation_type": "detect",
    "status": "completed",
    "model_version": "perth_v2",
    "source_media_url": "https://example.com/images/suspect.png",
    "metrics": {
      "overall_status": "present",
      "detected_model_versions": ["perth_v2"],
      "has_watermark": true,
      "detection_score": 0.94,
      "model_results": [
        {
          "model_version": "perth_v2",
          "status": "succeeded",
          "detected": true,
          "confidence": 0.94
        }
      ],
      "verdict": "verified",
      "synthid": true
    },
    "watermarked_media": null,
    "created_at": "2026-07-22T12:00:00.000Z",
    "updated_at": "2026-07-22T12:00:08.000Z"
  }
}
```

Image/video `overall_status` can be `present`, `degraded`, `absent`, or `inconclusive`, based on the available Resemble detection score. Both `present` and `degraded` indicate detected Resemble watermark signal. The optional `synthid` boolean is returned independently for both image and video.

## Response fields

| Field                                  | Type              | Description                                                                                         |
| -------------------------------------- | ----------------- | --------------------------------------------------------------------------------------------------- |
| `success`                              | boolean           | Whether the API request succeeded.                                                                  |
| `item.uuid`                            | string            | Unique identifier for the watermark job.                                                            |
| `item.media_type`                      | string            | Detected media type: `audio`, `image`, or `video`.                                                  |
| `item.operation_type`                  | string            | `detect`.                                                                                           |
| `item.status`                          | string            | `pending`, `processing`, `completed`, or `failed`.                                                  |
| `item.model_version`                   | string            | `perth_v2` for image/video; omitted for audio detection.                                            |
| `item.source_media_url`                | string            | Original source URL.                                                                                |
| `item.metrics`                         | object \| null    | Detection metrics when complete; otherwise `null`.                                                  |
| `item.metrics.overall_status`          | string            | Aggregate detection verdict.                                                                        |
| `item.metrics.detected_model_versions` | string\[]         | Only model versions that positively detected a watermark.                                           |
| `item.metrics.coverage_complete`       | boolean           | Audio only. Whether both Perth versions completed successfully.                                     |
| `item.metrics.has_watermark`           | object \| boolean | Per-channel aggregate for audio; boolean for image/video.                                           |
| `item.metrics.confidence`              | number \| null    | Audio aggregate confidence.                                                                         |
| `item.metrics.detection_score`         | number \| null    | Image/video detection score.                                                                        |
| `item.metrics.model_results`           | object\[]         | Separate results for every checked model version.                                                   |
| `item.metrics.synthid`                 | boolean           | Optional auxiliary SynthID verdict for audio, image, or video. Omitted when SynthID is unavailable. |
| `item.watermarked_media`               | null              | Detection does not produce a watermarked output file.                                               |

> **Note**
>
> Results for jobs created before the versioned audio response was introduced can contain historical flat metrics without `overall_status` or `model_results`. Clients reading stored results should tolerate both shapes.

## Error handling

Invalid input returns an error response, for example:

```json
{
  "success": false,
  "error": "File must be valid media format"
}
```

The source must be publicly accessible over HTTPS and remain available while processing. Audio, image, and video sources are limited to 200 MB.