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

FieldTypeRequiredDescription
urlstringYesPublic HTTPS URL to the audio, image, or video file.
custom_messagestringNoMessage 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.

Headers

HeaderValueDescription
AuthorizationBearer YOUR_API_TOKENRequired. Your API token.
Content-Typeapplication/jsonRequired.
PreferwaitOptional. Wait for Resemble watermark detection and the SynthID attempt, then return metrics in the initial response.

Examples

Detect an audio watermark

$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

$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

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

1{
2 "success": true,
3 "item": {
4 "uuid": "JOB_UUID",
5 "media_type": "audio",
6 "operation_type": "detect",
7 "status": "pending",
8 "source_media_url": "https://example.com/audio/suspect.wav",
9 "metrics": null,
10 "watermarked_media": null,
11 "created_at": "2026-07-22T12:00:00.000Z",
12 "updated_at": "2026-07-22T12:00:00.000Z"
13 }
14}

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

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

1{
2 "success": true,
3 "item": {
4 "uuid": "JOB_UUID",
5 "media_type": "audio",
6 "operation_type": "detect",
7 "status": "completed",
8 "source_media_url": "https://example.com/audio/suspect.wav",
9 "metrics": {
10 "overall_status": "present",
11 "detected_model_versions": ["perth_v1"],
12 "coverage_complete": true,
13 "has_watermark": {
14 "channel_0": true
15 },
16 "confidence": 0.97,
17 "synthid": false,
18 "model_results": [
19 {
20 "model_version": "perth_v1",
21 "status": "succeeded",
22 "detected": true,
23 "has_watermark": {
24 "channel_0": true
25 },
26 "confidence": 0.97
27 },
28 {
29 "model_version": "perth_v2",
30 "status": "succeeded",
31 "detected": false,
32 "has_watermark": {
33 "channel_0": false
34 },
35 "confidence": 0.02
36 }
37 ]
38 },
39 "watermarked_media": null,
40 "created_at": "2026-07-22T12:00:00.000Z",
41 "updated_at": "2026-07-22T12:00:05.000Z"
42 }
43}

Interpret the audio verdict

overall_statusMeaning
presentAt least one Perth version detected a watermark.
absentBoth versions completed successfully and neither detected a watermark.
inconclusiveNeither 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:

1{
2 "model_version": "perth_v1",
3 "status": "failed",
4 "detected": null,
5 "error": "Detector unavailable"
6}

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.

1{
2 "success": true,
3 "item": {
4 "uuid": "JOB_UUID",
5 "media_type": "image",
6 "operation_type": "detect",
7 "status": "completed",
8 "model_version": "perth_v2",
9 "source_media_url": "https://example.com/images/suspect.png",
10 "metrics": {
11 "overall_status": "present",
12 "detected_model_versions": ["perth_v2"],
13 "has_watermark": true,
14 "detection_score": 0.94,
15 "model_results": [
16 {
17 "model_version": "perth_v2",
18 "status": "succeeded",
19 "detected": true,
20 "confidence": 0.94
21 }
22 ],
23 "verdict": "verified",
24 "synthid": true
25 },
26 "watermarked_media": null,
27 "created_at": "2026-07-22T12:00:00.000Z",
28 "updated_at": "2026-07-22T12:00:08.000Z"
29 }
30}

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

FieldTypeDescription
successbooleanWhether the API request succeeded.
item.uuidstringUnique identifier for the watermark job.
item.media_typestringDetected media type: audio, image, or video.
item.operation_typestringdetect.
item.statusstringpending, processing, completed, or failed.
item.model_versionstringperth_v2 for image/video; omitted for audio detection.
item.source_media_urlstringOriginal source URL.
item.metricsobject | nullDetection metrics when complete; otherwise null.
item.metrics.overall_statusstringAggregate detection verdict.
item.metrics.detected_model_versionsstring[]Only model versions that positively detected a watermark.
item.metrics.coverage_completebooleanAudio only. Whether both Perth versions completed successfully.
item.metrics.has_watermarkobject | booleanPer-channel aggregate for audio; boolean for image/video.
item.metrics.confidencenumber | nullAudio aggregate confidence.
item.metrics.detection_scorenumber | nullImage/video detection score.
item.metrics.model_resultsobject[]Separate results for every checked model version.
item.metrics.synthidbooleanOptional auxiliary SynthID verdict for audio, image, or video. Omitted when SynthID is unavailable.
item.watermarked_medianullDetection does not produce a watermarked output file.

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:

1{
2 "success": false,
3 "error": "File must be valid media format"
4}

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