Privacy policy

What DocMint stores, for how long, and who else touches it. This was written from the database schema and the code that writes to it, not from a template.

1. Controller

The controller for the processing described here is:

Companyproductivity-boost.com Betriebs UG (haftungsbeschränkt) & Co. KG
AddressReichenbergerstr. 2, 94036 Passau, Germany
Represented byFlorian Standhartinger
Emailinfo@productivity-boost.com
Telephone+49 178 1981631

See also the imprint.

2. What is stored, and for how long

Everything below is in one PostgreSQL database. There is no third-party analytics product, no advertising network, no tracking pixel, and no third-party script or font on this website at all — these pages load nothing from any host other than this one.

What DocMint does count is a handful of daily totals, in that same database (see processors below): for each UTC day, one number each for views of the public pages, new accounts, started checkouts and completed payments — and, per public page, how many page loads were served (these are the views) and how many of those loads were entries from outside our domain zone (these are the visits; a load with no referrer at all counts as a visit too). Referrers from subdomains of our own domain zone (mintapis.com) are treated as our own traffic: they count as views, not as visits, and no host is stored for them. Per referring host name — the host only, never a path or query — the readout shows how many entries it sent. That is the entire dataset: a date, a kind or a page, a host name, and numbers. For this, DocMint stores no IP addresses, no user-agent strings, no cookies, no fingerprints and nothing that could identify a person, builds no personal profiles, and sends nothing to any third-party analytics product. Only the operator sees the totals — on an endpoint that answers only with a secret key — to know whether the website works and whether the service is growing.

DataWhyKept for
Email address and a bcrypt password hash To identify your account. The password itself is never written down — only the bcrypt hash of it. Until you delete the account in the dashboard or ask for it to be deleted.
API keys Stored only as a SHA-256 hash plus the first 16 characters, so a key can be recognised and listed but never read back — not by support, not by the operator. A label and the times it was created, last used and revoked are stored too. Until revoked; a revoked key keeps its row and a revocation timestamp.
Uploaded template files, and every version of them Storing a template under a name is the entire point of POST /v1/templates. The file's bytes, its size, a SHA-256 of it, the placeholder list extracted from it, and any note you attached to that version are all stored. Until you delete the template. Only the most recent 20 versions of each are kept; older ones are pruned automatically.
The data you send to be filled in On a synchronous call (/v1/render, /v1/batch, PDF conversion) it is held in memory for the length of the request and used to produce the document. It is never written to the database. On an async job (POST /v1/jobs) the whole job request — the data items, the template name or inline template, and the options — is stored in the jobs table so the job can run. Not stored for synchronous calls. An async job's request is deleted 7 days after the job finishes, once its credits are settled and any webhook delivery has succeeded or given up.
The documents that are produced On a synchronous call the document is produced in memory and returned in the response. It is not stored. An async job's output is stored in the files table as a hosted download link under /f/<token>; a link expires 24 hours after the job finishes. Expired files are deleted automatically; cleanup runs inside the service every 10 minutes. Not stored for synchronous calls. Async job outputs: 24 hours.
Templates sent inline as template_base64 On a synchronous call, treated exactly like the data above: used for the render and discarded. It is never written to the database. On an async job the inline template is stored with the job request in the jobs table, so the job can run. Not stored for synchronous calls. An async job's request is deleted 7 days after the job finishes, once its credits are settled and any webhook delivery has succeeded or given up.
Async job webhooks If you supply a webhook_url on POST /v1/jobs, it is stored with the job, together with the delivery attempts and the job result summary, so DocMint can send a signed POST with the job status and its result (download links) or error when the job finishes. Kept with the job; deleted 7 days after the job finishes, once its credits are settled and any webhook delivery has succeeded or given up.
Usage records One row per render: what kind of call, the format, the output mode, the template id, the credits, the duration and per-stage timings, whether it succeeded and the error code if not, and the request id. No document content, no template content and no request body. Kept, so quota accounting is accurate.
Stripe customer and subscription ids To connect an account to a subscription, and to let the Stripe customer portal find it. Only the identifiers — never a card number. Until the account is deleted.
Login sessions When you sign up or sign in on the website, a session row (a random id, your account id and an expiry time) is stored and one cookie, docmint_session, is set so the dashboard knows who you are. It is HttpOnly, SameSite=Lax and carries no tracking data. API calls with a key never create a session. 30 days, or until you sign out.
Daily site totals and visitor statistics Daily aggregates only. For each UTC day, one number each for public page views, new accounts, started checkouts and completed payments. For each UTC day and public page, how many page loads were served (the views) and how many of those loads were entries from outside our domain zone (the visits). A load with no referrer at all counts as a visit; referrers from subdomains of our own domain zone (mintapis.com) are treated as our own traffic — they count as views, not as visits, and no host is stored for them. And per referring host — the host name only, never the path, query string or full URL — how many entries it sent. No IP addresses, user-agent strings, cookies or fingerprints are stored for any of this, unique visitors are not counted, and no personal profiles are built, so nothing in these rows can be tied to you. A browser that signals an objection with Sec-GPC: 1 or DNT: 1 is not counted at all, and neither are bots, prefetches or anything that is not a full page load. Kept for 13 months; older rows are deleted by a cleanup that runs hourly.

The application does not log your IP address or user agent. The reverse proxy in front of the application keeps no access logs, and the application itself writes no IP addresses to its logs or to the database. Two exceptions. One is transient: the signup endpoint keeps the calling IP address in memory for 60 seconds to enforce one signup per minute; it is never written to disk or to the database. The other is stored: password-reset requests are rate limited in the password_reset_limits table under a SHA-256 hash of the action and the IP address — the hash, not the address itself. Rows older than 2 hours are deleted only when a later password-reset request runs the cleanup; there is no scheduled deletion, so no fixed retention period applies to these hashes.

3. Card details

Card numbers never reach this service. Payment is handled entirely by Stripe on Stripe's own pages: POST /v1/billing/checkout returns a Stripe URL and the browser goes there. DocMint stores only the Stripe customer and subscription identifiers, the plan and the credit limit. If you enter a VAT ID at checkout, Stripe holds it and puts it on the invoice; it is not stored here.

4. Email

DocMint sends exactly one kind of email: a transactional password-reset link, and only when you ask for one. The mail is handed to a Postfix relay running on the same server as the application, which forwards it over authenticated TLS to Google's Gmail SMTP service. There is no newsletter, no marketing mail and no confirmation email.

5. Outbound requests

DocMint never downloads content referenced by URL in your data. An image referenced by URL is not fetched; you must supply its bytes. The one outbound request made on your behalf is the job webhook: when an async job finishes, DocMint sends a signed POST with the job status and its result (download links) or error to the webhook_url you supplied. The only other outbound connections are the password-reset mail described above and Stripe API calls for billing.

6. Processors

Three companies process data on behalf of this service:

ProcessorWhat they doWhere
Hetzner Online GmbHRents the dedicated server on which the application and the PostgreSQL database both run.EU
Google Ireland LimitedDelivers the password-reset email through its Gmail SMTP service; the reset link is the only mail this service sends. Google's own terms state that in the EEA and Switzerland its services are provided by Google Ireland Limited, Gordon House, Barrow Street, Dublin 4.Ireland / worldwide (Google states it maintains servers around the world and that information may be processed outside the country where you live)
Stripe, Inc.Takes payments, stores card details and hosts the checkout and customer-portal pages. Stripe is the controller for the card data itself.Ireland / United States

LibreOffice, used for the optional PDF conversion, runs as a local process on the same server. It is not a processor and nothing leaves the machine for it.

7. Your rights

Under the GDPR you may request access to your data, correction, deletion, restriction of processing, portability, and you may object to processing. Write to info@productivity-boost.com. You may also complain to a supervisory authority; for this controller that is the Bayerisches Landesamt für Datenschutzaufsicht (BayLDA), Ansbach.

Being straight about deletion: signed-in users can delete their account permanently from the dashboard. Deletion removes the account and its linked API keys, sessions, templates and every stored version, hosted files, async jobs with their stored requests and results, and usage records. Stripe keeps its own customer and invoice records. Anonymous daily counters and hashed rate-limit keys that are not linked to an account remain. If you cannot use the dashboard, ask the operator to delete the account.

8. Legal basis

9. Changes

If this policy changes materially, the change will be visible in this page's git history — the repository is public at github.com/fstandhartinger/docmint.

DocMint · Docs · Imprint · Terms