Contracts: agreements and their evidence

Preview. Built, but not yet checked against a real provider account or a live deployment; it may still change.

A seller (a tenant) can put agreements in front of its own customers: a distance sales contract, a pre-information form, terms of service and a privacy notice. Payrudder keeps the texts, shows them where the customer pays, records that a specific text was accepted, and mails the customer a copy. It supplies templates and evidence, not legal guarantees: nothing here says that a text is sufficient in any country, and the starter texts must be reviewed by a lawyer before use (the plan lists what has and has not been checked).

The model

A business customer (customer_type = business) gets the business series when the seller published one, else the consumer text. A customer of unknown type is treated as a consumer (the consumer's text gives rights a business does not have, never the other way round).

Where it applies

PUT /v1/contracts/settings sets required_kinds. While it is not empty:

Path What happens
POST /v1/subscriptions refused with plans.contract.not_accepted until the customer has accepted the current version of each required kind (record it with POST /v1/customers/{id}/contract-acceptances; GET .../contract-requirements returns the texts to show)
Hosted invoice page, payment link and portal invoice (POST /i/{token}/pay, POST /c/{token}/invoices/{id}/pay) the page shows each text the customer has not accepted with an unticked box and a button that says it is an order with an obligation to pay; the server checks the boxes (the page needs no script) and starts nothing without them, or for a text replaced since the page was shown
Credit pack purchase, ad-hoc payment link they end on the same invoice page, so they are covered there; the link's "continue" step takes no money
A payment link that names its own agreements (required_contracts on POST /v1/payment-links) default (not agreed): the link's list replaces the seller's required_kinds for the page of that link (it does not add to it), and an empty or absent list means the setting applies. The kinds must be published when the link is made (plans.contract.kind_unpublished) and each may be named once (billing.payment_link.bad_required_contracts). The invoice link an ad-hoc link hands out when the payer continues carries the list; the same invoice opened by another link or by the portal asks for the setting
Renewals, dunning charges never held back: nobody is present to accept

A guest payment (a payment link with no customer) is covered by the invoice it was accepted for.

GET /v1/customers/{id}/contract-acceptances is paged (page_size, default 100, at most 200; next_page_token) newest first and can be narrowed by kind, source (api or hosted), version_id and the time of acceptance (from inclusive, to exclusive, RFC 3339).

The hosted pages fail closed: if the seller's agreements cannot be read, or a kind it requires has no published version, the page offers no way to pay and a pay request is refused.

After the acceptance

The customer is mailed the page they accepted, in their language (the template contract_accepted, which is a system mail the seller's mail switch does not hold back; a guest has no address and gets none). The mail is sent only when the page fetched has the hash the acceptance holds. The sellers' webhook endpoints get contract.accepted (one event for the group), contract.version_published and contract.withdrawal_requested (webhooks).

The portal, the withdrawal function and the renewal notice

Keeping the evidence

retention_months (12 to 120, default 36) is how long the IP address and user agent of an acceptance are kept; a daily job blanks them afterwards and changes nothing else (it is the only thing that ever changes an acceptance, and the database allows it nothing more). The rest of the record, including the snapshot, stays. A sandbox reset deletes the sandbox's acceptances (they name its customers); live evidence is never deleted. Promoting a sandbox to live copies the agreement texts as live's own first versions and never an acceptance.

What was checked, and what was not

See plan 21: the Turkish Mesafeli Sözleşmeler Yönetmeliği (consolidated text of mevzuat.gov.tr) and the EU Consumer Rights Directive 2011/83/EU with Directive (EU) 2023/2673 (Publications Office) were read, with article numbers and dates, for the structure of the pages and the starter texts. Not checked: that any text is legally sufficient anywhere, whether Payrudder is an intermediary service provider under the Turkish rules, national transpositions of the EU texts, how long an IP address may be kept under KVKK or the GDPR, auto-renewal rules, and the wording of the box sentences in German, French, Spanish and Arabic.