Dewatermark API
Remove watermarks from images and videos programmatically. Authenticate with your API key, send a request, and get a clean result back.
Get Started
Introduction
Hi, developers, welcome to use Dewatermark's API. The following are some basic introductions to your access service. Hope you can find the AI technology capabilities that are suitable for your business here. Thank you for using!
Authentication
Dewatermark uses API keys to allow access to the API. You can receive your unique API key by signing up and opening the API management page.
The API key must be included in all API requests to the server in a header that looks like the following:
X-API-KEY: API_KEY
You must replace API_KEY with your personal API key. Your personal API key can be obtained from the API management interface.
<API-KEY> with your API key.# With shell, you can just pass the correct header with each request
curl "https://platform.dewatermark.ai/api/object_removal/v3/erase_watermark" \
-H "X-API-KEY: <API-KEY>"bashWatermark Removal
Remove Watermark
/api/object_removal/v3/erase_watermark), which provides better results for high resolution images.This API allows you to remove watermark from an image and seamlessly inpaint the erased area to blend it naturally with the surrounding background. Each remove watermark image API call is counted as 1 credit.
Request body
| Form | Required | Type | Description |
|---|---|---|---|
original_preview_image | Optional | binary | The input image, it should be a JPEG image and the largest dimension is not greater than 6000 px. |
session_id | Optional | text | The session id, it represents the current image. |
mask_base | Optional | text | The masked image of the previously erased parts. |
mask_brush | Optional | binary | The mask image for the Remove Object API should include a binary representation of the unwanted object's outline, delineating the area to be removed and inpainted. |
remove_text | Optional | text | If set to 'true', enables the text removal feature for improved results when removing purely textual watermarks. Note that this may remove all text from your image. |
predict_mode | Optional | text | You can choose between "old" (2.0), "3.0", or "4.0". 2.0 works best for emoji, while 3.0 and 4.0 work for most cases. Its default value is 4.0. |
In the request form data, while either original_preview_image or session_id parameter is required, it is recommended to include session_id if it's already available. The initial request doesn't require mask_base and mask_brush.
Response
| Property | Description |
|---|---|
edited_image.image | The result after removing object, it's a base64 encoded image. |
edited_image.watermark_mask | This is the masked image of all previously erased parts. |
Continuing with Manual Refinement
Here's a complete example that demonstrates the watermark removal process with automatic detection and manual refinement. The process works as follows:






- Start with automatic watermark detection and removal
- If needed, perform manual corrections using brush masks
- Use
session_idfor subsequent refinements to optimize the process
The images show the progression from the original image through each step of the watermark removal process, including the manual masks used for refinement.
Even after the initial API call, you can achieve even more precise results by manually specifying the remaining watermark area you want to erase. Here's the process:
- Manual Selection: Define a mask that isolates the specific part of the image containing the remaining watermark or unwanted element. This mask acts as a guide for the API.
- API Call with Session ID and Mask: Make a subsequent API call to remove the designated area. Remember to include
original_preview_image(theedited_image.imagefrom the previous call, JPEG with largest dimension ≤ 1920),session_id(use this instead oforiginal_preview_imageon the second refinement),mask_brush(a refined mask of the remaining area), andremove_textwhen the watermark is purely text.
By following these steps, you can iteratively remove watermarks and achieve a highly refined final image.
curl -X POST "https://platform.dewatermark.ai/api/object_removal/v3/erase_watermark" \
-H "X-API-KEY: API_KEY" \
--form 'session_id="SESSION_ID"' \
--form 'original_preview_image=@"IMAGE_FILE"' \
--form 'mask_base=@"MASK_BASE_FILE"' \
--form 'mask_brush=@"MASK_BRUSH_FILE"' \
--form 'remove_text="true"' \
--form 'predict_mode="4.0"'bash{
"edited_image": {
"image": "BASE_64_IMAGE",
"image_id": "image_id",
"mask": "BASE64_MASK",
"watermark_mask": "BASE64_MASK"
},
"event_id": "event_id",
"session_id": "session_id"
}jsonRemove Watermark PRO
The PRO endpoint runs a higher-quality watermark removal model — best when you want the cleanest result in a single automatic call. Each PRO call is counted as 3 credits.
Request body
| Form | Required | Type | Description |
|---|---|---|---|
original_preview_image | Required | binary | The input image, it should be a JPEG image and the largest dimension is not greater than 6000 px. |
Response
| Property | Description |
|---|---|
edited_image.image | The result after removing the watermark, it's a base64 encoded image. |
curl --location 'https://platform.dewatermark.ai/api/object_removal/v1/erase_watermark_pro' \
--header 'X-API-KEY: YOUR_API_KEY' \
--form 'original_preview_image=@"/path/to/file"'bash{
"edited_image": {
"image": "BASE_64_IMAGE",
"image_id": "image_id"
},
"event_id": "event_id",
"session_id": "session_id"
}jsonVideo Watermark Removal
Video Watermark Removal
The Video Watermark Removal API allows you to remove watermarks from video files. The process involves four steps: generating an upload URL, uploading the video file, submitting the task, and polling for completion.
Video Requirements
Pricing
The credit cost is 0.5 credits per second, which equals approximately 1 credit for a 2-second video. Any failed or timeout tasks will result in a credit refund.
Step 1: Generate Upload URL
This endpoint generates a signed URL for uploading your video file and creates a task ID for tracking.
Response
| Property | Description |
|---|---|
task_id | Unique identifier for this video processing task |
upload_signed_url | Signed URL to upload your video file (valid for limited time) |
file_path | Internal storage path for the video |
status | Current status of the task (CREATED) |
created_at | Unix timestamp when the task was created |
curl --request POST \
--url https://platform.dewatermark.ai/api/video/v1/upload \
--header 'Content-Type: multipart/form-data' \
--header 'X-API-KEY: YOUR_API_KEY'bash{
"task_id": "yIuf8WVuRE2pzP2WM48v",
"upload_signed_url": "https://storage.googleapis.com/...",
"file_path": "dewatermark-videos-asia-southeast1-prod/yIuf8WVuRE2pzP2WM48v",
"status": "CREATED",
"push_notification_token": null,
"created_at": 1763794508
}jsonStep 2: Upload Video File
Upload your video file to the signed URL obtained in Step 1.
Important Notes
- Use HTTP PUT method (not POST)
- Set Content-Type header to
application/octet-stream - Send the video file as binary data
- For detailed information about using signed URLs, refer to Google Cloud Storage documentation
# Replace UPLOAD_SIGNED_URL with the URL from Step 1
curl --request PUT \
--url "UPLOAD_SIGNED_URL" \
--header 'Content-Type: application/octet-stream' \
--data-binary '@/path/to/your/video.mp4'bashStep 3: Submit Task
Submit the task for processing after the video upload is complete.
Request Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
task_id | Yes | string | The task ID obtained from Step 1 |
mask_brush | No | Binary File | Mask image to help AI focus on removing specific regions only, improving speed and accuracy |
mask_brush is optional, it helps AI focus on removing specific regions only, improving speed and accuracy. The mask should be the same size as the video input, it's a PNG image like the sample below.

curl --request POST \
--url https://platform.dewatermark.ai/api/video/v1/tasks \
--header 'Content-Type: multipart/form-data' \
--header 'X-API-KEY: YOUR_API_KEY' \
--form 'task_id=yIuf8WVuRE2pzP2WM48v' \
--form 'mask_brush=@mask_brush_file'bashStep 4: Poll Task Status
Poll this endpoint to check the status of your video processing task.
Response
| Property | Description |
|---|---|
task_id | Unique identifier for the task |
status | Current status (CREATED, PROCESSING, COMPLETED, FAILED) |
progress | Processing progress (0 to 1) |
has_watermark | Whether watermark was detected in the video |
duration | Video duration in seconds |
created_at | Unix timestamp when task was created |
started_at | Unix timestamp when processing started |
completed_at | Unix timestamp when processing completed |
download_signed_url | Signed URL to download the processed video (valid for 2 days) |
file_path | Internal storage path |
instance_name | Processing instance name |
download_signed_url is valid for 2 days from task completion. Use this URL to download your processed video file.Status Values
| Status | Description |
|---|---|
CREATED | Task has been created but not yet submitted |
PROCESSING | Video is being processed |
COMPLETED | Processing completed successfully, video is ready for download |
FAILED | Processing failed, credits will be refunded |
curl --request GET \
--url https://platform.dewatermark.ai/api/video/v1/tasks/yIuf8WVuRE2pzP2WM48v \
--header 'X-API-KEY: YOUR_API_KEY'bash{
"created_at": 1763794508,
"task_id": "yIuf8WVuRE2pzP2WM48v",
"has_watermark": true,
"instance_name": "snapedit-dewatermark-video-prod-northeast3-zrtv",
"progress": 1,
"file_path": "dewatermark-videos-asia-southeast1-prod/yIuf8WVuRE2pzP2WM48v",
"completed_at": 1763794728,
"upload_signed_url": "https://storage.googleapis.com/...",
"push_notification_token": null,
"duration": 51.3,
"status": "COMPLETED",
"download_signed_url": "https://storage.googleapis.com/...",
"started_at": 1763794550
}jsonComplete Workflow Example
The full end-to-end example below chains all four steps: generate the upload URL, upload the video, submit the task, then poll until it is COMPLETED and download the result.
# The full workflow is a sequence of the 4 requests above:
# 1. POST /api/video/v1/upload -> get task_id + upload_signed_url
# 2. PUT <upload_signed_url> -> upload the .mp4 (octet-stream)
# 3. POST /api/video/v1/tasks -> submit task_id
# 4. GET /api/video/v1/tasks/{id} -> poll until COMPLETEDbashPDF Watermark Removal
PDF Watermark Removal
Process a PDF asynchronously: request an upload URL, upload the file, start a task, then poll for the result.
How it works
- Request an upload URL — get a
task_idand a signed upload URL. - Upload the PDF —
PUTthe file directly to the signed URL. - Start the task — submit the
task_idto begin processing. - Poll for the result — check the task status until it finishes.
Credits & pricing
Cost is based on the number of pages in the PDF: credits = ceil(pages × 0.1) — in other words, 1 credit per 10 pages, rounded up. Any partial block of 10 pages costs a full credit.
| Pages | Credits |
|---|---|
| 1–10 | 1 |
| 11–20 | 2 |
| 15 | 2 |
| 21–30 | 3 |
| 100 | 10 |
| 300 (max) | 30 |
- Credits are deducted only when the task is successfully started (Step 3).
- If a task ends in
FAILED, the credits are automatically refunded. - The maximum allowed size is 300 pages per PDF.
Step 1: Request an Upload URL
Creates a task and returns a pre-signed URL to upload your PDF to.
Response
| Property | Description |
|---|---|
task_id | Unique identifier for this PDF task |
upload_signed_url | Signed URL to upload your PDF file to |
file_path | Internal storage path for the PDF |
status | Current status of the task (CREATED) |
created_at | Unix timestamp when the task was created |
Keep the task_id and upload_signed_url for the next steps.
curl --location --request POST 'https://platform.dewatermark.ai/api/pdf/v1/upload' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data ''bash{
"task_id": "abc123",
"upload_signed_url": "https://storage.googleapis.com/...",
"file_path": "...",
"status": "CREATED",
"created_at": 1718600000
}jsonStep 2: Upload the PDF
Upload the raw PDF bytes directly to the signed URL returned above. This request does not go to the API base URL and does not need the X-API-KEY header.
Important Notes
- Use HTTP PUT method (not POST)
- Set Content-Type header to
application/pdf - Send the PDF file as binary data
200 OK with an empty body means the upload succeeded.# Replace UPLOAD_SIGNED_URL with the URL from Step 1
curl --location --request PUT 'UPLOAD_SIGNED_URL' \
--header 'Content-Type: application/pdf' \
--data-binary '@document.pdf'bashStep 3: Start the Task
Begins processing the uploaded PDF. The task_id must be sent as multipart form data.
Request Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
task_id | Yes | string | The task ID obtained from Step 1 |
200 here means the job was accepted and started, not that it is finished. Proceed to polling.Possible errors
| Status | Meaning |
|---|---|
400 | Missing task_id, or the PDF exceeds the page limit (max 300 pages). |
403 | No credit available. |
429 | Insufficient balance for this PDF's page count. |
curl --location --request POST 'https://platform.dewatermark.ai/api/pdf/v1/tasks' \
--header 'X-API-KEY: YOUR_API_KEY' \
--form 'task_id=TASK_ID'bash{ "task_id": "abc123" }jsonStep 4: Poll for the Result
Returns the current state of the task. Poll periodically (e.g. every few seconds) until status is SUCCESS or FAILED.
Status Values
| Status | Meaning |
|---|---|
CREATED | Task is queued or in progress — keep polling. |
SUCCESS | Done. The processed PDF is available at the result URL. |
FAILED | Processing failed. Credits charged for this task are automatically refunded. |
curl --location 'https://platform.dewatermark.ai/api/pdf/v1/tasks/TASK_ID' \
--header 'X-API-KEY: YOUR_API_KEY'bash{ "task_id": "abc123", "status": "CREATED" }jsonAccount
Tracking Credit Balance
You can use this API to get the credit balance.
Response
| Property | Description |
|---|---|
status | Status of the request |
data.available_credit | Your current available credit balance |
data.user_id | Your user ID |
curl --request GET \
--url https://platform.dewatermark.ai/api/creditInfo \
--header 'X-API-KEY: YOUR_API_KEY'bash{
"status": "OK",
"data": {
"available_credit": 1000,
"user_id": "user_id"
}
}jsonReference
Errors
| Error Code | Meaning |
|---|---|
| 400 | Bad Request — Your request is invalid. |
| 401 | Unauthorized — Your API key is wrong. |
| 500 | Internal Server Error — We had a problem with our server. Try again later. |
| 503 | Service Unavailable — We're temporarily offline for maintenance. Please try again later. |