Security: Deal Approvals & Stage Gate
Last updated: 17 October 2026
This page describes how Deal Approvals & Stage Gate protects your HubSpot account and data.
Least privilege
- The app asks for deal access (to read stage changes and move deals), deal property settings (to create the Approval status property and list properties for conditions) and owners (to choose approvers). The pipeline rules, stage editing and workflow permissions are optional. It uses no sensitive data scopes and never reads contacts, companies or tickets.
- It only changes a deal’s stage when your policy says so: it moves an unapproved deal back to its last stage before the gate, moves an approved deal to the requested stage (you can turn this off), and sends a rejected deal in the waiting stage back to where it came from.
Authentication and request integrity
- The app connects through HubSpot’s OAuth flow. HubSpot shows the requested permissions before you connect.
- Every request from the app’s card, settings and home page to our backend, every webhook and every workflow action call carries HubSpot’s signature (X-HubSpot-Signature-v3). The backend checks it with the app’s client secret and rejects requests that are unsigned, changed or more than five minutes old. The HubSpot account and user come from the signed request, never from the request body.
- Only app admins (at first, the user who installed the app) can change policies and settings. Only the approvers of the current step can approve or reject, and the person who requested can never approve their own request.
- The CSV export and billing links are short-lived links signed by the backend (15 minutes).
- Stripe webhooks are verified with Stripe’s signature.
Data protection
- OAuth refresh and access tokens are encrypted at rest with AES-256-GCM. Each ciphertext is bound to its HubSpot account ID, so it cannot be used for another account. The encryption key is kept as a Cloudflare secret, separate from the database.
- Every database query filters on the HubSpot account ID from the verified request; tests check that one account cannot see or decide another account’s requests.
- Text you enter (comments, reasons, names) is escaped before it is written into notes on the deal.
- All traffic uses TLS. Hosting is on Cloudflare Workers with a D1 database located in Europe.
- The app stores policies, settings, approval requests and their history, and short-lived copies of your pipelines and users. It stores no contacts and no deal data beyond the fields named in the setup guide.
Reliability
- Stage changes are handled right away for the first few events of a webhook call and through a queue for the rest, so bulk edits stay inside HubSpot’s limit of 110 requests per 10 seconds per account. When HubSpot answers 429 (rate limited) or a 5xx error, the event is retried with back-off.
- Each webhook event is handled once (duplicates are dropped) and one deal is handled by one process at a time.
- A request can be decided only once: two approvers clicking at the same moment cannot both change it.
- We monitor the share of successful HubSpot API calls (target above 95%) and rate-limited calls (target below 5%).
Uninstall and deletion
Disconnecting in the app settings uninstalls the app through HubSpot’s uninstall API, revokes the token and deletes the account’s data immediately. Uninstalling in HubSpot is picked up from HubSpot’s app lifecycle events within the hour; the remaining account record is deleted after 30 days.
Reporting a vulnerability
Email support@kayabyte.dev with the subject “Security”. We confirm receipt within one business day. Please do not test against accounts you do not own.
See also the data processing agreement, sub-processors and the privacy policy.