Skip to content

Privacy Policy

Last updated: 2026-09-16. Written against what the code does, not what policies usually say.

1. Who we are

Chartosaurus ("we", "us") is a chart builder for Notion, built and operated by one person from Indonesia. It reads a Notion database you choose and draws a chart you can embed back into a Notion page.

This policy describes how we handle personal data when you use https://chartosaurus.com. It is written against what the software actually does — if you find a statement here that the product does not match, tell us and we will correct the policy or the code.

Contact for anything in this policy, including data requests: support@chartosaurus.com.

2. What we store

Account: your email address, a hashed password, an optional display name and avatar URL, whether your email is verified, and the dates the record was created and last changed.

Sessions: a session token, its expiry, and the IP address and browser user-agent of the device that signed in. We keep these to detect and investigate suspicious sign-ins. Every session on the account is destroyed when the password is reset.

Data source credentials: your Notion access token (and refresh token, if Notion issues one), plus the Notion workspace ID and bot ID of the connection. Notion is the only third-party data source you can connect. The Google Sheets flow that used to sit unfinished behind an environment flag has been removed outright — the code, the OAuth callback and the three database columns that could have held Google tokens are gone, so there is nothing left to switch on. Every token we store is encrypted before it is written to the database — see section 5.

CSV uploads: available, and stored in full. When you upload a CSV we parse it and keep the parsed rows in our database — there is no upstream to re-fetch them from, so this is the stored copy rather than a cache. An upload is capped at 5 MB and 50,000 rows. Deleting the connection or the account deletes the rows with it.

Charts and dashboards: the chart name, type, rendering engine, axis and styling configuration, the ID of the Notion database it points at, whether it is public, its embed token, and a view counter. Dashboards additionally store their layout and share token.

Billing: a customer ID and a subscription record from Creem, our payment processor — tier, billing interval, status, period dates, cancellation flags — plus the raw webhook payloads Creem sends us, which we keep so billing events are replay-safe and auditable. Those payloads are Creem's own event objects, so they can contain your email address, your name, your billing address and the last four digits of your card. Each stored payload now carries the customer ID it belongs to, written by the code that receives the event, so deleting your account deletes them with it — and any that outlive an account are deleted 90 days after we receive them. See section 10. We never see or store your full card number; that stays with Creem.

Audit log: one row per security-relevant action — password reset, password change, account deletion, forced logout, plan override, and an admin starting or stopping impersonation. The same log also records dashboard lifecycle events (created, deleted, shared, unshared, share token rotated) and every billing event we receive: subscription cancelled, trial ending, invoice paid, payment failed, invoice upcoming, customer created, charge refunded, subscription expired, webhook errors, and the provider's own event-type string alongside them. Notion telling us a database changed is logged too.

Each audit row holds an actor, an action and a timestamp. The actor is not always a user ID — on a webhook row it is the billing customer ID or a system identifier such as "creem" or "notion-webhook". An IP address is recorded only on the admin actions.

Error reports: see section 6.

3. What we do not store

Notion row content. Row values are fetched on demand and held in a short-lived server cache — see section 4. They are never written to our database.

Notion content blocks. We read your database's schema and its rows through the Notion API and nothing else: no page bodies, no paragraphs, no images, no comments, no other database you have not connected.

Card numbers, CVCs or bank details. Checkout and the billing portal are hosted by our payment processor; that data never reaches our servers.

Product analytics. We run no analytics product, no advertising pixel and no cross-site tracking, and we build no profile of you. Two things are measurement rather than nothing, so we name them here rather than let you find them.

Performance telemetry. Sentry samples 10% of performance transactions, and that sample includes client-side route changes — so a fraction of the moves you make between pages is recorded as timing data. See section 6.

Public embed views. Each public chart keeps a view counter. To avoid counting the same viewer twice within an hour, we store a key of the form view:<chart id>:<first 16 hex characters of a SHA-256 hash of the viewer's IP address> in Upstash Redis for one hour. That is a truncated, hashed IP address of everyone who loads a public embed, held for an hour and then gone. It is not reversible into an address and it is not linked to an account.

We do not sell personal data, we do not share it with anyone for marketing, and we do not use your Notion data — or anything else you give us — to train machine-learning models.

4. Notion data specifically

Access is granted by you through Notion's OAuth flow, and it covers only the pages and databases you explicitly share with the Chartosaurus integration during that flow. Notion, not us, decides what that grant reaches; we cannot widen it from our side.

We call exactly three Notion data endpoints, all of them read-only: search, to list the databases you shared with us so you can pick one; database retrieve, to read that database's property names and types; and database query, to read the row values needed to draw the chart. On top of those we use Notion's OAuth endpoints when you connect — we redirect you to its authorize page and exchange the result at its token endpoint. We make no write calls anywhere — Chartosaurus cannot create, edit or delete anything in your workspace.

Row values are held in a short-lived cache on our server, never our database, so a chart or embed loads without hitting Notion on every view. It is the framework's data cache, which on a self-hosted server like ours is written to the server's filesystem rather than kept in memory. Each entry expires on its own, and how long it lives depends on your plan — Free 300 seconds, Starter 60 seconds, Pro 60 seconds, Business 30 seconds, Enterprise 30 seconds.

The cache also refreshes ahead of that timer when Notion tells us via webhook that the database changed. We verify the webhook's signature and use only the database ID in it to invalidate the cache; we do not store the payload.

To revoke our access, remove the Chartosaurus integration from your Notion workspace (Notion → Settings → Connections → Chartosaurus → Remove access). That invalidates the token at Notion's end, which is what actually stops us reading. Deleting the connection inside Chartosaurus Settings deletes our stored copy of that connection's token, but revoking at Notion is the step that ends access.

After revocation, rows already in the cache stay readable until their timer expires — at most five minutes, on the Free tier — and are not refreshed after that, because the next fetch fails against a revoked token.

Your Notion data is never sold, never shared with another customer, and never used to train a model. It is read to draw your chart and for nothing else.

5. How your tokens are protected

Notion tokens are encrypted with AES-256-GCM — an authenticated cipher, so a tampered ciphertext fails to decrypt rather than decrypting to something wrong — using a 256-bit key held in the server environment and never in the database or the source tree. Each value gets a fresh random 96-bit IV.

The key lives only in the deployment environment. Anyone reading a database dump gets ciphertext and nothing else.

Tokens are decrypted in memory only for the duration of a Notion API call. They are never sent to the browser, never written to logs, and are excluded from your data export.

When you delete a connection, that connection's stored tokens are deleted with it. One behaviour worth knowing: if you delete a Notion connection while a second Notion workspace is still connected, we re-point you at that other workspace rather than disconnecting you. To be disconnected from Notion entirely, delete every Notion connection.

When you delete your account, every token on the account goes with it. Deleting tokens on our side does not revoke them at Notion — do that in Notion too, as described in section 4.

6. Error monitoring

Runtime errors and a 10% sample of performance transactions — including client-side route changes — are sent to Sentry so crashes get fixed. Sentry's "send default PII" option is switched off, so IP addresses and request bodies are not attached to events.

Every outbound event first passes through a scrubber that redacts embed tokens, share tokens and password-reset tokens from URLs, error messages, breadcrumbs and span data, because an embed URL is itself the credential for a private chart.

Error events can still incidentally contain a user ID or a database ID inside a stack trace or message. They are not a deliberate collection channel and are retained under Sentry's own retention schedule.

7. Sub-processors

Contabo — the virtual private server that runs the application, in a data centre in Germany. PostgreSQL runs in Docker on that same server and is administered by us, not by a managed database service, so nobody at Contabo touches the database itself. Holds everything in section 2.

Creem — checkout, subscriptions, invoices and tax. Receives your email address and your card details directly at its own hosted checkout; what comes back to us is a customer ID, a subscription ID and a status.

Resend — transactional email only: address verification and password-reset links. Receives your email address and the message.

Sentry — error and performance monitoring, as described in section 6.

Upstash Redis — rate limiting on sign-up, sign-in, change-password, password-reset requests and everything under /embed/, plus the one-hour embed view-dedupe key described in section 3. Receives the requesting IP address, as part of a counter key for the limits and hashed and truncated for the embed counter; it holds no account data.

Notion — the source you connect. Google is not on this list: the Google Sheets flow was removed outright, so the software holds no Google OAuth scope and nothing reaches Google at all.

That is the complete list, and there is no AI provider on it. Each entry is set out in full — what it receives and why — at Sub-processors. We add none silently: a new sub-processor means an update to this section under the notice rules in section 13.

8. Why we are allowed to hold it (GDPR legal bases)

Performance of a contract: your account, your charts, your connections, your subscription. Without these there is no service to deliver.

Legitimate interest: session IP and user-agent, rate-limit counters, the audit log and error monitoring — all narrowly for security, abuse prevention and keeping the service working. We balanced this against your interests and kept the data minimal and short-lived.

Legal obligation: billing and tax records.

Consent: nothing currently depends on it. We set no non-essential cookies and send no marketing email. If that ever changes, it will be opt-in and revocable.

9. Your rights

We apply these rights to everyone who asks, wherever you live. Chartosaurus is operated from Indonesia; where the GDPR, UK GDPR or CCPA/CPRA apply to you, they apply on top of what is written here and we do not ask you to prove which one you are covered by.

Access and portability — Settings → Export downloads a JSON file with your account record, every connection (its type, its workspace ID and its metadata, never the tokens), the rows of any CSV stored against a connection, every chart, every dashboard, your subscription record and any linked sign-in accounts.

Three things are left out of that file on purpose. Data source tokens, your password hash and your session tokens are never exported. Embed and share tokens appear as a yes-or-no flag rather than the token itself, because an embed token is the credential that opens a private chart — an export file that gets forwarded or backed up is not a safe place to carry live credentials. You can always read a share token from the chart or dashboard itself.

Correction — email us what is wrong and we will fix it. The settings screen lets you change only your password; there is no self-service editor for your name or email address yet.

Deletion — Settings → Delete account. See section 10 for exactly what that removes.

Objection and restriction — email support@chartosaurus.com and say what you object to. The practical consequence of objecting to security logging or error monitoring is usually that the account cannot be operated, so we will tell you honestly what a restriction would break before acting on it.

We answer within 30 days and charge nothing. We do not discriminate against anyone for exercising a right — there is no "pay more if you opt out" tier, because there is nothing to opt out of.

If we get it wrong, you may complain to your local data protection authority. We would rather you emailed us first.

10. Retention and deletion

While your account is open, we keep the data in section 2 for as long as you keep the account.

Deleting your account is immediate and irreversible. Settings → Delete account asks you to type your email address to confirm, then deletes the user record and, by database cascade, your sessions, your password hash, every connection and the tokens and any CSV rows inside them, every chart, every dashboard, every subscription record, and any pending password-reset token. There is no grace period and no undo — if you want your charts, export first.

Two things survive. Security audit-log rows are kept deliberately — they record that a deletion happened, and an audit log you can erase by deleting the account is not an audit log. They contain a user ID and an action, not your email or your content. Payment and tax records are held by our payment processor under its own retention schedule, as tax law requires.

The billing webhook records described in section 2 used to be a third survivor. They are not any more: every one we receive is now filed with the customer ID it belongs to, so account deletion reaches it, and a scheduled job deletes any row older than 90 days whether or not an account is attached. The manual-removal offer we published while that was untrue no longer applies, because there is nothing left to remove by hand.

Cached Notion rows are not deleted so much as abandoned: they expire on their own timer within five minutes at most, and nothing refreshes them once the account is gone.

Database backups are taken by us, on the same Contabo server in Germany, and are deleted 30 days after they are written. The schedule is ours rather than a provider's, and the 30-day window is not a policy we keep to by hand — the backup script deletes every dump older than that on each run. So a deleted record can persist in a backup for up to 30 days after deletion, and no longer. Backups are encrypted and are restored only in a disaster, never to recover an individual deleted account.

11. Cookies and local storage

Session cookie — set by our authentication library when you sign in. HttpOnly, so scripts cannot read it. It is what keeps you signed in; without it the app cannot work.

notion_oauth_state — set for the duration of the Notion connection flow to prevent cross-site request forgery. HttpOnly, SameSite=Lax, secure in production, one-hour lifetime, deleted as soon as the flow completes.

Our application sets exactly two cookies, and both are strictly necessary, which is why there is no cookie banner: there is nothing to consent to. We set no analytics, advertising or cross-site tracking cookies, and no third party sets a cookie through us.

We stop short of saying no other cookie can exist. The authentication library we use mounts its own set of endpoints, and it could set an internal cookie of its own that we do not control. The two named above are the ones our code sets, and neither of them tracks you.

Your theme choice, sidebar state and builder panel layout are kept in your browser's local storage, not in a cookie. They never leave your device and are never sent to us.

12. Age

Chartosaurus is not intended for anyone under 16, and we do not knowingly collect data from children. If you believe a child has created an account, email support@chartosaurus.com and we will delete it.

13. Changes to this policy

The last-updated date at the top of this page changes whenever this policy does.

For a material change — a new sub-processor, a new category of data, a new purpose — we will email you and show an in-app notice at least 30 days before it takes effect.

14. Contact

Email support@chartosaurus.com for anything: a privacy question, a data request, an objection, or a correction to this page. One person reads that inbox and answers within two business days.

A suspected vulnerability goes to the same address — please give us a reasonable window to fix it before disclosing publicly. How we handle a report, and how the service is secured, is set out at Security.