WaterMark™ Developers — free REST API & webhooks

Developers

Your data. Your API. Included free.

Every WaterMark plan includes a read API, incremental export feeds, and signed webhooks — no setup fee, monthly add-on, or per-call charge. Pull customers, visits, invoices, and payment-ledger rows into the tools you run; use a deliberately scoped connector for two safe office actions.

$0 — on every plan REST + JSON Signed webhooks Keys you control

Quickstart

Two minutes from zero to your customer list.

  • 1. Mint a key. In the office dashboard, open Settings → API keys (owner accounts only), name it (e.g. "Zapier"), and create. The full key — wk_… — is shown exactly once; we store only its hash, so copy it right away.
  • 2. Call the API. Send it as a Bearer token:
curl https://watermarkapp.online/api/v1/customers \
  -H "Authorization: Bearer wk_YOUR_KEY"
# Python
import requests
r = requests.get("https://watermarkapp.online/api/v1/customers",
                 headers={"Authorization": "Bearer wk_YOUR_KEY"}, timeout=15)
print(r.json()["data"])
// Node
const r = await fetch("https://watermarkapp.online/api/v1/customers", {
  headers: { Authorization: "Bearer wk_YOUR_KEY" },
});
console.log((await r.json()).data);

Authentication & limits

  • Header: Authorization: Bearer wk_… on every request. A missing, malformed, or revoked key returns 401.
  • Rate limit: 120 requests per minute per key. Over budget returns 429 — back off and retry.
  • Scope: every key starts with read only and sees only your company's data. An owner may explicitly add the automation scope for the two documented Zapier actions; it does not grant invoice, job, payment, or customer creation.
  • Key hygiene: secrets are stored as SHA-256 hashes (never retrievable), every key shows its last-used time in the dashboard, and revocation is instant and permanent. Rotate by minting a new key and revoking the old one.

Short-lived client credentials

Low-code and server integrations may exchange the displayed key prefix (client ID) plus the one-time key (client secret) for a short-lived access token (15 minutes by default — the response's expires_in is authoritative). Revoking the backing key invalidates that token immediately.

curl -u "wk_PREFIX:wk_FULL_KEY" \
  -d "grant_type=client_credentials&scope=read" \
  https://watermarkapp.online/api/v1/oauth/token

The response contains access_token, token_type: "Bearer", expires_in, and the granted scope. API access tokens are purpose-bound and cannot sign in to the WaterMark office.

Endpoints

GET/api/v1/customers

Your customer list, oldest first.

{
  "id": 42,
  "name": "Rivera, Dana",
  "address": "18 Lakeview Dr, Denville, NJ 07834",
  "phone": "9735550142",
  "email": "dana@example.com",
  "state": "NJ",
  "tags": ["weekly", "gate-code"],
  "credit_balance": 0.0
}
GET/api/v1/jobs

Service visits, newest first.

{
  "id": 9310,
  "pool_id": 57,
  "customer_id": 42,
  "technician_id": 3,
  "status": "complete",
  "scheduled_date": "2026-07-10",
  "completed_at": "2026-07-10T18:22:41+00:00"
}
GET/api/v1/invoices

Invoices, newest first — amounts, payments, balance, and tax, straight from the ledger.

{
  "id": 5120,
  "customer_id": 42,
  "job_id": 9310,
  "amount": 145.00,
  "amount_paid": 145.00,
  "balance": 0.0,
  "tax": 9.02,
  "status": "paid",
  "description": "Weekly service — July",
  "created_at": "2026-07-10T18:23:05+00:00",
  "paid_at": "2026-07-11T14:02:33+00:00"
}
GET/api/v1/payments

Immutable money-in ledger rows. Processor identifiers and internal reconciliation notes are deliberately omitted.

{
  "id": 8122,
  "customer_id": 42,
  "invoice_id": 5120,
  "amount": 145.00,
  "method": "card",
  "created_at": "2026-07-11T14:02:33Z",
  "modified_on": "2026-07-11T14:02:33Z"
}
Broad writes stay intentionally closed. The optional automation scope can create an office follow-up task or append a non-access customer note. Creating customers, jobs, invoices, payments, and schedule changes remains unavailable through the public API.

Incremental export feeds

GET/api/v1/export/{resource}

Use customers, jobs, invoices, or payments. Start with an optional ?modified_after=<ISO-8601>&limit=100, follow next_cursor while has_more is true, then persist the final checkpoint for your next poll.

  • A signed high-water mark freezes each page walk, so records changed during a long export are picked up on the next poll instead of skipped.
  • limit defaults to 100 and is capped at 500. Cursors are bound to one company and one resource.
  • Current-state feed: it returns records that still exist and does not emit deletion tombstones. Run a periodic full reconciliation if your destination must detect hard-deleted records.

Webhooks

Push, not poll. Register an HTTPS endpoint in the dashboard and WaterMark POSTs you a signed JSON envelope the moment things happen — the exact pattern Zapier's and Make's webhook triggers consume directly.

Events

Webhook event types
EventFires when…
customer.createda new customer is added
job.completeda tech completes a visit
job.rescheduleda visit moves to a new date
job.skippeda visit is skipped (with the reason)
invoice.paidan invoice is fully paid
payment.receivedmoney lands on an invoice
lead.createda booking-page lead arrives
estimate.approveda customer approves a quote
review.receiveda customer leaves a review
agreement.signeda service agreement is signed

Delivery & verification

  • Each delivery carries X-WaterMark-Event (the event name) and X-WaterMark-Signature — an HMAC-SHA256 hex digest of the raw request body using your webhook's secret. Verify it before trusting the payload.
  • The JSON body is an envelope with the event's fields nested under data: {"event": "...", "sent_at": "<ISO timestamp>", "org_id": 123, "data": {…event fields…}}. Read body.data.invoice_id, not body.invoice_id.
  • At-least-once: failed deliveries are persisted and retried on a backoff ladder (five attempts over roughly four days), and the office can replay any delivery manually. Retries of the same delivery carry X-WaterMark-Delivery-Id — dedupe on it.
  • Respond with any 2xx quickly; do your processing async.
# Python — verify the signature
import hmac, hashlib

def verify(secret: str, raw_body: bytes, signature: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature or "")
// Node — verify the signature
const crypto = require("node:crypto");

function verify(secret, rawBody, signature) {
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature || ""));
}

Zapier / Make triggers in 60 seconds

  • In Zapier, add a Webhooks by Zapier → Catch Hook trigger (in Make, a Custom webhook) and copy its URL.
  • In WaterMark, register that URL as a webhook and pick the events you want.
  • Done — job.completed can append to a Sheet, invoice.paid can post to Slack, lead.created can drop into your CRM.

A connector can register the same trigger rail through POST /api/v1/zapier/subscriptions and stop only its own subscription through DELETE /api/v1/zapier/subscriptions/{id}. Both require an API key with the explicit automation scope and an Idempotency-Key header.

Minimal Zapier actions

These are the only public writes. Each requires the automation scope plus a stable Idempotency-Key; replaying the same key returns the first result without a second effect.

POST/api/v1/zapier/actions/tasks

Create a visible office follow-up task, optionally linked to an in-company customer, job, invoice, or business unit.

{
  "title": "Follow up on heater quote",
  "priority": "high",
  "category": "follow_up",
  "customer_id": 42
}
POST/api/v1/zapier/actions/customer-notes

Append a general, service, or billing note. Automation keys cannot write gate codes or access instructions.

{
  "customer_id": 42,
  "body": "Customer requested a Friday callback",
  "kind": "general"
}

Use GET /api/v1/zapier/catalog to discover the live trigger, action, and starter-template contract instead of hard-coding marketing copy.

What it costs

Nothing. The API and webhooks are included on every WaterMark plan — no activation fee, no monthly API add-on, no per-call metering. Many pool platforms gate API access behind higher tiers or charge for it (verify each vendor's current pricing). We think your data is yours, full stop.

Fair-use note: the 120 req/min per-key budget exists so one integration can't slow the app for your crew. Building something bigger? Talk to us — we'll work with you.