Prerequisites
- A BIZ MORI API key (get one here)
- An image or PDF file to watermark (
jpg,jpeg,png,webp,bmp,tif,tiff, orpdf)
Use the automatically issued
sk_test_ key to exercise the whole v3 flow without running watermark processing or consuming credits. Test orders complete about five seconds after the upload, and their download URLs return a fixed sample file instead of your watermarked output. Use a live API key when you need an actual watermarked file.How it works
- Create an order with the file names and the watermark texts for each file.
- Upload each file with
PUTto the presigneduploadUrlin the response. Processing starts automatically once every file is uploaded — there is no confirm step. - Wait for the order to finish by polling
GET /api/v3/orders/{orderId}or by receiving a webhook. - Download the results: one call returns a URL for each output file and one URL for all of them.
Step 1: Create an order
Create a watermark embed order. Each file takes 1 to 10 watermark texts, and each text produces its own output file and uses 1 credit. The request below embeds two texts into one image, so it creates two output files and uses 2 credits.files[]follows the order offilesin your request. Usefiles[i].uploadUrlto upload the file you sent asfiles[i].outputs[]has one entry per watermark text. ItsfileIdvalues (such as501-1) appear only in this create response. The order details and the download response identify output files with numericfileIdvalues instead.expiresAtis when the order files are deleted. Download your results before then.
Reuse the same
idempotencyKey only when you retry the same request. It returns the existing order instead of creating a new one. The same key with a different request body returns 409 WATERMARK_V2_CONFLICT.Step 2: Upload files
PUT each file to its presigneduploadUrl. This is a direct upload to storage — no Authorization header needed.
Send a Content-Type header that matches the file extension. The presigned URL is signed for that type, so any other value is rejected.
No confirm step needed. Processing starts automatically once every file in the order is uploaded.
A live
uploadUrl expires after 900 seconds. If it expires, call GET /api/v3/orders/{orderId} to receive a fresh inputFiles[].uploadUrl for each file that is still waiting for upload. Upload every file within 12 hours of creating the order, or the order becomes failed. Test keys receive https://api.bizmori.com/api/v2/test-uploads/{signedToken} instead, valid for 1 hour; it accepts the same unauthenticated PUT and discards the file contents.Step 3: Wait for the order to finish
Poll the order untilstatus is complete, or set up webhooks to receive order.watermarkEmbed.completed or order.watermarkEmbed.failed instead of polling.
When the order is
complete, result.outputFiles[] lists one output file per watermark text. The order details have the same shape for every order type; see Get order details for every field.
processingDelayed is true, automatic retries are exhausted and the order is waiting for manual recovery. It stays inProgress, so keep polling or wait for the webhook.
The order.watermarkEmbed.failed webhook includes an errorCode that explains why the order failed. See Webhooks for the event payloads and error codes.
Step 4: Download the results
Oncestatus is complete, request the download URLs. One call returns a URL for each output file in files[] and one URL for all results in archiveUrl. If the order has one output file, archiveUrl points to that file; if it has several, it points to a ZIP archive.
files[]lists the same output files in the same order asresult.outputFiles[], with the samefileIdvalues. Match them byfileIdto see which watermark text each file carries.- The URLs are valid for up to 3600 seconds, or less if the retention period ends sooner. Request new URLs each time you download instead of storing them. After
expiresAt, this endpoint returns400 ORDER_EXPIRED.
For a test order,
archiveUrl and files[] point to fixed sample files (a ZIP when the order has several outputs). The samples are not your watermarked files.Full React example
Everything above, wired into one component: single-file upload with progress, a watermark text list with add/remove and duplicate detection, backoff polling, and a download button that fetches a fresh URL on each click. No dependencies beyond React.WatermarkEmbedUploader.jsx
import.meta.env.VITE_MORI_API_KEY is Vite’s syntax. Use process.env.NEXT_PUBLIC_MORI_API_KEY on Next.js, or whatever your bundler exposes to client code. crypto.randomUUID() needs a secure context: HTTPS and localhost are fine, a plain-HTTP LAN address is not.Error handling
For the complete error code reference, see Error Codes.
Migrating from v2 to v3
The v3 request body has the same shape as v2, so most integrations only change the endpoint paths and how they read results.
Things that stay the same: images and PDFs can be mixed in one order,
originalFileUrl still skips the upload for hosted files, and processing still starts without a confirm call.
After v2 support ends (from 09:00 KST on October 9, 2026, which is 00:00 UTC):
- Authentication and permission checks still run first, so
401and403errors are returned as before. - Authenticated requests to the v2 watermark embed and extract endpoints return
410 Gonewith{ "code": "WATERMARK_V2_API_SUNSET" }, for both live andsk_test_keys. TheLinkheader points to the v3 endpoint. Create new orders with v3. - v2 orders that have not started processing by then fail without being processed. The order details (
errors.errorCode) and the failed webhook carryWATERMARK_V2_API_SUNSETwith a message pointing to v3. The order is not charged, and its credits are restored. - Orders already processing at that time finish and record their result. No new run starts for them afterwards.
- You can still get existing v2 orders and download results and reports that were already created, within the existing retention period. New v2 reports cannot be created or regenerated.
Deprecation: true, Sunset: Fri, 09 Oct 2026 00:00:00 GMT, and Link headers.
Next steps
Watermark Extract
Check a file for a watermark and create a report.
Test API keys
Exercise the v3 flow without consuming credits.
Webhooks
Get notified when processing completes.
API reference
See every field of the v3 watermark embed endpoint.