Draft. Needs a lawyer's review before use. Nothing on this page is in force yet.
Data processing agreement
Items marked TO FILL IN need an answer; items marked "to confirm" are believed true but not yet checked.
What this is
This agreement covers the personal data Dunly handles for a merchant who uses Dunly to recover failed Stripe payments. The merchant is the controller of that data. Dunly is the processor: it uses the data only to recover the merchant's failed payments, on the merchant's instructions.
The agreement adopts the European Commission's standard contractual clauses between controllers and processors under Article 28(7) of the GDPR (Commission Implementing Decision (EU) 2021/915 of 4 June 2021). The full, binding text of the clauses is the Commission's: eur-lex.europa.eu/eli/dec_impl/2021/915/oj. This page lists the clauses, says which options Dunly and the merchant choose, and fills in the annexes. If anything on this page conflicts with the clauses, the clauses win.
How Dunly bills is in the terms.
Parties
- Controller: the merchant who accepts this agreement (details in Annex I).
- Processor: Dunly, TO FILL IN (legal entity, address, company number).
The clauses and the options chosen
Section I
- Clause 1. Purpose and scope.
- Clause 2. Invariability of the Clauses. The clauses are not changed.
- Clause 3. Interpretation. Read in line with the GDPR.
- Clause 4. Hierarchy. The clauses prevail over any other agreement between the parties, including Dunly's terms.
- Clause 5. Docking clause (optional). Not used.
Section II: Obligations of the parties
- Clause 6. Description of processing. See Annex II.
- Clause 7. Obligations of the parties:
- 7.1 Instructions. Dunly acts only on the merchant's documented instructions. Connecting Stripe and pressing Start recovering, the settings in the dashboard and this agreement are those instructions.
- 7.2 Purpose limitation. Only for the purpose in Annex II.
- 7.3 Duration of the processing. See Annex II.
- 7.4 Security of processing. See Annex III. Only people who need access to run the service get it, and they are bound to confidentiality.
- 7.5 Sensitive data. Dunly does not process special categories of data.
- 7.6 Documentation and compliance. Dunly answers the merchant's questions about the processing and allows audits as the clause describes.
- 7.7 Use of sub-processors. Option 2, general written authorisation. The merchant authorises the sub-processors in Annex IV. Dunly tells the merchant by email at least 30 days before adding or replacing one. The merchant can object in that time; if the objection can't be resolved, the merchant can end the service before the change takes effect. Dunly binds each sub-processor to the same data protection duties and stays responsible for them.
- 7.8 International transfers. Transfers outside the EEA happen only as Annex IV describes.
- Clause 8. Assistance to the controller. Dunly helps the merchant answer requests from their customers (access, deletion and the like) and with security, breach and impact-assessment duties under Articles 32 to 36.
- Clause 9. Notification of personal data breach. 9.1 covers a breach on the merchant's side; 9.2 a breach on Dunly's side, which Dunly reports to the merchant without undue delay after becoming aware of it, with what is known at the time.
Section III: Final provisions
- Clause 10. Non-compliance with the Clauses and termination. When the service ends, Dunly deletes the merchant's personal data as Annex II's retention section says, unless the merchant asks for a copy first.
Annex I: List of parties
Controller
- Name: TO FILL IN by the merchant
- Address: TO FILL IN
- Contact person, position and email: TO FILL IN
- Activities relevant to the processing: sells subscriptions billed through Stripe and uses Dunly to recover failed payments
- Signature and date: TO FILL IN
Processor
- Name: Dunly, TO FILL IN (legal entity)
- Address: TO FILL IN
- Contact: hello@trydunly.com
- Activities relevant to the processing: recovers failed Stripe payments for the controller by emailing its customers and offering a payment page
- Signature and date: TO FILL IN
Annex II: Description of the processing
Categories of data subjects
- The merchant's customers. Any failed invoice payment opens a case, not only a failed renewal, and the Stripe events Dunly receives cover every customer of the connected Stripe account whose invoice or customer record changes (see "copies of the Stripe events" below), whether or not a payment of theirs failed.
- The merchant's staff who sign in to Dunly's dashboard (for running their account; see the end of the next section).
Categories of personal data
Dunly stores, for each failed invoice (a "case"):
- the customer's email address and name, as the merchant's Stripe account has them;
- Stripe identifiers: customer, invoice, subscription, payment method, payment intent and SetupIntent ids;
- the invoice amount and currency, the decline reason and decline codes, the case status, its dates and who recovered it;
- the case log: emails sent, skipped, failed, bounced or stopped (a failed email keeps the email provider's error message, which can name the recipient's address); link clicks (which email the link was in, and whether the visit looked like an email security scanner); payment page views; cards saved; bank confirmations; retries and their results. No IP address and no full browser identifier is stored for clicks or views.
Dunly also stores:
- copies of the Stripe events it receives, as Stripe sends them. Dunly stores each event before deciding whether it needs it, and stores it whether or not it acts on it. The events are invoice events (payment failed, paid, voided, marked uncollectible), subscription cancellations, customer updates, refunds and disputes on charges, and the merchant disconnecting Dunly. They cover every customer of the connected Stripe account, not only those with a case, and they are stored for merchants in report-only mode too, though Dunly acts on none of them then. An invoice event carries the customer details on the invoice (for example email, name, billing address and phone, if the merchant has them in Stripe) and the invoice's lines. A customer update carries the whole customer record, which can include address, phone, shipping details and any metadata the merchant keeps on the customer in Stripe. A refund event carries the charge, with the customer's billing details on it. A dispute event can hold the evidence the dispute carries, such as the customer's name, email address, IP address and address. Dunly keeps the whole event only until it has processed it. Then it deletes the copy and keeps a row with the event's id, type and dates and no customer data, and deletes that row 30 days after the event was received. An event that has not been processed by then is deleted too, with its copy;
- for the loss report, the last 90 days of the merchant's failed subscription renewals: customer email and name, amount, dates, last decline code and outcome;
- email addresses that bounced or complained, with the reason and the date, so no more mail goes to them. The list is kept per merchant: an address that bounced or complained on one merchant's email is not sent that merchant's recovery emails, and the list is deleted with the merchant.
The email provider (Resend) also keeps its own suppression list for Dunly's whole account. A hard bounce or complaint on one merchant's email can therefore stop another merchant's mail to the same address at the provider. That list is outside Dunly's deletion, and the addresses stay at Resend.
Billing records (a separate class)
Dunly also keeps billing records of its own: for each recovery it bills, the merchant's Stripe account id, the Stripe invoice id and number, the amount, currency, fee and dates, the terms version, and a merchant name; for each credit, the amount, date and the Stripe ids of the event and of the refunded charge or the dispute; for each monthly statement, the totals and a copy of the merchant's billing details as they stood when it closed; and the merchant's billing details (legal name, address, VAT number and billing email) as the merchant entered them. The merchant name is the merchant's Stripe business name, else its organization's name unless that name has an @ in it, so an owner's email address used as the default name isn't copied. With neither, the row has no name. The billing details and the merchant name can name a person, such as a sole trader or a billing contact. They hold no customer names, email addresses or customer ids. Dunly keeps these as a controller in its own right, to meet tax and accounting law, so they are not the merchant's data that Dunly processes on the merchant's instructions. They are kept after the merchant's data is deleted, for as long as that law requires (period to confirm). Nothing deletes them automatically today. See "Duration and retention".
The Stripe invoice id and number identify an invoice in the merchant's own Stripe account and say nothing about the customer on their own, but anyone with access to that account can link them to a customer.
Dunly never sees or stores card numbers or security codes. Customers enter card details into Stripe's own form on Dunly's page, and they go straight to Stripe. Dunly reads a card's brand and last four digits from Stripe to show on the payment page, but does not store them.
For the merchant's staff, Dunly stores their email address, their sign-in sessions and sign-in codes (both only as keyed hashes), and the IP address of sign-in code requests and failed sign-in attempts. For each session it also stores the browser's User-Agent string (which names the browser and operating system) and when the session was last used; no IP address is stored for sessions. A session ends after 14 days without use, and 30 days after sign-in at the latest. Sessions are deleted a day after they end (when they expire, go 14 days without use or are signed out), and codes a day after they expire (codes last 10 minutes); failed-attempt records a day after they are made. Staff can see their sessions and sign any of them out from the dashboard.
Sensitive data
None.
Nature of the processing
Reading the merchant's invoices, invoice payments, charges, refunds, disputes, customers and payment methods from Stripe; storing the data above; sending emails to customers on the merchant's behalf; showing customers a payment page; asking Stripe to charge the customer's card when the merchant has chosen Dunly's retries; showing the merchant reports and case timelines.
Purpose
Recovering the merchant's failed subscription payments, showing the merchant what was recovered and how, and working out Dunly's fee.
Duration and retention
- Processing lasts while the merchant uses Dunly.
- The merchant's data is kept while the merchant is connected: cases and their logs, the loss report and the suppression list. The copies of Stripe events are kept only as described above. A merchant that disconnects (in the dashboard, from Stripe, or because its organization is deleted) has its data kept for a while in case it reconnects, then erased automatically within 12 months of disconnecting: its cases and their logs, the loss report, the suppression list and the connection itself. A merchant that reconnects before then is not erased. If the merchant asks in writing, Dunly deletes the data within 30 days, by hand.
- When an organization is deleted in the dashboard, Dunly stops processing for it at once and erases its data (cases and their logs, the copies of Stripe events, loss reports, suppressed addresses, the merchant connection, sending domain, memberships and invites) 7 days after the deletion (normally within the following hour). If removing the organization from a provider such as the email provider fails, Dunly finishes the erasure by hand. When a staff member deletes their account and is the only member of an organization, that organization is erased at once.
- When a staff member deletes their account, Dunly erases the user, their sessions, sign-in codes and memberships, and every invite sent to their address.
- Suppressed email addresses are kept per merchant and deleted with the merchant (Resend's own list is described above).
- Staff sign-in sessions, codes and failed-attempt records are deleted automatically as described above.
- Billing records (see Billing records above) are not part of the merchant's data that these erasures delete. They stay after an erasure for as long as tax and accounting law requires (period to confirm), kept by Dunly as controller.
- Deleted data stays in database backups until those backups rotate out. Backup retention period: TO FILL IN.
Annex III: Technical and organisational measures
What is in place today:
- Encryption in transit. All of Dunly's public addresses (dashboard, API, payment page, website) are served over HTTPS with Let's Encrypt certificates. Dunly talks to Stripe and Resend over HTTPS.
- No card data. Card details are collected by Stripe's own form and never reach Dunly.
- Signed, expiring payment links. The link in each email carries a token signed with a secret key (HMAC-SHA256). It names one case, can't be forged or reused for anything else, stops working at the case deadline (21 days after the case opens) and earlier when the case closes.
- Passwordless sign-in. Staff sign in with a one-time code sent to their email, valid for 10 minutes. Codes and session tokens are stored only as keyed hashes (HMAC-SHA256). Session cookies are HTTP-only, sent only over HTTPS in production, and same-site. Sign-in code requests are limited per email address and per IP address, and wrong codes are limited per IP.
- Access by organisation role. Every dashboard request is checked against the user's membership of the organisation; settings that change how Dunly works are limited to the organisation's owners.
- Limits on payment links. How often a payment link can be opened or used is limited per visitor and per case, so a link can't make Dunly call Stripe without limit. The limits are kept in memory and start again when Dunly is updated.
- Verified webhooks. Events from Stripe and Resend are accepted only with a valid signature.
- Stripe access. Dunly holds no Stripe passwords or per-merchant access tokens; it acts on the merchant's connected Stripe account with its own platform key, and the merchant can disconnect it at any time from Dunly or from Stripe.
- Database. One PostgreSQL database on a single server, used through its own database user that has no administrator rights.
- Backups. A daily backup of the database is stored with Amazon Web Services (S3); a restore has been tested. Region and retention: TO FILL IN.
- Hosting provider's security. Hetzner publishes its technical and organisational measures and its certificates.
- Secrets. Signing and hashing keys and provider keys are kept in the hosting platform's environment settings, not in the code or the database.
- Minimal tracking. No IP addresses or full browser identifiers are kept for customers' clicks or page views.
To confirm or TO FILL IN:
- Encryption at rest of the server's disk and of the backups: to confirm.
- How long the application's logs are kept: TO FILL IN. Their request lines hold the method, route, status, duration and any error, and no IP address, User-Agent, email address, query string or body. Other lines hold ids, counts, sending domain names and error messages, and a provider's error message can quote an email address.
- What the web proxy's logs contain (for example IP addresses) and how long they are kept: to confirm.
- Who at Dunly has access to the server and database, and how that access is protected (for example SSH keys, two-factor sign-in on provider accounts): TO FILL IN.
- Breach response contact and process: TO FILL IN.
Annex IV: List of sub-processors
The merchant authorises these sub-processors (general authorisation, Clause 7.7 option 2, 30 days' notice of changes). The same list is published on the sub-processors page.
| Sub-processor | Purpose | Data | Location |
|---|---|---|---|
| Stripe (Stripe Payments Europe, Limited, Ireland; Stripe, LLC, United States) | Payments: reading invoices, invoice payments, charges, refunds, disputes, customers and payment methods on your connected Stripe account; collecting card details in Stripe's own form; charges and retries | Payment data, customer email and name | Ireland and the United States. Stripe says it runs data centres in the United States and India, limits global storage to authentication and security data, and may transfer data globally under its own terms. |
| Resend (Plus Five Five, Inc., United States) | Email delivery: recovery emails to your customers, sign-in codes, bounce and complaint reports | Recipient's email address, not their name; the email's content: merchant name, amount, deadline, invoice number and description, payment link, support address and logo link; ids of the case and organization. For Dunly's own emails: the recipient's address and the content. | United States. Resend's terms allow other transfers outside the EEA. |
| Cloudflare, Inc. (United States) | DNS for trydunly.com and forwarding of mail to hello@trydunly.com; records are DNS only today, so traffic to Dunly does not pass through Cloudflare | Mail sent to hello@trydunly.com | Global network. Cloudflare's terms allow processing outside the EEA, the UK and Switzerland. |
| TO FILL IN (mailbox provider) | The mailbox that receives mail Cloudflare forwards from hello@trydunly.com | Mail sent to hello@trydunly.com | TO FILL IN |
| Hetzner Online GmbH (Germany) | Hosting: the server that runs Dunly's application and database | All data Dunly stores | TO FILL IN (data centre) |
| Amazon Web Services (Amazon Web Services EMEA SARL, Luxembourg, if the account's country is in Europe, the Middle East or Africa; TO CONFIRM the account's country) | Storage of database backups | All data Dunly stores, in backup files | TO FILL IN (S3 region) |
Transfers outside the EEA, as checked on 2026-11-03. We checked the EU-US Data Privacy Framework list at https://www.dataprivacyframework.gov/list on that date. It showed Stripe, LLC, Cloudflare, Inc. and Amazon.com, Inc. as active. AWS says it is covered by the Amazon.com, Inc. certification. It showed Resend as "Active - Re-certification under Review". That status can change, so check the list for the current one. The data processing terms of Stripe, Resend, Cloudflare and AWS also provide for the European Commission's standard contractual clauses.
Hetzner. Hetzner's data processing agreement says it processes data only in the EU or the EEA, and that a transfer to a third country needs the customer's prior consent. Hetzner also offers data centres in the United States and Singapore, so this holds for Dunly once the data centre above is filled in and is in the EEA. (TO CONFIRM.)
AWS. AWS keeps customer data in the region the customer chooses, except as needed for services the customer starts or to comply with the law.
Stripe's role. Your Stripe account is your own agreement with Stripe. Under Stripe's data processing agreement, Stripe acts as a processor for you when it provides its payment services, and as an independent controller for its own purposes, such as fraud monitoring and legal compliance. Dunly reads and acts on your account only as you instruct it through the connection you authorise.
The providers' own terms. Data processing agreements: Stripe, Resend, Cloudflare, Hetzner and AWS. Their own sub-processors: Resend and AWS; Hetzner's are in Appendix 3 of its agreement.