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

Set your API token and source URL:

$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 and image files can be up to 25 MB; videos can be up to 100 MB.

1. Apply the Watermark

Create an asynchronous watermark job:

$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:

$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}"

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:

$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:

$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:

ValueMeaning
presentAt least one supported Perth version detected a watermark.
absentBoth versions completed and neither detected a watermark.
inconclusiveNo 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.

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

ProblemWhat to check
The apply request failsConfirm that the URL is public HTTPS, points directly to supported media, and remains available.
Image/video verification is negativeUse the same custom_message for both apply and detect.
overall_status is inconclusiveInspect model_results to see which detector was unavailable.
The watermarked URL no longer worksThe signed output URL expired; retrieve or generate the output again.

Endpoint Guides