# API reference All endpoints are under https://api.watermark.ws. Send JSON bodies and your key in the `Authorization` header. Processing endpoints answer `202 Accepted` with a request in status `queued`; read it with `GET /v1/requests/{id}`, or receive its webhook. The same reference as an OpenAPI 3.1 spec: https://api.watermark.ws/openapi.json. Headers on every processing endpoint: | Name | Type | Required | Description | | --- | --- | --- | --- | | `Authorization` | header | yes | `Bearer wm_live_…` or `Bearer wm_test_…`. See [Authentication](https://api.watermark.ws/docs/authentication.md). | | `Idempotency-Key` | header, up to 255 characters | no | Makes a retry safe: the same key with the same body returns the first request instead of starting another. See [Idempotency](https://api.watermark.ws/docs/requests.md#idempotency). | ## The request object What every processing endpoint returns, and what `GET /v1/requests/{id}` and webhooks carry. | Name | Type | Description | | --- | --- | --- | | `id` | integer | The request's id. | | `object` | string | Always `request`. | | `endpoint` | string | Which endpoint started it, such as `images/process`. | | `status` | string | Where the request is. Only `succeeded` is charged. One of: `queued`, `processing`, `succeeded`, `failed`, `aborted`. | | `livemode` | boolean | `false` for a test key's request. | | `source` | string | The URL the file was downloaded from. | | `input` | object | What was sent besides the source: operations, output and the endpoint's own fields. | | `progress` | integer, 0 to 100 | How far a video has got while it is processing. | | `result` | object | Once succeeded. | | `result.data` | object | About the output: dimensions and format for images, duration and codec for videos, pages and size for PDFs. | | `result.files` | array | The files made. Read endpoints make none. | | `result.files[].url` | URL | A signed link to download the file. | | `result.files[].url_expires_at` | timestamp | When the link stops working: when the result is deleted. | | `result.files[].format` | string | The file format, such as `webp`. | | `result.files[].size` | integer or null | Bytes. | | `result.deleted_at` | timestamp | When the files are deleted, 7 days after the request finished. | | `error` | object | Once failed. See [Errors](https://api.watermark.ws/docs/errors.md#a-request-that-fails-while-processing). | | `error.code` | string | Stable; branch on it. | | `error.message` | string | For people. | | `price` | Money object | An amount of money. | | `price.amount` | string | Dollars, six decimals. | | `price.currency` | string | Always `usd`. | | `price.micro_usd` | integer | Millionths of a dollar. | | `customer` | string | As sent. | | `metadata` | object | As sent. | | `created_at` | timestamp | When the request was accepted. | | `completed_at` | timestamp | When it finished. | ```json { "id": 1234, "object": "request", "endpoint": "images/process", "status": "succeeded", "livemode": true, "source": "https://example.com/photo.jpg", "result": { "data": { "width": 1600, "height": 1067, "format": "WEBP", "size": 183021 }, "files": [ { "url": "https://api.watermark.ws/v1/results/1234?expires=1792335604&signature=…", "url_expires_at": "2026-10-18T15:00:04Z", "format": "webp", "size": 183021 } ], "deleted_at": "2026-10-18T15:00:04Z" }, "price": { "amount": "0.002000", "currency": "usd", "micro_usd": 2000 }, "customer": "cus_42", "created_at": "2026-10-11T15:00:00Z", "completed_at": "2026-10-11T15:00:04Z" } ``` ## The event object Posted to `webhook_url` when a request finishes, signed in the `Watermark-Signature` header. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | Name | Type | Description | | --- | --- | --- | | `id` | string | The same on every retry of a delivery. Use it to ignore a repeat. | | `object` | string | Always `event`. | | `type` | string | What happened. One of: `request.succeeded`, `request.failed`, `request.aborted`. | | `created` | integer | Unix time. | | `data` | Request object | | ```json { "id": "evt_1234_done", "object": "event", "type": "request.succeeded", "created": 1791738000, "data": { "id": 1234, "object": "request", "status": "succeeded", "result": { "…": "…" } } } ``` ## Errors Every error has one shape, and an HTTP status that matches its `type`. See [Errors](https://api.watermark.ws/docs/errors.md) for every code. | Status | Meaning | | --- | --- | | 401 | No key, or not a valid one. | | 402 | No credit left, or the endpoint needs an account that has paid. | | 404 | Not found on this account. | | 409 | A conflict: the request has finished, or the Idempotency-Key was used for another request. | | 422 | Invalid input, or a URL the API will not use. | | 429 | Too many requests a minute (rate_limited, see Retry-After), or too many of the account's requests running at once (concurrency_limited). | ```json { "error": { "type": "invalid_request", "code": "validation_failed", "message": "The operations.0.width field must be between 1 and 20000.", "param": "operations.0.width", "request_id": "1234" } } ``` ## Images JPEG, PNG, GIF, WebP, TIFF, BMP, HEIC and AVIF in; JPEG, PNG, WebP, GIF or TIFF out. ### POST /v1/images/process Process image. Run operations on an image, in order, and save the result. Price: $0.002 per request. Failed requests are free. Body parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | URL | yes | A public `http` or `https` URL of the file. See [Sources](https://api.watermark.ws/docs/requests.md#sources). | | `operations` | array of operations, 1 to 20 | yes | Run in order, top to bottom. Each is `{"type": …}` plus that operation's parameters. See [Operations](https://api.watermark.ws/docs/operations.md). | | `output` | object | no | How to save the result. | | `output.format` | string | no | The file format of the result. One of: `jpg`, `png`, `webp`, `gif`, `tif`. Default: `jpg`. | | `webhook_url` | URL | no | Where to post the request when it finishes. Defaults to the account's webhook, if set. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | | `customer` | string, up to 64 characters | no | Your own reference for who the request is for. Returned with it, and totalled by `GET /v1/usage?group_by=customer`. | | `metadata` | object, up to 20 keys | no | Up to 20 keys of your own, returned with the request and in its webhooks. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/images/process \ -H "Authorization: Bearer $WATERMARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": "https://example.com/photo.jpg", "operations": [ {"type": "resize", "width": 1600, "height": 1600}, {"type": "watermark", "image_url": "https://example.com/logo.png", "x": 40, "y": 40} ], "output": {"format": "webp"}, "customer": "cus_42" }' ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->images->process('https://example.com/photo.jpg', [ ['type' => 'resize', 'width' => 1600, 'height' => 1600], ['type' => 'watermark', 'image_url' => 'https://example.com/logo.png', 'x' => 40, 'y' => 40], ], [ 'output' => ['format' => 'webp'], 'customer' => 'cus_42', ]); ``` CLI: ```bash # Waits for the result; add --no-wait to return as soon as it is queued. watermark image process https://example.com/photo.jpg \ --op resize:width=1600,height=1600 \ --op watermark:image_url=https://example.com/logo.png,x=40,y=40 \ --format webp --customer cus_42 --out photo-watermarked.webp ``` Returns `202`: Accepted and queued. Returns `200`: The request first sent with this Idempotency-Key. ```json { "id": 1234, "object": "request", "endpoint": "images/process", "status": "queued", "livemode": true, "source": "https://example.com/photo.jpg", "created_at": "2026-10-11T15:00:00Z" } ``` Errors: 401, 402, 409, 422, 429. ### POST /v1/images/read Read image. Read dimensions, format, colorspace and orientation. Price: $0.0005 per request. Failed requests are free. Body parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | URL | yes | A public `http` or `https` URL of the file. See [Sources](https://api.watermark.ws/docs/requests.md#sources). | | `webhook_url` | URL | no | Where to post the request when it finishes. Defaults to the account's webhook, if set. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | | `customer` | string, up to 64 characters | no | Your own reference for who the request is for. Returned with it, and totalled by `GET /v1/usage?group_by=customer`. | | `metadata` | object, up to 20 keys | no | Up to 20 keys of your own, returned with the request and in its webhooks. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/images/read \ -H "Authorization: Bearer $WATERMARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": "https://example.com/photo.jpg" }' ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->images->read('https://example.com/photo.jpg'); ``` CLI: ```bash # Waits for the result; add --no-wait to return as soon as it is queued. watermark image read https://example.com/photo.jpg ``` Returns `202`: Accepted and queued. Returns `200`: The request first sent with this Idempotency-Key. ```json { "id": 1234, "object": "request", "endpoint": "images/read", "status": "queued", "livemode": true, "source": "https://example.com/photo.jpg", "created_at": "2026-10-11T15:00:00Z" } ``` `result.data` once it has succeeded: ```json { "frames": 1, "orientation": "Undefined", "format": "JPEG", "colorspace": "sRGB", "width": 900, "height": 600, "size": 97451 } ``` Errors: 401, 402, 409, 422, 429. ## Videos MP4, MOV, WebM, MKV, AVI, FLV, MPEG and MPEG-TS in; MP4 out. Needs an account that has bought credits. ### POST /v1/videos/process Process video. Run operations on a video, in order, and save an MP4. Reports `progress` while it runs. Price: $0.02 per started minute of video, accounts that have bought credits only. Failed requests are free. Body parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | URL | yes | A public `http` or `https` URL of the file. See [Sources](https://api.watermark.ws/docs/requests.md#sources). | | `operations` | array of operations, 1 to 20 | yes | Run in order, top to bottom. Each is `{"type": …}` plus that operation's parameters. See [Operations](https://api.watermark.ws/docs/operations.md). | | `output` | object | no | How to save the result. | | `output.format` | string | no | The file format of the result. One of: `mp4`. Default: `mp4`. | | `max_duration` | integer, 1 to 7200 | no | Only keep the first this many seconds. | | `webhook_url` | URL | no | Where to post the request when it finishes. Defaults to the account's webhook, if set. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | | `customer` | string, up to 64 characters | no | Your own reference for who the request is for. Returned with it, and totalled by `GET /v1/usage?group_by=customer`. | | `metadata` | object, up to 20 keys | no | Up to 20 keys of your own, returned with the request and in its webhooks. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/videos/process \ -H "Authorization: Bearer $WATERMARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": "https://example.com/clip.mp4", "operations": [ {"type": "watermark", "image_url": "https://example.com/logo.png", "x": 24, "y": 24} ], "webhook_url": "https://example.com/hooks/watermark" }' ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->videos->process('https://example.com/clip.mp4', [ ['type' => 'watermark', 'image_url' => 'https://example.com/logo.png', 'x' => 24, 'y' => 24], ], [ 'webhook_url' => 'https://example.com/hooks/watermark', ]); ``` CLI: ```bash # Waits for the result; add --no-wait to return as soon as it is queued. watermark video process https://example.com/clip.mp4 \ --op watermark:image_url=https://example.com/logo.png,x=24,y=24 \ --webhook https://example.com/hooks/watermark --out clip-watermarked.mp4 ``` Returns `202`: Accepted and queued. Returns `200`: The request first sent with this Idempotency-Key. ```json { "id": 1234, "object": "request", "endpoint": "videos/process", "status": "queued", "livemode": true, "source": "https://example.com/clip.mp4", "created_at": "2026-10-11T15:00:00Z" } ``` Errors: 401, 402, 409, 422, 429. ### POST /v1/videos/read Read video. Read dimensions, duration, codec, bitrate and frame rate. Price: $0.001 per request, accounts that have bought credits only. Failed requests are free. Body parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | URL | yes | A public `http` or `https` URL of the file. See [Sources](https://api.watermark.ws/docs/requests.md#sources). | | `webhook_url` | URL | no | Where to post the request when it finishes. Defaults to the account's webhook, if set. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | | `customer` | string, up to 64 characters | no | Your own reference for who the request is for. Returned with it, and totalled by `GET /v1/usage?group_by=customer`. | | `metadata` | object, up to 20 keys | no | Up to 20 keys of your own, returned with the request and in its webhooks. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/videos/read \ -H "Authorization: Bearer $WATERMARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": "https://example.com/clip.mp4" }' ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->videos->read('https://example.com/clip.mp4'); ``` CLI: ```bash # Waits for the result; add --no-wait to return as soon as it is queued. watermark video read https://example.com/clip.mp4 ``` Returns `202`: Accepted and queued. Returns `200`: The request first sent with this Idempotency-Key. ```json { "id": 1234, "object": "request", "endpoint": "videos/read", "status": "queued", "livemode": true, "source": "https://example.com/clip.mp4", "created_at": "2026-10-11T15:00:00Z" } ``` Errors: 401, 402, 409, 422, 429. ### POST /v1/videos/screenshot Screenshot video. Save one frame as an image. Price: $0.002 per request, accounts that have bought credits only. Failed requests are free. Body parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | URL | yes | A public `http` or `https` URL of the file. See [Sources](https://api.watermark.ws/docs/requests.md#sources). | | `seconds` | integer, 0 to 86400 | yes | Which moment, in seconds from the start. | | `output` | object | no | How to save the result. | | `output.format` | string | no | The file format of the result. One of: `jpg`, `png`. Default: `jpg`. | | `webhook_url` | URL | no | Where to post the request when it finishes. Defaults to the account's webhook, if set. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | | `customer` | string, up to 64 characters | no | Your own reference for who the request is for. Returned with it, and totalled by `GET /v1/usage?group_by=customer`. | | `metadata` | object, up to 20 keys | no | Up to 20 keys of your own, returned with the request and in its webhooks. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/videos/screenshot \ -H "Authorization: Bearer $WATERMARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": "https://example.com/clip.mp4", "seconds": 5, "output": { "format": "jpg" } }' ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->videos->screenshot('https://example.com/clip.mp4', 5, [ 'output' => ['format' => 'jpg'], ]); ``` CLI: ```bash # Waits for the result; add --no-wait to return as soon as it is queued. watermark video screenshot https://example.com/clip.mp4 \ --format jpg --seconds 5 --out clip-frame.jpg ``` Returns `202`: Accepted and queued. Returns `200`: The request first sent with this Idempotency-Key. ```json { "id": 1234, "object": "request", "endpoint": "videos/screenshot", "status": "queued", "livemode": true, "source": "https://example.com/clip.mp4", "created_at": "2026-10-11T15:00:00Z" } ``` Errors: 401, 402, 409, 422, 429. ## Documents PDF in and out. ### POST /v1/documents/process Process document. Run operations on every page of a PDF. Price: $0.004 per page. Failed requests are free. Body parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | URL | yes | A public `http` or `https` URL of the file. See [Sources](https://api.watermark.ws/docs/requests.md#sources). | | `operations` | array of operations, 1 to 20 | yes | Run in order, top to bottom. Each is `{"type": …}` plus that operation's parameters. See [Operations](https://api.watermark.ws/docs/operations.md). | | `max_pages` | integer, 1 to 2000 | no | Only keep the first this many pages. | | `webhook_url` | URL | no | Where to post the request when it finishes. Defaults to the account's webhook, if set. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | | `customer` | string, up to 64 characters | no | Your own reference for who the request is for. Returned with it, and totalled by `GET /v1/usage?group_by=customer`. | | `metadata` | object, up to 20 keys | no | Up to 20 keys of your own, returned with the request and in its webhooks. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/documents/process \ -H "Authorization: Bearer $WATERMARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": "https://example.com/contract.pdf", "operations": [ {"type": "watermark", "image_url": "https://example.com/logo.png", "x": 36, "y": 36, "diagonal_lines_color": "#c0c0c0", "diagonal_lines_opacity": 40} ] }' ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->documents->process('https://example.com/contract.pdf', [ ['type' => 'watermark', 'image_url' => 'https://example.com/logo.png', 'x' => 36, 'y' => 36, 'diagonal_lines_color' => '#c0c0c0', 'diagonal_lines_opacity' => 40], ]); ``` CLI: ```bash # Waits for the result; add --no-wait to return as soon as it is queued. watermark document process https://example.com/contract.pdf \ --op watermark:image_url=https://example.com/logo.png,x=36,y=36,diagonal_lines_color=#c0c0c0,diagonal_lines_opacity=40 \ --out contract-watermarked.pdf ``` Returns `202`: Accepted and queued. Returns `200`: The request first sent with this Idempotency-Key. ```json { "id": 1234, "object": "request", "endpoint": "documents/process", "status": "queued", "livemode": true, "source": "https://example.com/contract.pdf", "created_at": "2026-10-11T15:00:00Z" } ``` Errors: 401, 402, 409, 422, 429. ### POST /v1/documents/read Read document. Read the page count and page size. Price: $0.0005 per request. Failed requests are free. Body parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | URL | yes | A public `http` or `https` URL of the file. See [Sources](https://api.watermark.ws/docs/requests.md#sources). | | `webhook_url` | URL | no | Where to post the request when it finishes. Defaults to the account's webhook, if set. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | | `customer` | string, up to 64 characters | no | Your own reference for who the request is for. Returned with it, and totalled by `GET /v1/usage?group_by=customer`. | | `metadata` | object, up to 20 keys | no | Up to 20 keys of your own, returned with the request and in its webhooks. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/documents/read \ -H "Authorization: Bearer $WATERMARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": "https://example.com/contract.pdf" }' ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->documents->read('https://example.com/contract.pdf'); ``` CLI: ```bash # Waits for the result; add --no-wait to return as soon as it is queued. watermark document read https://example.com/contract.pdf ``` Returns `202`: Accepted and queued. Returns `200`: The request first sent with this Idempotency-Key. ```json { "id": 1234, "object": "request", "endpoint": "documents/read", "status": "queued", "livemode": true, "source": "https://example.com/contract.pdf", "created_at": "2026-10-11T15:00:00Z" } ``` Errors: 401, 402, 409, 422, 429. ### POST /v1/documents/snapshot Snapshot document. Render one page as an image. Price: $0.002 per request. Failed requests are free. Body parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | URL | yes | A public `http` or `https` URL of the file. See [Sources](https://api.watermark.ws/docs/requests.md#sources). | | `page` | integer, 1 to 2000 | no | Which page, from 1. Default: `1`. | | `output` | object | no | How to save the result. | | `output.format` | string | no | The file format of the result. One of: `jpg`, `png`. Default: `jpg`. | | `webhook_url` | URL | no | Where to post the request when it finishes. Defaults to the account's webhook, if set. See [Webhooks](https://api.watermark.ws/docs/webhooks.md). | | `customer` | string, up to 64 characters | no | Your own reference for who the request is for. Returned with it, and totalled by `GET /v1/usage?group_by=customer`. | | `metadata` | object, up to 20 keys | no | Up to 20 keys of your own, returned with the request and in its webhooks. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/documents/snapshot \ -H "Authorization: Bearer $WATERMARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": "https://example.com/contract.pdf", "page": 1, "output": { "format": "png" } }' ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->documents->snapshot('https://example.com/contract.pdf', 1, [ 'output' => ['format' => 'png'], ]); ``` CLI: ```bash # Waits for the result; add --no-wait to return as soon as it is queued. watermark document snapshot https://example.com/contract.pdf \ --format png --page 1 --out contract-page.png ``` Returns `202`: Accepted and queued. Returns `200`: The request first sent with this Idempotency-Key. ```json { "id": 1234, "object": "request", "endpoint": "documents/snapshot", "status": "queued", "livemode": true, "source": "https://example.com/contract.pdf", "created_at": "2026-10-11T15:00:00Z" } ``` Errors: 401, 402, 409, 422, 429. ## Requests Follow, list and abort requests. ### GET /v1/requests List requests. The account's requests, newest first. Query parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `limit` | integer, 1 to 100 | no | How many requests to return. Default: `20`. | | `before` | integer | no | Only requests older than this id. Pass the last id of a page to get the next one. | cURL: ```bash curl "https://api.watermark.ws/v1/requests?limit=20" \ -H "Authorization: Bearer $WATERMARK_API_KEY" ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $requests = $client->requests->list(20); ``` CLI: ```bash watermark requests --limit 20 ``` Returns `200`: A page of requests. ```json { "object": "list", "data": [ { "id": 1234, "object": "request", "endpoint": "images/process", "status": "succeeded", "livemode": true, "created_at": "2026-10-11T15:00:00Z" } ], "has_more": true } ``` Errors: 401, 422, 429. ### GET /v1/requests/{id} Get request. One request, with its result once it has succeeded. Download links in the result work until the result is deleted. Path parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The request's id. | cURL: ```bash curl https://api.watermark.ws/v1/requests/1234 \ -H "Authorization: Bearer $WATERMARK_API_KEY" ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->requests->get(1234); ``` CLI: ```bash watermark request get 1234 ``` Returns `200`: The request. ```json { "id": 1234, "object": "request", "endpoint": "images/process", "status": "succeeded", "livemode": true, "source": "https://example.com/photo.jpg", "result": { "data": { "width": 1600, "height": 1067, "format": "WEBP", "size": 183021 }, "files": [ { "url": "https://api.watermark.ws/v1/results/1234?expires=1792335604&signature=…", "url_expires_at": "2026-10-18T15:00:04Z", "format": "webp", "size": 183021 } ], "deleted_at": "2026-10-18T15:00:04Z" }, "price": { "amount": "0.002000", "currency": "usd", "micro_usd": 2000 }, "customer": "cus_42", "created_at": "2026-10-11T15:00:00Z", "completed_at": "2026-10-11T15:00:04Z" } ``` Errors: 401, 404, 429. ### GET /v1/results/{id} Download result. The link in `result.files[].url`: open it as given, with no key. It works until the result is deleted (`url_expires_at`) and redirects to the file. Anyone with the link can download the file. Query parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The request's id. | | `expires` | integer | yes | Part of the link. | | `signature` | string | yes | Part of the link. | cURL: ```bash curl -L -o photo-watermarked.webp "https://api.watermark.ws/v1/results/1234?expires=1792335604&signature=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" ``` PHP: ```php $request = $client->requests->get(1234); file_put_contents('photo-watermarked.webp', file_get_contents($request['result']['files'][0]['url'])); ``` CLI: ```bash # --out on a process command downloads the file for you; a link you already have is a plain download. curl -L -o photo-watermarked.webp "https://api.watermark.ws/v1/results/1234?expires=1792335604&signature=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" ``` Returns `302`: Redirects to the file. Errors: 403, 410. ### POST /v1/requests/{id}/abort Abort request. Stop a request that has not finished. It is not charged. Path parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The request's id. | cURL: ```bash curl -X POST https://api.watermark.ws/v1/requests/1235/abort \ -H "Authorization: Bearer $WATERMARK_API_KEY" ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $request = $client->requests->abort(1235); ``` CLI: ```bash watermark request abort 1235 ``` Returns `200`: The aborted request. One that has already finished is a `409 request_finished`. ```json { "id": 1235, "object": "request", "endpoint": "videos/process", "status": "aborted", "livemode": true, "source": "https://example.com/clip.mp4", "price": { "amount": "0.000000", "currency": "usd", "micro_usd": 0 }, "created_at": "2026-10-11T15:00:00Z", "completed_at": "2026-10-11T15:00:09Z" } ``` Errors: 401, 404, 409, 429. ## Account Balance, usage and the operation catalog. ### GET /v1/account Get account. The account behind the key: balance, tier, and the key's mode and limits. cURL: ```bash curl https://api.watermark.ws/v1/account \ -H "Authorization: Bearer $WATERMARK_API_KEY" ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $account = $client->account->get(); ``` CLI: ```bash watermark account ``` Returns `200`: The account. ```json { "object": "account", "id": 7, "name": "Acme Photos", "email": "dev@example.com", "tier": "paid", "balance": { "amount": "18.420000", "currency": "usd", "micro_usd": 18420000 }, "webhook_url": "https://example.com/hooks/watermark", "livemode": true, "limits": { "requests_per_minute": 120, "concurrent_requests": 10, "max_source_bytes": 2147483648 }, "suspended": false, "created_at": "2026-10-11T14:52:10Z" } ``` Errors: 401, 429. ### GET /v1/usage Get usage. Requests, spend and bytes over at most 92 days, grouped by day, endpoint, customer or status. Query parameters: | Name | Type | Required | Description | | --- | --- | --- | --- | | `from` | date | no | First day, `YYYY-MM-DD`. Defaults to 29 days ago. | | `to` | date | no | Last day, `YYYY-MM-DD`. Defaults to today. | | `group_by` | string | no | What each row totals. One of: `day`, `endpoint`, `customer`, `status`. Default: `day`. | | `customer` | string, up to 64 characters | no | Only this customer's requests. | cURL: ```bash curl "https://api.watermark.ws/v1/usage?from=2026-10-01&group_by=endpoint" \ -H "Authorization: Bearer $WATERMARK_API_KEY" ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $usage = $client->account->usage([ 'from' => '2026-10-01', 'group_by' => 'endpoint', ]); ``` CLI: ```bash watermark usage --from 2026-10-01 --group-by endpoint ``` Returns `200`: Usage. ```json { "object": "usage", "from": "2026-10-01", "to": "2026-10-13", "group_by": "endpoint", "data": [ { "endpoint": "images/process", "requests": 1840, "succeeded": 1822, "failed": 18, "spent": "3.644000", "spent_micro_usd": 3644000, "source_bytes": 912455120, "result_bytes": 301228873 } ] } ``` Errors: 401, 422, 429. ### GET /v1/operations List operations. Every operation, its parameters and the output formats, per media type: what a client needs to build requests. The same catalog, with pictures, is at https://api.watermark.ws/docs/operations. cURL: ```bash curl https://api.watermark.ws/v1/operations \ -H "Authorization: Bearer $WATERMARK_API_KEY" ``` PHP: ```php $client = new \Watermark\Api\Client(getenv('WATERMARK_API_KEY')); $catalog = $client->account->operations(); ``` CLI: ```bash watermark operations ``` Returns `200`: The catalog. The example shows one operation of one media type. ```json { "object": "operations", "data": { "image": { "formats": [ "jpg", "png", "webp", "gif", "tif" ], "operations": { "resize": { "description": "Resize to a width and height.", "params": { "width": { "description": "The width in pixels.", "required": true }, "height": { "description": "The height in pixels.", "required": true }, "preserve_aspect_ratio": { "description": "Fit inside the box instead of stretching to it.", "required": false, "default": true }, "crop_center": { "description": "Fill the box and crop what overflows, centered.", "required": false, "default": false } } } } } } } ``` Errors: 401, 429.