Authentication

TextWatermark uses two separate authentication layers depending on what you're doing.

Layer Token type Used for
User JWT Bearer <jwt> Account management, credits, tokens, subscription — /api/auth/*, /api/v2/users/*
API Token Bearer Watermark encode/decode calls — /api/watermark/*, MCP server

1. User Authentication (JWT)

User JWTs are short-lived access tokens issued on login. They authenticate calls to account management endpoints. You don't need to handle this manually if you use the dashboard — it manages tokens in the browser automatically.

Registration & email verification

# 1. Register
curl -X POST https://textwatermarking.com/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "yourpassword"}'

# → Check your inbox for a verification link, then click it (or hit the URL directly):
# GET https://textwatermarking.com/api/auth/verify-email?token=<token>

Login

curl -X POST https://textwatermarking.com/api/auth/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{"email": "[email protected]", "password": "yourpassword"}'

# Response:
# {
#   "accessToken": "eyJhbGci...",   ← valid for 2 hours
#   "user": { "id": "...", "plan": "pro", ... }
# }
# A httpOnly refresh token cookie is also set automatically.

Using the access token

curl https://textwatermarking.com/api/v2/users/me \
  -H "Authorization: Bearer eyJhbGci..."

Refreshing the access token

When the access token expires (after 2 hours), use the refresh token cookie to get a new one — no re-login required.

curl -X POST https://textwatermarking.com/api/auth/refresh \
  -b cookies.txt \
  -c cookies.txt

# Response: { "accessToken": "eyJhbGci..." }  ← fresh 2-hour token

Logout

curl -X POST https://textwatermarking.com/api/auth/logout \
  -b cookies.txt \
  -H "Authorization: Bearer eyJhbGci..."

# Revokes the refresh token. The access token expires naturally after 2h.

2. API Token Authentication

API tokens authenticate watermark calls. They are long-lived, scoped by permission (encode / decode), and optionally linked to a signing channel for keyed watermarking.

Creating an API token

Create tokens from your dashboard or via API (requires a valid user JWT):

curl -X POST https://textwatermarking.com/api/v2/tokens \
  -H "Authorization: Bearer <user-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My encode bot",
    "permissions": ["encode"],
    "signing_channel_id": null
  }'

# Response:
# {
#   "token": "a3f8e2b1c9d47f6a2b5c8d1e9f3a4b7c...",   ← shown ONCE, store it securely
#   "id": "...",
#   "name": "My encode bot",
#   "token_prefix": "mcp_a3f8e2b1"
# }

Important: The full token value is shown only once at creation time. Store it in an environment variable immediately — it cannot be retrieved again. If lost, revoke and create a new one.

Using an API token

curl -X POST https://textwatermarking.com/api/watermark/encode \
  -H "Authorization: Bearer a3f8e2b1c9d47f6a..." \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The quick brown fox jumps over the lazy dog",
    "secret": "owner-id-42"
  }'

Token permissions

Permission Allowed endpoints Typical use case
encode /encode, /encode-robust Content creation pipeline, LLM agent inserting watermarks
decode /decode, /decode-robust Verification pipeline, plagiarism detection bot
encode + decode All watermark endpoints MCP server, general-purpose integration

MCP server usage

The published MCP server uses an API token directly — no JWT required:

# In your MCP config (e.g. Claude Desktop)
{
  "mcpServers": {
    "textwatermarking": {
      "command": "npx",
      "args": ["@textwatermarking/mcp-server", "--token", "a3f8e2b1c9d47f6a..."]
    }
  }
}

Revoking a token

curl -X DELETE https://textwatermarking.com/api/v2/users/tokens/<token-id> \
  -H "Authorization: Bearer <user-jwt>"

3. Security Best Practices

  • Store API tokens in environment variables — never hardcode them in source code or commit them to git.
  • Use the minimum required permission — give encode-only tokens to pipelines that only write watermarks; separate decode tokens for verification.
  • Revoke compromised tokens immediately — from your dashboard or via DELETE /api/v2/users/tokens/:id. Revocation is instant.
  • Never expose tokens client-side — proxy all watermark calls through your own backend if you need to call from a browser.
  • Use signing channels for sensitive content — keyed watermarks can only be decoded through your channel, adding an ownership verification layer.

4. Authentication Errors

Status Meaning Fix
401 Missing, invalid, or expired token Check the Authorization header; refresh JWT if expired
403 Token valid but insufficient permissions, or account suspended Use a token with the correct permission (encode/decode); contact support if suspended
402 Valid token but no credits remaining Top up credits or upgrade plan; response includes a checkout_url

See the Error Handling page for the full list of error codes and response shapes.