> 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.

# Apply and Verify a Watermark

Apply a Resemble watermark to media, retrieve the processed asset, and verify that its watermark can be detected.

## What You Will Build

This walkthrough completes a full watermark round trip:

1. Submit a public media URL for watermarking.
2. Wait for the watermarked output.
3. Submit that output for watermark detection.
4. Interpret the verification result.

The same workflow supports audio, image, and video files.

## Prerequisites

* A Resemble API token with Watermarking access
* A publicly accessible HTTPS URL for an audio, image, or video file
* `curl` and [`jq`](https://jqlang.github.io/jq/)

Set your API token and source URL:

```bash
export RESEMBLE_API_TOKEN="YOUR_API_TOKEN"
export SOURCE_URL="https://example.com/media/source.wav"
```

The source must remain publicly available while processing. Audio, image, and video files can be up to 200 MB. The watermarked file comes back as WAV, PNG, or MP4 unless you add `"output_format": "source"` to the apply request to keep the source's format.

## 1. Apply the Watermark

Create an asynchronous watermark job:

```bash
APPLY_RESPONSE=$(jq -n --arg url "${SOURCE_URL}" '{url: $url}' \
  | curl --silent --show-error --fail-with-body \
      --request POST 'https://app.resemble.ai/api/v2/watermark/apply' \
      -H "Authorization: Bearer ${RESEMBLE_API_TOKEN}" \
      -H 'Content-Type: application/json' \
      --data-binary @-)

echo "${APPLY_RESPONSE}" | jq
export APPLY_UUID=$(echo "${APPLY_RESPONSE}" | jq -r '.item.uuid')
```

For image or video media, you can include a `strength` from `0.0` to `1.0` and a `custom_message` of up to 64 characters. Audio watermarking ignores those fields.

## 2. Retrieve the Watermarked Asset

Poll the apply result until processing finishes:

```bash
while true; do
  APPLY_RESULT=$(curl --silent --show-error --fail-with-body \
    --request GET \
    "https://app.resemble.ai/api/v2/watermark/apply/${APPLY_UUID}/result" \
    -H "Authorization: Bearer ${RESEMBLE_API_TOKEN}")

  STATUS=$(echo "${APPLY_RESULT}" | jq -r '.item.status')
  echo "Apply status: ${STATUS}"

  case "${STATUS}" in
    completed) break ;;
    failed)
      echo "${APPLY_RESULT}" | jq
      exit 1
      ;;
  esac

  sleep 3
done

export WATERMARKED_URL=$(echo "${APPLY_RESULT}" | jq -r '.item.watermarked_media')
echo "Watermarked media: ${WATERMARKED_URL}"
```

> **Warning**
>
> `watermarked_media` is a signed URL that expires. Download the output promptly or use it immediately in the verification request below.

## 3. Detect the Watermark

Submit the watermarked output for verification:

```bash
DETECT_RESPONSE=$(jq -n --arg url "${WATERMARKED_URL}" '{url: $url}' \
  | curl --silent --show-error --fail-with-body \
      --request POST 'https://app.resemble.ai/api/v2/watermark/detect' \
      -H "Authorization: Bearer ${RESEMBLE_API_TOKEN}" \
      -H 'Content-Type: application/json' \
      --data-binary @-)

echo "${DETECT_RESPONSE}" | jq
export WATERMARK_DETECT_UUID=$(echo "${DETECT_RESPONSE}" | jq -r '.item.uuid')
```

If you applied a custom message to an image or video, include that same `custom_message` in this request. Audio detection ignores the field.

## 4. Verify the Result

Poll the detection result:

```bash
while true; do
  WATERMARK_RESULT=$(curl --silent --show-error --fail-with-body \
    --request GET \
    "https://app.resemble.ai/api/v2/watermark/detect/${WATERMARK_DETECT_UUID}/result" \
    -H "Authorization: Bearer ${RESEMBLE_API_TOKEN}")

  STATUS=$(echo "${WATERMARK_RESULT}" | jq -r '.item.status')
  echo "Detection status: ${STATUS}"

  case "${STATUS}" in
    completed) break ;;
    failed)
      echo "${WATERMARK_RESULT}" | jq
      exit 1
      ;;
  esac

  sleep 3
done

echo "${WATERMARK_RESULT}" | jq '.item.metrics'
```

For audio, `metrics.overall_status` is:

| Value          | Meaning                                                                    |
| -------------- | -------------------------------------------------------------------------- |
| `present`      | At least one supported Perth version detected a watermark.                 |
| `absent`       | Both versions completed and neither detected a watermark.                  |
| `inconclusive` | No version detected a watermark and at least one detector was unavailable. |

Audio results also include `coverage_complete`, `detected_model_versions`, and a result for each checked model version.

For images and videos, both `present` and `degraded` indicate that watermark signal was detected. Inspect `detection_score`, `verdict`, and `model_results` for supporting details.

> **Note**
>
> To reduce round trips during development, add `Prefer: wait` to either POST request. The initial response then waits for processing and returns the completed job when possible.

## Troubleshooting

| Problem                              | What to check                                                                                    |
| ------------------------------------ | ------------------------------------------------------------------------------------------------ |
| The apply request fails              | Confirm that the URL is public HTTPS, points directly to supported media, and remains available. |
| Image/video verification is negative | Use the same `custom_message` for both apply and detect.                                         |
| `overall_status` is `inconclusive`   | Inspect `model_results` to see which detector was unavailable.                                   |
| The watermarked URL no longer works  | The signed output URL expired; retrieve or generate the output again.                            |

## Endpoint Guides

* [Apply Watermark](/detect/watermark/apply)
* [Detect Watermark](/detect/watermark/detect)
* [Watermarking Overview](/detect/watermark)