Privacy Policy
Last updated: 2 November 2026
Watchtower is operated by SHAJ Studio. This policy explains what data the application accesses, what it stores and what it does not.
1. What Watchtower is
Watchtower is a monitoring application for HighLevel agencies. It is installed once at agency level, reads configuration and activity signals from the agency's sub-accounts and reports problems by email and through a dashboard.
Watchtower is read-only. It never creates, changes or deletes anything in a customer's account or their clients' accounts. It does hold one write-type permission, used only to request read-only access to each sub-account (see section 5).
2. What we access
Watchtower requests permissions to read the data listed below, plus one permission it uses only to request read-only access to each sub-account. The agency approves these at install. Together they allow it to read:
- Sub-account configuration: workflows, custom values, custom fields, tags, pipelines, calendars, calendar bookings, users (we read the staff list and use only how many people are on it), phone numbers and number pools, business profile settings and the sub-account's own currency
- Forms, surveys and email campaign configuration and counts, and the delivery counts of scheduled and bulk email sends
- The list of sub-accounts installed under the agency, so new and removed sub-accounts are found
- Opportunities: pipeline stage, monetary value and creation date, to find leads that have sat unworked
- New contact (lead) arrival events. We read only the contact's ID and its attribution source (medium and session source), used to measure whether a new lead gets a first response. We hold read access to contacts so these events are delivered. We never request contact records from HighLevel
- Conversations: read and unread state, and, for a lead that may not have been followed up, the type, sender and time of outbound messages on that conversation, to check whether a real team member replied
- Tasks: whether a task exists for a contact and who it is assigned to, one of the signals checked for a newly arrived lead that hasn't had any response yet
- Message send and delivery outcomes, and, for a specific failed text message, the carrier error code that explains why it failed
- Payment transactions: whether each recent payment succeeded or failed, whether it ran in test mode and, for a failed payment, the error the payment processor reported
- Trigger links and domain redirects: their names and the web addresses they send visitors to, so we can check that those addresses still work
- Email delivery statistics, and the sending domain used for outbound email
- Conversation AI and Voice AI agents: whether an agent is switched off, which channels it responds on and its configured goals
- Voice AI call logs, to count how many calls each Voice AI agent has answered in the last 7 days. We use only the count. We never use call transcripts, summaries, caller details or any other call content
- Contact field definitions: the names and ids of built-in and custom fields on the contact record, used to confirm a Voice AI agent's own configured goal still points to a real field
- Social media account connections and post status
- Facebook and Google ad account connection status, to see whether its access has expired
- Snapshot push status to a sub-account
- Appointment and opportunity creation events
- Message and conversation activity events: inbound messages, unread-count changes on a conversation, contact tag changes and opportunity stage changes. We use the event type and identifiers only. Names, contact details and message text in these events are discarded before anything is written (see section 3)
- Sub-account creation, update and deletion events, so new, changed and removed sub-accounts are found at once
- The agency's own name, email and, where configured, whitelabel domain, used to personalize the dashboard and digest and to link to the agency's own branded login
- When the dashboard is opened inside HighLevel, the signed-in user's details from HighLevel's session (ID, name and email). We use the agency ID and the user type to confirm the request comes from an agency user. The user's ID, name and email are not stored or logged
The full list of permissions is shown on the consent screen before installation.
3. What we store
We store configuration metadata and event counts, not customer records.
Specifically, we store:
- Sub-account identifiers, names, timezone and business email
- The configuration values our checks examine, for example whether a workflow is published or whether a custom value is empty. For a custom value that still holds placeholder text, we store its name and the text itself, which is written by the agency
- A standard an agency has chosen to capture from one of its own sub-accounts, used to check others built from the same template
- Counts and outcomes derived from activity events, such as how many messages were sent and how many failed
- Findings we generate, including the finding text, when it was first seen, when it was resolved and, when an agency tells us a finding was wrong, the reason and any note they add. That note is free text the agency's own team writes. Findings are kept while Watchtower stays installed, including after they are resolved
- The names and details shown in findings, such as the names of forms, workflows, calendars, campaigns, pipelines, stages, AI agents, tags and custom fields, phone numbers, trigger link names and addresses, social account names, the error text from failed posts and payment error text
- The agency's HighLevel plan name, the ID of the snapshot a sub-account was built from, the ID of the app version HighLevel reports as installed on a sub-account and the domain the agency's team opens HighLevel from, used to build links to the setting that needs fixing
- Agency settings: digest recipients and whether each address can receive email, frequency, thresholds and which checks an agency has muted, including any free-text reason given
- A record of each digest sent and whether it was opened, to measure whether digests are useful
- For each nightly check of an agency, we record when it started, how long it took, how many sub-accounts it checked, how many failed and the lowest request allowance HighLevel reported as remaining. These records hold no contact or message data. Older records are removed as new ones are written. All of them are deleted with the agency's other data.
- When a digest recipient unsubscribes or reports a digest as spam, a keyed hash of their email address (not the address itself), so that address isn't added back to that agency's digest by mistake. It is deleted when the agency uninstalls
- The domain names used for outbound email, and the results of a public DNS lookup against each one (whether SPF, DKIM and DMARC records are present, and the DMARC policy set). We never store the full email address a message was sent from, only the domain
- For a failed text message, the message ID and the carrier error code it was classified under. We never store the carrier's raw error text, which can contain the recipient's own phone number
- For the leads-not-worked check, the opportunity ID and the date we last confirmed a real team member had followed up, so we do not re-check the same answered opportunity every night
- For a newly arrived lead, the contact ID and its attribution source (medium and session source), and nothing else about the contact: no name, email, phone number or message content. The same first-response check also reads the contact ID referenced by a new outbound message, appointment or opportunity, used only to confirm a response happened
- For payments that fail for the same setup reason (not a declined card), the error type, code and message the payment processor reported, and the name of the source the payment came from. We do not store the payer's name, card details or payment amounts
- For trigger links and domain redirects, the name, the address it sends visitors to and, when that address stops working, the reason (page not found, page removed or domain not found). Between checks we keep whether each address was dead on its last check and when we checked it. A finding about a link also keeps the link's name and address for as long as the finding is kept
- For each Voice AI agent, its name and the number of calls it answered in the last 7 days, shown on the dashboard. Nothing from the calls themselves is stored
- A short, stripped record of each activity event we receive (the event type, identifiers and the fields our checks read, never contact names, email addresses, phone numbers or message text). The exception is sub-account creation and update events, which also keep the sub-account's name and business email. While an agency is installed we delete these after 90 days at the latest. A small number of text-message delivery records, holding only message IDs and statuses, are kept longer where a check needs them to confirm that an earlier problem was fixed
- A short record of each webhook delivery we receive: when it arrived, the event type, the delivery ID, whether we accepted it and a short error if not. It is not linked to an agency and is deleted after 4 days at the latest
- For each email delivery event, the event type and severity (to classify a bounce), the message's own internal ID (to avoid double-counting repeated events for the same send), any campaign reference included in the event (empty on every real send we've observed so far) and five delivery flags describing whether the message passed sender authentication, was routed normally or was a system or test send
We do not store contact records or message content. Incoming webhook data is stripped before it is written: contact names, email addresses, phone numbers and the body text of emails and SMS messages are discarded and never persisted. What remains is the identifier and the fields our checks read. Webhook data passes through our network provider (Cloudflare) and our host (Railway) on its way to us.
Our server logs hold agency names, sub-account names, the email addresses of digest recipients and the visitor address of the first request after each restart. Our host keeps them for its own retention period. When an agency marks a finding not useful, the note, the finding text and the agency and sub-account names are also emailed to us so we can improve our checks. We also receive emails about how the service is running, for example when a check cannot run for an agency or when an account becomes inactive. These name the agency and sometimes its sub-accounts. We keep them in our own mailbox until we delete them by hand, and we delete those about an agency when it asks us to. Our email provider also keeps copies for its own retention period.
Message text and SMS error text are read into memory to make a decision and are never written to our database. The outbound-message and carrier-error-code checks above read directly from HighLevel at the moment a check runs, use only the specific field named (who sent it and when, or the error code), and discard everything else, including the message body and the raw error text, before anything is stored.
4. What we send by email
Watchtower emails a digest to the recipients an agency configures, daily by default, or weekly, or paused, at the hour the agency sets. It contains sub-account names and the findings we detected, and links to your Watchtower dashboard, where each finding links straight to the setting in HighLevel that needs fixing. A finding can include counts, deal value totals and names the agency has set up, such as forms, workflows, calendars, campaigns, pipelines, stages, AI agents, tags, custom fields, trigger links with their addresses, social accounts and sending domains. It can also include a phone number, the text of a custom value, a payment error message or the error text from a failed social post. It does not contain contact data or message content.
We also email the agency's recipients a notice when Watchtower loses access and needs to be reconnected.
Email is sent through Resend. Agencies choose their own recipients and can pause digests or stop all email at any time from the settings page. A reconnect notice is still sent while digests are paused, because monitoring has stopped until the connection is restored. Any recipient can also unsubscribe directly from a link included in every digest. If a recipient reports a digest as spam, we treat it as an unsubscribe from that agency's digests. If an address cannot receive email, we stop sending to it and mark it on the agency's settings page.
We record whether digest emails are opened, to measure whether they're useful.
5. Access credentials
OAuth tokens issued by HighLevel are encrypted at rest using AES-256-GCM. They are used only to make the read requests described above, and to request a read-only access token for each sub-account from the agency's own token.
6. Deletion
When you uninstall Watchtower from your agency, the agency's data is deleted from our database immediately. The exceptions are a small number of sub-account creation and update event records and a log of webhook deliveries that is not linked to any agency. A daily clean-up removes the event records after 90 days at the latest, and the delivery log is deleted after 4 days at the latest. A few short-lived records, such as server logs, delivery logs and copies of emails already sent, are kept by us or our providers for a limited time and expire according to each one's retention period. Our email provider, Resend, keeps its own list of addresses that hard-bounced or reported our email as spam, so nothing is sent to them again. That list is held by Resend and is not cleared when an agency uninstalls.
Our database host, Neon, keeps a restore history of 2 days. Encrypted backups are kept for up to 7 days, then deleted. They do not contain the stored webhook event records. Data deleted from our database can therefore remain in that history for up to 2 days and in an encrypted backup for up to 7 days before it is gone for good.
If a single sub-account is removed or uninstalled while the agency stays installed, we stop monitoring it and delete its access token. A daily clean-up deletes its stored findings, name and settings once 14 days have passed. If the sub-account is added back within those 14 days, its data is kept. If HighLevel tells us a sub-account was deleted, we delete its data straight away.
A later reinstall starts fresh.
If your HighLevel account becomes inactive, we pause monitoring and delete your data after 14 days unless the account becomes active again.
Agencies may also ask us to delete their data, or the data of one sub-account, at any time by emailing support@shajstudio.com from an address we hold for the agency. We confirm who is asking, delete the data and confirm back in writing. We aim to finish within 30 days of confirming the request.
7. Sub-processors
- Neon: database hosting
- Railway: application hosting and the scheduled backup job
- Cloudflare: network and security layer in front of the application, and visitor analytics on the public website pages, which Cloudflare describes as cookieless
- Cloudflare R2: storage for our encrypted database backups. The job that takes them reads the database while it runs and encrypts the backup before it is stored
- Resend: transactional email delivery
- HighLevel: the source system Watchtower reads from
- Public DNS: to check a sending domain's SPF, DKIM and DMARC records, Watchtower looks up that domain's public DNS records. Only the domain name is sent in the lookup.
We also keep a plain count of how many times each install button on our website is pressed, and how many times the install link a visitor emails to themselves is opened, per day. It holds no IP address, cookie or other visitor details. The email-yourself button only opens your own email app; the message you send does not come to us.
Link checks. To check that a trigger link or domain redirect still works, our servers send one web request to the address your agency configured, identifying itself as Watchtower-LinkChecker. We use only whether the address responded and never keep the page. We do not send these requests to private or internal network addresses.
The tour video on our website loads from YouTube (privacy-enhanced mode) only when a visitor presses play.
8. What we do not do
- We do not sell data
- We do not use customer data to train models
- We do not share data with advertisers
- We do not access accounts beyond those the installing agency has granted
9. Security
Data is transmitted over TLS. Tokens are encrypted at rest. Database backups are encrypted before they are stored, and the key that opens them is not kept with them. Access to the dashboard requires a signed token or an authenticated HighLevel session, and every request is scoped to a single agency's own data.
10. Your agency's own clients
Where an agency's sub-accounts contain personal data belonging to their clients' customers, the agency remains the controller of that data. Watchtower acts as a processor, reads only what is described above, and stores only the identifiers and fields listed in section 3, never the names, contact details or message content of those customers. Text an agency writes into its own account, such as custom values or trigger link addresses, can appear in findings exactly as written.
11. Changes
We will update this policy when what we store or access changes, and revise the date at the top.
12. Contact
support@shajstudio.com