Privacy Policy
Last updated: April 8, 2026
1. Controller
The controller responsible for data processing within this application is:
Tim Kuehl
2. What is Opal?
Opal is a web application that allows users to schedule and automatically publish posts to Instagram Business and Creator accounts via the Instagram Graph API.
3. Data We Collect
Account data
To sign in, we collect your email address via a magic link (passwordless authentication). No password is stored.
Instagram access token
When you connect your Instagram account, we store an OAuth access token issued by Meta. This token allows Opal to publish posts on your behalf and access insights data. It is stored server-side only and never exposed to the browser. Tokens are automatically refreshed before expiration.
Post content
Images you upload and captions you write are stored to enable scheduled publishing. Images are stored in encrypted storage (Cloudflare R2). Post data (caption, schedule time, status) is stored in the database with row-level security ensuring only you can access your own posts.
Profile insights
We collect daily snapshots of your Instagram account performance metrics including: follower count, total interactions (impressions), reach, profile views, and website clicks. These snapshots are stored in the database to calculate trends over 7-day and 30-day periods. This data is used only to display performance trends in your dashboard.
DM triggers and history
If you use the automated DM feature, we store:
- Trigger keywords and DM message templates you configure
- Log of Instagram comment IDs that have received a DM (to prevent duplicate messages)
- Records of DMs sent (timestamp, recipient, message content)
Creator and hashtag tracking
When you track creators or hashtags, we store your tracking list and periodically fetch engagement data (likes, comments, shares) from their public posts via the Instagram Graph API. This data is used only to display engagement analytics for the creators and hashtags you choose to monitor.
4. How We Use Your Data
- To authenticate you and maintain your session
- To publish Instagram posts at the scheduled time
- To collect and display your account performance metrics (followers, reach, interactions)
- To calculate and display growth trends (7-day and 30-day comparisons)
- To send automated DMs in response to comments (if configured)
- To track creators and hashtags you select and fetch their engagement metrics
- To refresh your Instagram access token before it expires
Data usage limitations: We do not use your data for:
- Profiling or automated decision-making beyond what you explicitly configure
- Advertising or marketing purposes
- Analytics that track your behavior across external services
- Sharing with third parties (except as required by law or as listed in section 5)
- Creating derivative products or machine learning models
5. Third-Party Services & Data Processors
We use the following third-party services for core functionality. These are data processors operating under Data Processing Agreements (DPAs) compliant with GDPR Article 28:
| Service | Purpose | Privacy |
|---|---|---|
| Supabase | Database, authentication, RLS-protected data storage | Policy ↗ |
| Cloudflare R2 | Encrypted object storage for post images and media | Policy ↗ |
| Vercel | Application hosting and serverless API functions | Policy ↗ |
| Meta (Instagram) | OAuth authentication and Instagram Graph API access | Policy ↗ |
| cron-job.org | Triggering scheduled tasks (post publishing, token refresh, comment checks) | Policy ↗ |
Data transfers: Some processors (Meta, Vercel, cron-job.org) may process data outside the EU/EEA. Their privacy policies contain information about safeguards and standard contractual clauses.
6. Cookies & Local Storage
Functional cookies
We use only essential cookies required for authentication and session management:
- Supabase authentication cookie – Maintains your logged-in session. Expires after 24 hours of inactivity.
- CSRF tokens – Protect against cross-site request forgery attacks.
Local storage
The browser stores non-sensitive user preferences (UI theme, selected time period) in localStorage. This is cleared when you sign out.
No tracking or advertising
We do not use:
- Tracking cookies or pixels
- Third-party analytics (Google Analytics, Mixpanel, etc.)
- Advertising cookies
- Fingerprinting technologies
7. Data Retention & Deletion
During active account usage
Your data is retained as long as your account exists and is necessary for the service to function. This includes:
- Email address (for authentication)
- Instagram access token (for API access)
- Scheduled posts (until published or deleted)
- Profile insights snapshots (retained for trend calculation)
- DM triggers and send history (retained for duplicate prevention)
- Creator and hashtag tracking data (retained for analytics)
Account deletion
When you delete your account:
- All your personal data is immediately deleted from our servers
- Linked Instagram tokens are revoked
- Images in storage are deleted
- Database records are deleted (cascade delete via foreign keys)
- Deletion is permanent and cannot be reversed
To request account deletion, contact tim@tensquared.marketing.
Token revocation
Instagram access tokens can be revoked at any time:
- From the Settings page within Opal (revokes token immediately)
- From your Instagram account settings (Meta side)
- Automatic expiration (tokens expire after ~60 days if not refreshed)
8. Your Rights under GDPR
As a data subject under the GDPR, you have the following rights. To exercise any of these rights, contact us at tim@tensquared.marketing. We will respond within 30 days (or up to 90 days for complex requests).
Right of access (Article 15)
You can request a copy of all personal data we hold about you in a structured, commonly-used format.
Right to rectification (Article 16)
You can correct inaccurate or incomplete personal data.
Right to erasure (Article 17)
You can request deletion of your personal data. We will delete your account and all associated data within 30 days unless there are legal grounds to retain it.
Right to restrict processing (Article 18)
You can request we limit how we use your data while we investigate a dispute.
Right to data portability (Article 20)
You can request your data in a machine-readable format (JSON, CSV) to transfer to another service.
Right to object (Article 21)
You can object to processing of your data. Since we only process data necessary for the service, this would be equivalent to requesting account deletion.
Right to withdraw consent (Article 7)
You can withdraw consent for Instagram OAuth access at any time by revoking the token.
Right to lodge a complaint
If you believe your rights have been violated, you can lodge a complaint with the German data protection authority:
Berliner Beauftragte für Datenschutz und Informationsfreiheit
Friedrichstraße 219, 10969 Berlin
9. Security & Data Protection
Transport security
All data is transmitted over HTTPS with TLS 1.3 encryption. Man-in-the-middle attacks are prevented through certificate pinning and HSTS headers.
Authentication security
We use passwordless authentication (magic link) instead of passwords, which eliminates password-related breaches. Sessions are time-limited (24 hours) and use secure, HttpOnly cookies.
Token security
Instagram access tokens are:
- Stored server-side only (never exposed to browser)
- Protected with Row-Level Security in the database
- Automatically refreshed before expiration (preventing token reuse attacks)
- Revoked on account deletion or user request
Database security
Row-Level Security (RLS) is enforced in Supabase — each user can only access their own data. This is enforced at the database level, not the application level, providing defense in depth.
File storage security
Images are stored in Cloudflare R2 with encryption at rest. User access is restricted to their own assets through path-based validation and signed URLs. Unauthorized access attempts are rejected with 403 Forbidden.
API security
We protect against common attacks:
- CSRF: Protected with CSRF tokens on state-changing requests
- SSRF: Input validation prevents server-side request forgery attacks
- Timing attacks: Timing-safe cryptographic comparisons prevent secret disclosure
- Injection: Parameterized queries prevent SQL injection
- XSS: Content Security Policy (CSP) headers and React's built-in XSS protections
Dependency management
We keep dependencies up-to-date and monitor for security vulnerabilities. Critical updates are applied immediately.
10. Legal Basis for Processing
Under GDPR Article 6, we process your personal data on the following legal bases:
- Performance of contract (Article 6(1)(b)): Data necessary to provide the scheduling and publishing service
- Your consent (Article 6(1)(a)): OAuth consent for Instagram API access (can be withdrawn anytime)
- Legitimate interests (Article 6(1)(f)): Security monitoring, fraud prevention, and service improvement
- Legal obligation (Article 6(1)(c)): Required by law (e.g., preventing abuse)
11. Data Protection Officer & Contact
As a personal project operated by an individual data controller, we do not employ a formal DPO. However, we comply with GDPR requirements and are committed to data protection.
Data Controller:
Tim Kuehl
For privacy inquiries, data subject requests, or complaints, please email the above address.
12. Changes to This Policy
We may update this policy from time to time. The date at the top of this page reflects the most recent revision. Material changes will be communicated via email to registered users. Continued use of Opal after changes constitutes acceptance of the updated policy.
Questions? Contact us at tim@tensquared.marketing