=== SignSealer ===
Contributors: mashdunllc
Tags: esignature, waiver, contract, signature, agreement
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.17.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Send waivers and agreements from WordPress, and see who has signed. Signing happens on SignSealer; this site keeps ids and status, never evidence.

== Description ==

Your site sends somebody a document to sign, and later wants to know whether they signed it. That is the whole job of this plugin.

Everything that makes a signature worth having happens on SignSealer: consent recorded as its own event before the signature is accepted, the document's exact text fingerprinted into every entry on the trail, and a hash chain that breaks if any entry is altered. A certificate can be checked afterwards by anyone holding its code, without an account.

**You need a SignSealer account.** This plugin is a client for it. See https://signsealer.com.

= Three things this plugin refuses to do =

These are limits on purpose, not features that are missing.

**It never renders a signature pad.** Signing happens on SignSealer's own pages. A drawing captured in WordPress and posted to an API would make every claim on the certificate untrue — the certificate says what the signing engine observed, and it cannot observe something that arrived as a form field.

**It never stores evidence.** Document ids, a status and a link. If you restore a six-month-old backup of this site, nothing about any signature changes, because nothing about any signature was here.

**It never holds a master credential.** The connection is OAuth 2.0 with PKCE, scoped to one business, and you can end it from your own SignSealer account without touching WordPress. There is no key here that reaches two accounts.

= Why a link, and a frame only where the site is proven =

SignSealer's signing pages refuse to be framed (`frame-ancestors`) on any site the business has not proven is its own. A signing page inside another site's frame is a clickjacking target, and the thing being clicked is a signature. So the block, the shortcode and the forms send the signer to SignSealer's own page, where they can see whose address bar they are signing on. The frames are where signing comes first, on this site: WooCommerce's **Before payment**, a form set to be signed before it is sent, and Amelia's and Simply Schedule Appointments' signing before the booking. Connecting the plugin proves the site to SignSealer, which is what lets its signing page be shown here.

= What it does =

* Connects your site to one SignSealer business over OAuth 2.0 with PKCE.
* Registers its own webhook endpoint when you connect, so there is no secret to copy between two screens.
* Verifies every delivery: the HMAC signature, a five-minute freshness window, and a replay it has already seen. Fires a `signsealer_event` action your own code can hook.
* Has its own **SignSealer** item in the admin menu. **Start here** says what the plugin does, whether the site is connected, and — for every integration — whether its plugin is on the site, whether it is set up, and the steps to set it up.
* Lists that business's forms and templates under **SignSealer → Templates**, with the shortcode for each one beside it.
* Gives you a **SignSealer agreement** block, and `[signsealer_sign workflow="your-form"]` if you prefer a shortcode.
* **WooCommerce:** mark a product as needing an agreement, and the document is started when the order is paid (or placed, your choice), offered on the thank-you page, in the order email and under My Account, with its status on the order screen and in the order notes. Or have it signed before payment: the cart's checkout button becomes "Sign the agreement", the customer signs on your site, in a frame, and the checkout will not place the order until it is signed. Its settings are under **WooCommerce → Settings → SignSealer**.
* **Details the agreement needs:** a template that asks for more than an order knows — where it takes place, a vessel's name — is answered on the product by you, or asked of the customer before they sign.
* **WooCommerce Bookings:** a booking you confirm starts its agreement straight away, paid or not, and the booking's date, time, number of people and resource are filled into the template.
* **Amelia, LatePoint and Simply Schedule Appointments:** choose the workflow a booking of each service starts, under **SignSealer → Bookings**. The person who booked is emailed the link to sign, and the booking fills in the service, the date and time, how many people, who runs it and where. Amelia's form opens the agreement before it books, and books once it is signed; Simply Schedule Appointments opens it over the page as soon as the booking is made; LatePoint's confirmation step shows a button to sign.
* **Event Tickets:** RSVPs and tickets for your events, under **SignSealer → Bookings**: one workflow every ticket and RSVP starts, and a different one for any ticket that needs it. Whoever booked is emailed the link to sign, for everyone they booked, and the event fills in its name, date, time, venue and organizer, and how many people. The RSVP's own message and the order page show a button to sign.
* **Events Manager:** bookings for your events, under **SignSealer → Bookings**: one workflow every event's bookings start, and a different one for any event that needs it. Whoever booked is emailed the link to sign, for the spaces they booked, and the event fills in its name, date, time, location and tickets. Events Manager's own message after booking shows a button to sign.
* **Booking Calendar:** choose the workflow every booking starts, under **SignSealer → Bookings**. Whoever booked is emailed the link to sign, and the booking fills in the date (and the time, for a time slot), how many people, and the name, email and phone from its form. Booking Calendar's own message after booking shows a button to sign.
* **FluentBooking:** meetings, lessons and sessions booked on its event types, under **SignSealer → Bookings**: one workflow every event type starts, and a different one for any that needs it. Whoever booked is emailed the link to sign, with the event type, the date and time, the host and an in-person place filled in, and FluentBooking's own confirmation shows a button to sign.
* **MotoPress Hotel Booking:** stays at your accommodation types, under **SignSealer → Bookings**: one workflow every booking starts, and a different one for any accommodation type that needs it. Once a booking is confirmed, the guest is emailed the link to sign, with the check-in date and time, the check-out date, the nights and everybody staying filled in, and its Booking Confirmed page shows a button to sign.
* **Bookly:** appointments booked with your services, under **SignSealer → Bookings**: one workflow every service starts, and a different one for any service that needs it. Once a booking is approved, the customer is emailed the link to sign, with the service, the date and time, how many people and the staff member filled in, and the last step of Bookly's booking form shows a button to sign.
* **Gravity Forms, WPForms, Fluent Forms, Contact Form 7, Formidable Forms, Ninja Forms, SureForms, Forminator, MetForm, Everest Forms and JetFormBuilder:** map a form to a workflow in that form's own settings (in Ninja Forms, a SignSealer action) — which field is the email, which is the name, which field answers each blank the template asks — and a submission ends on the signing page, or with a button to sign in the form's own confirmation. Or the form signs first: pressing its button opens the agreement over the form, and the form is sent once it is signed. A blank the form does not ask is asked on your site just before signing. **SignSealer → Forms** lists every form, with a link to its settings.
* **The button to sign** is SignSealer blue, a colour of your own, or your theme's own button, as you choose under **SignSealer → Settings**.
* Sends the signer back to your site afterwards: the order they came from, or the page the form was on.

= For developers =

Every verified delivery fires an action:

`add_action( 'signsealer_event', function ( $event, $payload ) {
    if ( 'signing.completed' === $event ) {
        // $payload['document']['id'] has signed.
    }
}, 10, 2 );`

The signature is checked before this fires, so a handler can trust what it is handed.

Once a document completes, its signers' answers to your form's questions
are handed to `signsealer_document_completed`, asked for from SignSealer
just after the delivery. This plugin stores none of them; what your own code
does with them is up to it:

`add_action( 'signsealer_document_completed', function ( $document ) {
    if ( 'Yes' === ( $document['answer']['married'] ?? '' ) ) {
        // "Are you married?" was answered Yes.
    }
} );`

`$document['answer']` has one value per question, by the question's key; a
tick box is `Yes` or `No`. A question more than one person answered (two
signers, each person in a party) holds every different answer, sorted and
joined with a comma: `Yes` means everyone said Yes, `No, Yes` that they
differed. `answers_text` is every answer,
one line each, for an email; `answers` has each one with who gave it.
Sensitive answers are masked, as your staff see them. To ask for a
document's answers yourself: `signsealer_get_answers( $document_id )`.
It runs from WP-Cron, so on a site that runs WP-Cron from the server it
waits for the next run.

== Installation ==

1. Install and activate the plugin.
2. Open **SignSealer → Start here** in the admin menu and press **Connect to SignSealer**.
3. Sign in to SignSealer (or create an account there), choose the business this site belongs to, and approve. You are brought straight back.

4. Back on Start here, pick the integrations you want. Each card has its three steps and a link to a step-by-step guide at https://signsealer.com/wordpress.

The plugin registers itself with SignSealer, registers its own webhook endpoint, and signed statuses start arriving with nothing to copy or paste. Your site must be on https: SignSealer checks the plugin is really running there before it connects, and https is also how it posts signed statuses back.

== Frequently Asked Questions ==

= Why does my site need to be on https? =

Two reasons. Before SignSealer connects a site it fetches a small page the plugin serves, to check the plugin is really running there and that the request came from this site; it will only do that over https, so nobody can register an application in your site's name. And once connected, SignSealer posts signed statuses back to your site, which must also be over https so those deliveries are private and verifiable.

= Do I need a SignSealer account? =

Yes. This plugin talks to the SignSealer API; it is not a standalone signing tool.

= Where is the signed document kept? =

On SignSealer, with its certificate and audit trail. This site keeps the document's id and its status so a page can say whether it is signed.

= Can I collect the signature on my own page? =

No, and that is deliberate. See "Three things this plugin refuses to do" above.

= Does the plugin add a link or a credit to my site? =

Not unless you ask it to. Under SignSealer → Settings → The sign button there is a setting, off by default, that puts a small "Signed with SignSealer" line under the signing button block and the `[signsealer_sign]` shortcode, linking to signsealer.com. Only a button to your own business's form gets it: nothing else the plugin shows, and not a shortcode pointed at another business. A business with white label is not offered it.

= What happens if I deactivate the plugin? =

Nothing at SignSealer. Your documents, evidence and certificates are unaffected. Deactivating does not revoke the connection — end that in SignSealer under Developers → Connected apps.

= Does it work with WooCommerce? =

Yes. On a product's edit screen, under General, choose the **SignSealer agreement** that product needs. When an order containing it is paid — or placed, under WooCommerce → Settings → SignSealer — the document is started for the customer, offered on the thank-you page, in their order email and under My Account, and its status appears on the order screen and in the order notes as SignSealer reports it. Works whether your orders live in posts or in WooCommerce's own order tables.

= Can the customer sign before they pay? =

Yes. Under WooCommerce → Settings → SignSealer choose **Before payment**. While a customer's cart holds a product whose agreement is unsigned, the cart's checkout button reads **Sign the agreement** and goes to a page of your site, in your theme, that shows SignSealer's signing page in a frame; a customer who reaches the checkout some other way is sent back to it. The classic checkout and the checkout block both refuse to place the order until SignSealer confirms it is signed, and the order then carries that signed document. SignSealer shows its signing page in a frame only on sites the business has proven, and the site you connected is one.

= My agreement asks for something the order does not know =

A template blank that nothing fills — `{{location}}` on a photo release, say — would make SignSealer refuse to start the document. So on the product's edit screen, under its SignSealer agreement, each such blank has a box: fill it in to answer it for every order of that product, or leave it empty and the customer is asked. Before payment they are asked on the signing page, beside their name and email. After payment the order's Sign link — on the thank-you page, in the order email and under My Account — opens a page of your site that asks, and the agreement is sent once they have answered. The order notes say when an agreement is waiting for that.

= Does it work with WooCommerce Bookings? =

Yes. A bookable product is a product, so mark it the same way. A booking you confirm starts its agreement at once, whether or not it has been paid, because the agreement is wanted before the day. The booking's date, time, number of people and resource go to the template as `booking_date`, `booking_time`, `persons` and `resource`, and the booking's own screen shows where the agreement stands.

= Does it work with Amelia, LatePoint or Simply Schedule Appointments? =

Yes, since 1.8.0. Open SignSealer → Bookings, which lists the services in each (in Simply Schedule Appointments, its appointment types), and choose the workflow a booking of each starts. A booking made through the plugin's booking form, or by staff, starts that workflow for the person who booked, and SignSealer emails them the link; LatePoint's confirmation step shows a button to sign too. Since 1.16.0 the person signs on the page in the other two as well. Amelia's booking form opens the agreement over itself when the person presses Book, and makes the booking once it is signed (a booking Amelia takes payment for through Stripe or WooCommerce is made first, and the agreement opens just after). Simply Schedule Appointments opens it over the page as soon as the booking is made, or on the page its form sends people to afterwards. Closed without signing, a button to sign stays on the page, and the email has the link. In Simply Schedule Appointments an appointment waiting on payment starts its agreement once it is booked. The booking fills in `booking_date`, `booking_time`, `service_name`, `persons` and `staff`. Any other blank the agreement asks is listed under the service: choose what of the booking answers it (a `location` blank is given the booking's location, when the plugin has locations set up), or type the answer to use for every booking of that service. A booking saved again — rescheduled, confirmed, paid — starts nothing a second time, and a canceled one starts nothing. If a booking could not start its agreement, SignSealer → Bookings says which and why.

= Does it work with Event Tickets? =

Yes, since 1.9.0: its RSVPs (the ones Event Tickets 5.30 makes, and the older kind a site has not moved over yet) and its Tickets Commerce tickets, free or paid. Open SignSealer → Bookings. Under Event Tickets, the first row is every ticket and RSVP; each ticket of the events still to come is listed under it, for any that should start a different workflow. Whoever RSVPs or buys is emailed the link to sign: one agreement for each ticket in their order, saying how many people it is for, because Event Tickets asks one name and email an order. A logged-in visitor's RSVP is under their account's email, as Event Tickets records it. The event fills in `service_name` (the event's name), `ticket_name`, `booking_date`, `booking_time`, `persons`, `location` (its venue) and `staff` (its organizer); an RSVP on a page rather than an event fills in the page's name, the ticket and how many. The RSVP's "received" message and the order page show a button to sign. An RSVP of "not going" starts nothing, and a ticket starts its agreement once its order is completed. Event Tickets Plus, the paid add-on that sells tickets through WooCommerce, has not been tested.

= Does it work with Events Manager? =

Yes, since 1.10.0. Open SignSealer → Bookings. Under Events Manager, the first row is every event; each event still to come is listed under it, with its date, for any that should start a different workflow (each date of a recurring event is an event of its own). A booking starts its agreement for the person who booked, one agreement a booking with `persons` the spaces they took, and SignSealer emails them the link; Events Manager's own message after booking shows a button to sign too. A booking waiting for your approval starts it; one waiting on a payment starts it once it is approved; a rejected or cancelled one starts nothing; approving a booking later starts nothing a second time. The event fills in `service_name` (the event's name), `ticket_name`, `booking_date` and `booking_time` (in the event's own time zone), `persons` and `location`. Events Manager Pro's payments and forms have not been tested.

= Does it work with Booking Calendar? =

Yes, since 1.11.0, with the free Booking Calendar's calendar. Open SignSealer → Bookings and choose the workflow every booking starts. A booking made on the calendar, or added in its admin, starts that workflow for whoever booked, and SignSealer emails them the link; Booking Calendar's own message after booking shows a button to sign too (with its "message" setting for after booking; with its own thank-you page, the email is the way). Its form's fields are read by name: `firstname` (or `name`) and `secondname`, `email` (or any email field), `phone`, and `adults` and `children` (or `visitors`) for `persons`. The booking fills in `booking_date` (its first day) and `booking_time` for a time slot. A booking waiting for your approval starts its agreement, and an edited booking does not start a second one. The paid editions' separate resources are not listed yet: their bookings start the one workflow.

= Does it work with FluentBooking? =

Yes, since 1.12.0. Open SignSealer → Bookings. Under FluentBooking, the first row is every event type; each active event type is listed under it, by its calendar, for any that should start a different workflow. A booking starts its agreement once it is scheduled: booked on its page, added by the host, or, for one waiting for the host's confirmation or a payment, once confirmed or paid. SignSealer emails the person the link, and FluentBooking's confirmation (and its receipt page) shows a button to sign. The booking fills in `service_name` (the event type), `booking_date` and `booking_time` (in the calendar's time zone), `persons`, `staff` (the host) and `location` for an in-person place, with the person's name, email and phone. In a group event each person has a booking of their own and signs their own. FluentBooking Pro's group, round-robin and multi-slot bookings have not been tested.

= Does it work with MotoPress Hotel Booking? =

Yes, since 1.13.0, with the free MotoPress Hotel Booking Lite (and the paid version, which has the same hooks). Open SignSealer → Bookings. Under MotoPress Hotel Booking, the first row is every accommodation type; each type is listed under it, for any that should start a different rental agreement. A booking starts its agreement once it is confirmed: by the guest's email link (its default), by you, or by a payment. SignSealer emails the guest the link, and its Booking Confirmed page (and Reservation Received after a payment) shows a button to sign. The booking fills in `booking_date` and `booking_time` (the check-in date and the site's check-in time), `check_out_date`, `nights`, `service_name` (the accommodation types booked) and `persons` (the adults and children in all of them), with the guest's name, email and phone. A booking with several accommodations starts the first one's workflow. A booking imported from another site's calendar (Airbnb, Booking.com) has nobody to sign and starts nothing.

= Does it work with Bookly? =

Yes, since 1.14.0, with the free Bookly (and Bookly Pro, which adds to it). Open SignSealer → Bookings. Under Bookly, the first row is every service; each service is listed under it, for any that should start a different workflow. A booking starts its agreement once it is approved: as it is made, which is Bookly's default, or, for one left pending, when you approve it, when its approve link is followed, or when it is paid for. A booking your staff add in Bookly's calendar starts one too. SignSealer emails the customer the link, and the last step of Bookly's booking form shows a button to sign. The booking fills in `service_name`, `booking_date` and `booking_time`, `persons` and `staff` (the staff member), with the customer's name, email and phone. Bookly Pro's recurring appointments start one agreement for the series. A booking whose time has already passed starts nothing. Bookly's free version announces nothing to other plugins, so SignSealer looks for the bookings Bookly approved as each of its requests ends; a booking made some other way, such as Bookly Pro's WooCommerce add-on, is not seen yet.

= Does it work with Gravity Forms, WPForms, Fluent Forms or Contact Form 7? =

Yes. Open the form's SignSealer settings, in its own plugin: Gravity Forms' form Settings, WPForms' builder Settings, Fluent Forms' Settings & Integrations, or Contact Form 7's SignSealer tab (SignSealer → Forms lists every form with a link there). Choose a workflow and say which of its fields hold the email address and the name (and the last name, when the form asks for it in a field of its own). Every other blank the workflow's document asks is listed, and for each you choose the field that answers it or type the answer to use; one left with neither is asked of the person on a page of your site just before they sign. After they submit, the person is sent straight to the signing page, or the form's own confirmation gains a button to sign — your choice per form. The entry keeps the document's id, title and status, and a note on it says what was sent and what happened. Contact Form 7 keeps no entries, so there the link is carried to its own script and shown under the form's message.

= And Formidable Forms, Ninja Forms or SureForms? =

Yes, since 1.7.0. In Formidable Forms the settings are in the form's Settings, under SignSealer; in SureForms, in the form's Form Settings, under SignSealer, with a Save button of its own. In Ninja Forms SignSealer is an action: open the form's Emails & Actions, add SignSealer, and fill in the person's email and name with merge tags, the way the form's own email is set up. Each answers the agreement's blanks and sends the person on to sign the same way as the plugins above. These three keep the entry as they always have; see who signed in SignSealer.

= Can they sign before the form is sent? =

Yes, since 1.7.0. In a form's SignSealer settings, under **When they sign**, choose **Before the form is sent**. Pressing the form's own button then opens the agreement over the form, on your page; once it is signed, the form is sent by itself and its entry carries the signed document. Somebody who closes it without signing sends nothing, and no entry is kept. The check is made by your site asking SignSealer, not by the browser, so it cannot be skipped. SignSealer emails them the link as well, as it always does.

= A visitor was told "Too many agreements have been started from your connection" =

Since 1.14.4 one visitor's address may start 20 agreements an hour, before payment or from a form: enough for anybody signing their own, and a limit on a script sending your agreements to address after address. Your staff, logged in, are not counted. A form sent past the limit keeps its entry, with a note saying nothing was sent. To change the number, return another from the `signsealer_starts_per_hour` filter (0 for no limit). If your site is behind a proxy that does not pass the visitor's address on, every visitor looks like the proxy: return the address your proxy vouches for from the `signsealer_visitor_ip` filter.

= And Forminator, MetForm, Everest Forms or JetFormBuilder? =

Yes, since 1.8.0. None has a place in its own screens for another plugin's settings, so a form's SignSealer settings are a page of this plugin's: open SignSealer → Forms and press Open settings beside the form. MetForm's, Everest Forms' and JetFormBuilder's lists of forms also have a SignSealer link under each form. Everest Forms and JetFormBuilder work whether a form sends with AJAX or reloads the page; a JetFormBuilder form that signs first is sent with AJAX, so the signing can open over it. Both answer the agreement's blanks, can sign before the form is sent, and send the person on to sign the same way as the others. MetForm shows its messages as plain text, so the button to sign appears under the form rather than in its message.

= Can WordPress do something different depending on an answer? =

Yes, with Uncanny Automator (free). Make an Everyone recipe with the trigger
SignSealer → "A document from a form is signed", choose the form, and choose
the answer it waits for, such as "Are you married? → Yes". Make a second
recipe for "No". Each question on the form is also a token for the recipe's
actions. Developers can use the `signsealer_document_completed` action
instead (see For developers).

= What about Elementor Pro Forms? =

Not yet. Start here names it if it finds it on your site, with the way round it until then: give the form you want signed a public address in SignSealer, and set your form's confirmation to redirect to it (or to a page with the SignSealer agreement block). The person types their name and email again, and nothing is recorded on the entry.

= Where did Settings → SignSealer go? =

Since 1.5.0 SignSealer has its own item in the admin menu, with Start here, Forms, WooCommerce, Templates and Settings under it. Old bookmarks to the Settings pages still work: they take you to the same page in its new place. Since 1.7.0 a form's settings are with the form, in its own plugin, and the shop's under WooCommerce → Settings → SignSealer; SignSealer's Forms and WooCommerce items take you there.

= Does the signer come back to my site afterwards? =

Yes, when your site is on https. After signing, the page offers a way back to the order they came from, or the page the form was on. SignSealer only sends people to sites a business has proven it holds, and connecting this plugin proved this one.

== Screenshots ==

1. SignSealer → Start here: connected to the business, with a card for each
   integration and its steps.
2. SignSealer → Bookings: the agreement each accommodation type starts, and
   the answer to a blank the booking does not fill.
3. SignSealer → Templates: the business's forms and templates, with the
   shortcode for each.
4. With Before payment, the cart sends the customer to sign the agreement
   first.
5. The signing page on your own site, in your theme.

== External services ==

This plugin connects to the SignSealer API at `https://api.signsealer.com` — the service it is a client for. It is required for the plugin to do anything.

**What is sent, and when:**

* When you press Connect: this site's address and a one-time token, so SignSealer can fetch `/wp-json/signsealer/v1/site` on this site, confirm the plugin is running here, and register an application for this site. Then the PKCE challenge, once, as the browser is sent to approve, and, when you have approved, the code SignSealer hands back with the PKCE verifier and this site's application id and secret, exchanged for an access token and a refresh token. The refresh token is exchanged again whenever the access token runs out.
* Once connected: a request for your business's name and address on SignSealer, and the registration of this site's webhook address (`/wp-json/signsealer/v1/webhook`, named "WordPress: " and this site's host) for SignSealer's events. The Settings screen lists that registration, and can ask for a new webhook secret.
* On every call afterwards: an access token, and this site's address in the user-agent header so a support request can be traced.
* When you send a document: the template you chose, the values you filled in, and the signer's name and email address.
* When a WooCommerce order starts a document: the customer's name, email address and phone number if given, the order number, the product's name and quantity, the answers you gave on the product to the agreement's other blanks, any the customer typed on the page that asked them, and the address of the order-received page to send them back to.
* When a customer signs before payment: the name and email address they type, the product's name and quantity, the answers to the agreement's other blanks (yours from the product, and theirs from the page), and the address of the signing page on your site to send them back to. Their session keeps the document's id and signing link until the order is placed.
* When a form submission starts a document: the values of the fields you mapped (email address, name, phone, and any template blanks), any answer you typed for a blank in the form's settings, and the address of the page the form was on.
* When a booking starts a document (LatePoint, Amelia, Simply Schedule Appointments, Event Tickets, Events Manager, Booking Calendar, FluentBooking, MotoPress Hotel Booking or Bookly): the customer's name, email address and phone if given; the service, event or room; the date and time; how many people; the staff member and location, and the check-out date and nights, where the booking has them; the booking's id; and the answers you set for the agreement's other blanks.
* While somebody signs first (before payment, before a form is sent, or before an Amelia or Simply Schedule Appointments booking): requests for whether they have signed yet. If an Amelia booking signed for in advance is never made, a request an hour later to void that document.
* When the "Signed with SignSealer" credit is on: a request for your business's branding, for the credit's wording, while the Settings screen shows it.
* When somebody ticks a box to be texted, at checkout or on a form, before the document starts: their phone number, the words beside the box exactly as they saw them, and which form or order it was, on which site. SignSealer keeps this as the record of their consent to be texted about that document.
* Every ten minutes at most, while an administrator screen or the checkout asks: a request for whether your SignSealer business can send texts, and the wording to show beside a box to be texted.
* When a document completes, and only if your own code or an Uncanny Automator recipe is listening for its answers (the `signsealer_document_completed` action): a request for that document, by its id, tried again up to four more times over about fifteen minutes if SignSealer cannot be reached. Its title, status, your reference and its signers' answers come back, sensitive answers masked, and are handed to that code or recipe. This plugin stores none of it; Uncanny Automator keeps each run's tokens in its own log, as it does for every trigger.
* While you build an Uncanny Automator recipe with SignSealer's trigger, and when that trigger runs: requests for your forms and, for the form chosen, the questions it asks. The questions are kept for an hour.

**What is received:** access and refresh tokens, your business's name, address and branding, this site's webhook registration and its secret, template and workflow lists, a form's questions, document ids and statuses, whether a signer has signed, signing links, a completed document's answers when asked for as above, and whether your business can send texts, with the wording for the box.

SignSealer is operated by Mashdun LLC.
Terms: https://signsealer.com/legal/terms
Privacy policy: https://signsealer.com/legal/privacy-policy
Subprocessors: https://signsealer.com/security/subprocessors

== Changelog ==

= 1.17.1 =
* Saving a form's SignSealer settings keeps each line of "More blanks from
  the form". 1.17.0 joined them into one, so a form with two or more extra
  blanks lost them on the next Save; save it again with the lines as they
  should be.
* Uncanny Automator: "Any form" means the business's forms, and no longer
  includes documents sent from the dashboard or through the API. A third
  choice, "started on this site", narrows a recipe to the documents this
  site started itself (its form plugins' submissions, orders and bookings);
  left as it is, a recipe hears its form wherever it was started.
* When texting waits for the business's own verified number, or the business
  is in the beta, the settings screens say so, instead of "SignSealer could
  not be asked".
* The readme's example of `signsealer_document_completed` no longer warns on
  a form without the question it reads.

= 1.17.0 =
* A form's answers can drive what WordPress does next. When a document
  completes, the plugin asks SignSealer for what its signers answered, just
  after the delivery and without storing any of it, and fires
  `signsealer_document_completed` with one value per question.
  `signsealer_get_answers()` asks for them on demand. A tick box is Yes or
  No; sensitive answers are masked, as your staff see them.
* Uncanny Automator: a trigger, "A document from a form is signed", for
  Everyone recipes. Each question on the form you choose is a token, and the
  trigger can wait for one answer ("Are you married? → Yes"), which works in
  Automator's free edition. One recipe per answer.
* Every form the plugin handles checks its nonce before reading anything
  posted with it, including the SureForms tab and the SignSealer → Forms
  page, and posted lists are sanitized as they are read. A product's
  SignSealer settings are saved only by somebody who may edit that product.
* The plugin's scripts are written out readably, and External services now
  names every request the plugin makes.

= 1.16.2 =
* The page SignSealer reads to confirm the plugin is running here,
  `/wp-json/signsealer/v1/site`, shows only a SHA-256 of the connection
  attempt's token, never the token itself.
* The plugin's stylesheets and scripts are files of their own, under
  `assets/`, loaded with `wp_enqueue_style()` and `wp_enqueue_script()`,
  and given what they need as data. The sign button's colour, which you
  choose, is the one style still written on the page.
* Everything the plugin prints is escaped as it is printed. Its own pages
  in a block theme are framed by the theme's header and footer as
  WordPress itself prints them.
* A form the plugin draws for a visitor is read only once its nonce has
  been checked. A page left open too long is shown again to fill in.
* Bookly: the button on the last step of the booking form needs the token
  Bookly's own form sends with every step.

= 1.16.1 =
* Every form the plugin draws for a visitor, and the question an Amelia
  booking page asks before it books, carries a nonce that is checked
  before anything is started. A page left open too long is shown again,
  to send once more; an Amelia page kept by a cache past its nonce lets
  Amelia book, and the agreement opens just after.
* The plugin's own pages are built as text, with no output buffer left to
  other code.
* The notice that SignSealer has ended the connection shows on the
  Dashboard, the Plugins screen and SignSealer's own screens, not on
  every admin screen; the Plugins screen's "connect" notice can be
  dismissed.
* SignSealer → WooCommerce has a menu address of its own, which leads to
  WooCommerce → Settings → SignSealer as before.

= 1.16.0 =
* Amelia: pressing Book opens the agreement over Amelia's own form, and the
  booking is made once it is signed. Bookings Amelia takes payment for on
  routes of its own (Stripe, WooCommerce, Mollie, Razorpay) are made first,
  and the agreement opens over the page just after.
* Simply Schedule Appointments: the agreement opens over the page as soon
  as the booking is made, or on the page its form sends people to.
* Where the agreement opens just after the booking, closing it without
  signing leaves a button to sign on the page; the email still goes, with
  the link.
* An agreement started before an Amelia booking that is never made is
  voided an hour later. One already signed by everyone cannot be, and
  SignSealer → Bookings says so.

= 1.15.0 =
* A setting under SignSealer → Settings → The sign button: show a small
  "Signed with SignSealer" line, linking to signsealer.com, under the
  signing button block and the `[signsealer_sign]` shortcode, for your own
  business's forms. It is off unless you turn it on, and nothing else the
  plugin shows gets it. A business with white label is not offered it.

= 1.14.5 =
* If SignSealer does not answer just after you connect, SignSealer's
  screens in WordPress now ask again, at most once a minute, until this
  site knows its business and its webhook is registered. Until now
  "Reload to try again" asked nothing, and the signing button and signed
  statuses waited until the connection was forgotten and made again.
* Refreshing the connection's token keeps the business's name and address.
  The first refresh after connecting dropped them, and from then on the
  signing block and shortcode showed visitors nothing.

= 1.14.4 =
* Security: a Formidable Forms answer is no longer passed through
  `maybe_unserialize()`. Formidable's own decoding, which only makes
  arrays, is all that runs on what a visitor typed.
* The connection's token is refreshed by one request at a time. Two at once
  could present a refresh token SignSealer had just rotated, and SignSealer
  then ends the connection. If SignSealer does end it, every admin screen
  now says so, with a button to connect again.
* Agreements started by visitors -- before payment, and from a form, before
  or after it is sent -- are limited to 20 an hour from one address (the
  `signsealer_starts_per_hour` filter changes it; `signsealer_visitor_ip`
  names the address behind a proxy). Past it nothing is sent and no consent
  to text is recorded. A WPForms or Fluent Forms submission kept as spam
  starts nothing.
* A webhook delivery sent again under a different event id is recognised
  as the repeat it is.
* Forgetting the connection now forgets the webhook's signing secret and any
  unfinished connection attempt too; connecting again gets the endpoint a
  new secret by itself.
* A document's status is kept only for documents this site started, not
  for every document the business sends.

= 1.14.3 =
* SignSealer → Bookings says a button to sign shows on the booking plugin's
  own confirmation wherever it has room for one, not on LatePoint's alone,
  and its row for every service no longer shows an id of 0.
* The directory's screenshots are of the screens as they are now: Start
  here, Bookings, Templates, the cart and the signing page.

= 1.14.2 =
* Plugin Check reports nothing at any severity, with every category, error
  and warning included: JetFormBuilder's sign-first refusal is thrown in
  plain steps (written as one expression, it stopped the escaping check),
  and Amelia's services are read with the table as a query placeholder.

= 1.14.1 =
* Start here has a card of its own for each of Amelia, LatePoint and Simply
  Schedule Appointments, each linking its own step-by-step guide, where one
  card used to stand for the three.
* Elementor Pro Forms is named as not supported, rather than not supported
  yet, with MetForm, which works with Elementor, as the way to sign from an
  Elementor site.

= 1.14.0 =
* Bookly. Its services are set up on SignSealer → Bookings: one row for
  every service, and one for each. A booking starts its agreement once it
  is approved (as it is made, by Bookly's default, or later by you, its
  approve link or a payment), with the service, the date and time, how
  many people and the staff member filled in, and the last step of
  Bookly's booking form shows a button to sign.

= 1.13.0 =
* MotoPress Hotel Booking. Its accommodation types are set up on SignSealer
  -> Bookings: one row for every type, and one for each. A booking starts
  its rental agreement once it is confirmed (by the guest's email link, by
  you, or by a payment), with the check-in date and time, the check-out
  date, the nights and everybody staying filled in, and its Booking
  Confirmed page shows a button to sign. Imported bookings start nothing.

= 1.12.0 =
* FluentBooking. Its event types are set up on SignSealer → Bookings: one
  row for every event type, and one for each. A booking starts its
  agreement once it is scheduled (booked, added by the host, or confirmed
  or paid after waiting), with the event type, the date and time in the
  calendar's zone, the host and an in-person place filled in, and
  FluentBooking's confirmation shows a button to sign.

= 1.11.0 =
* Booking Calendar. Under SignSealer → Bookings, choose the workflow every
  booking starts. Whoever booked is emailed the link to sign, with the date
  (and time, for a time slot), how many people, and their name, email and
  phone from its form, and Booking Calendar's own message after booking
  shows a button to sign. Both its default form and the one it made before
  10.x are read.

= 1.10.0 =
* Events Manager. Its events are set up on SignSealer → Bookings: one row
  for every event, and one for each event to come. A booking starts one
  agreement for whoever booked, for the spaces they took, with the event's
  name, date, time, location and tickets filled in, and Events Manager's
  own message after booking shows a button to sign. A booking waiting for
  approval starts it; one waiting on a payment starts it once approved; a
  rejected or cancelled one starts nothing.

= 1.9.0 =
* Event Tickets. Its RSVPs and Tickets Commerce's tickets are set up on
  SignSealer → Bookings: one row for every ticket and RSVP, and one for each
  ticket of the events to come. Whoever booked is emailed the link to sign,
  one agreement for each ticket in their order, and the event fills in its
  name, date, time, venue, organizer and how many people. The RSVP's message
  and the order page show a button to sign. An RSVP of "not going" starts
  nothing, and a paid ticket starts its agreement once it is paid. RSVPs
  made the way Event Tickets did before 5.30 work too.

= 1.8.0 =
* Forminator and MetForm. A form's SignSealer settings are a page of this
  plugin's, reached from SignSealer → Forms (and, for MetForm, from a
  SignSealer link under each form in its list). Each can sign before the
  form is sent, or after: straight to the signing page, or a button to
  sign. MetForm's messages are plain text, so its button appears under the
  form. Until now Start here called both "not supported yet".
* Everest Forms and JetFormBuilder, the same way, with a SignSealer link
  under each form in their lists; with AJAX or without. A JetFormBuilder
  form that signs first is sent with AJAX. Start here now names only
  Elementor Pro Forms as not supported yet.
* Amelia, LatePoint and Simply Schedule Appointments. Under the new
  **SignSealer → Bookings**, choose the workflow a booking of each service
  starts. The person who booked is emailed the link to sign; the booking
  fills in the service, the date and time, how many people, who runs it and
  where, and the owner chooses or types the answer to anything else the
  agreement asks. LatePoint's confirmation step shows a button to sign. A
  booking saved again starts nothing a second time.

= 1.7.1 =
* A form's **What the agreement asks** now lists the boxes on an uploaded
  PDF that the sender fills in, such as the equipment and the pickup and
  return dates on a rental agreement, matched to the form's fields of the
  same name. Before, they were not listed, and the start was refused unless
  they were typed under **More blanks from the form**. Needs SignSealer's
  list of a workflow's sender boxes (00478).

= 1.7.0 =
* A form's SignSealer settings are with the form, in its own plugin:
  Gravity Forms' form Settings, WPForms' builder Settings, Fluent Forms'
  Settings & Integrations, and Contact Form 7's editor, each under
  SignSealer. **SignSealer → Forms** lists every form, what it starts and a
  link to its settings. Nothing you had set up changes.
* The shop's settings are under **WooCommerce → Settings → SignSealer**, beside
  WooCommerce's own; SignSealer → WooCommerce takes you there, and so do old
  bookmarks.
* A template that asks for something the plugin does not fill no longer stops
  the signing with SignSealer's "… is required". The plugin reads the blanks
  each workflow asks from SignSealer:
  * a form's settings list them, each with the field that answers it (the one
    that looks like it is chosen for you) or an answer to use every time, and
    say which are not answered yet;
  * a product's agreement lists them, each with a box the shop fills in or
    leaves for the customer;
  * before payment the signing page asks the customer for the rest, beside
    their name and email; and once they have signed in its frame, it moves
    on by itself, without their pressing "I have signed it";
  * after payment, an order whose agreement still needs something waits for
    the customer: its Sign link opens a page of your site that asks, then
    starts the agreement and goes on to sign it. The order notes say so.
* Formidable Forms, Ninja Forms and SureForms. Formidable's settings are in a
  form's Settings, SureForms' in a tab of its Form Settings, and Ninja Forms
  has a SignSealer action beside a form's email and success message, its
  details filled in with merge tags.
* A form whose agreement asks something the form does not is no longer
  refused: the person is asked for it on a page of your site, just after
  submitting, and the agreement starts once they answer. "Nothing here" for
  such a form shows the link to that page in the form's confirmation.
* A form that asks for the first and last name separately names the person by
  both: choose the second as the **Last name field**.
* A form can sign before it is sent, in all seven form plugins: pressing its
  button opens the agreement over the form, and the form is sent once it is
  signed, its entry carrying the signed document. Nobody who does not sign
  leaves an entry. Your site asks SignSealer whether it is signed before it
  accepts the form.
* The link to sign in a form's confirmation, on the thank-you page and on the
  signing button is a button, with room around it: SignSealer blue, a colour
  of your own, or your theme's buttons (SignSealer → Settings).
* WPForms: a form made from one of WPForms' templates and not saved since
  showed an empty SignSealer section. It shows its settings.

= 1.6.3 =
* Tells WooCommerce that the plugin works with the block cart and checkout,
  which it already did: the order hook, the refusal of an unsigned order,
  the "text me" box and the cart's button each have a block half. WooCommerce
  no longer marks the plugin incompatible on the Features screen or offers to
  switch your shop back to the classic checkout because of it.

= 1.6.2 =
* With agreements signed before payment, the cart's checkout button reads
  "Sign the agreement" and goes to the signing while anything is unsigned,
  on the classic cart and the cart block alike. The checkout page itself
  sends a customer back to the signing rather than letting them fill in a
  form that cannot be placed. The checkout still refuses an unsigned order.
* The signing page before payment is drawn in the theme's own header and
  footer on a block theme, and has a look of its own: a list of what needs
  signing, a card for who is signing, labelled fields and proper buttons.

= 1.6.1 =
* An order or a form entry no longer goes back to "draft" just after its
  agreement was sent. SignSealer raises a document's creation and its
  sending in the same instant, and the two can reach your site in either
  order; the plugin now keeps "sent" from the moment it sends, and
  "signed" once it has been told so at checkout, so a delivery behind
  either is not believed and no "is now draft" note is added.

= 1.6.0 =
* The link can go by text as well as email. When your SignSealer plan
  includes texting, WooCommerce can ask at checkout whether the customer
  wants the link by text (SignSealer, WooCommerce), and each form under
  SignSealer, Forms can name a tick box as its texting consent field. A
  ticked box, and the phone number given, are recorded at SignSealer as the
  person's consent, in the words beside the box, before the agreement is
  sent, so the first text can go.
* Nothing to be texted is offered when the business cannot text: on a plan
  without texting, or on a test account. The screens say which.
* The words to put beside the box come from SignSealer: the opt-in wording
  your business declared, or the one the carriers approved on SignSealer's
  own forms, with your business's name.

= 1.5.1 =
* The thank-you page asks for the signature once, near the top. On a block
  theme (such as Twenty Twenty-Five) the "One more step" box came last, after
  the addresses, with a smaller list of the same documents above it; it now
  takes that list's place under the order.
* The Sign buttons on your site (the thank-you page, the block and the
  shortcode) are styled by block themes as well as classic ones. On a block
  theme they were plain links.
* The block's preview in the editor looks like the button your visitors
  will see, rather than a greyed-out one.
* The order's SignSealer box says Signed, Waiting for a signature, Declined
  and so on as a coloured status.
* Tidier cards on Start here: a status no longer wraps oddly under a long
  name, and a card's button and guide link no longer touch.

= 1.5.0 =
* SignSealer has its own item in the admin menu, with Start here, Forms,
  WooCommerce, Templates and Settings under it, instead of three entries
  under Settings. Old Settings addresses still work: they go to the same
  page in its new place, and a connection that was halfway through when you
  updated still finishes.
* **Start here**: what SignSealer does, whether this site is connected, and
  a card for every integration — WooCommerce, WooCommerce Bookings, Gravity
  Forms, WPForms, Fluent Forms, Contact Form 7 and the signing button — that
  says whether its plugin is on this site, whether it is set up, and the
  three steps to set it up, with a link to a step-by-step guide. Form
  plugins it does not work with yet are named, with the way round it.
* **SignSealer → Forms** is always in the menu, and explains itself; a site
  with none of the supported form plugins is told which ones work. The
  WooCommerce choice moved to its own page, which also lists the products
  that need an agreement.
* Connecting: coming back from SignSealer no longer shows "That connection
  attempt has expired" under "Connected" when the page loads twice, and a
  reload after connecting shows the connection rather than an error.
  Pressing Connect again after an attempt that did not finish reuses the
  application the first press registered instead of registering another.
  Turning down the connection on SignSealer's screen now says so. Somebody
  making their SignSealer account while connecting has thirty minutes
  rather than five.
* A link to Start here and Settings beside Deactivate on the plugins screen,
  and a one-line pointer there until the site is connected.

= 1.4.2 =
* Deleting the plugin now removes everything it stored. Until now it left
  the form mappings, the WooCommerce trigger setting, the links from each
  agreement back to its order or form entry, and a few short-lived caches
  in the database after the plugin itself was gone. Notes and agreement ids
  on your WooCommerce orders and form entries stay: they are part of those
  orders' and entries' history.
* That includes sites with a persistent object cache (Redis, Memcached),
  where cached copies are now removed along with the stored ones, and every
  site of a multisite network, not only the one it was deleted from.
* An agreement's status can no longer go backwards. SignSealer's notices
  about one agreement can arrive out of order (they are sent in parallel and
  retried), and a late "sent" arriving after "signed" set the agreement back
  to waiting: the WooCommerce order and the form entry asked for a signature
  that had already been given, and gained a note saying so. The newest
  status now wins, by when it happened.
* Checked by deleting the plugin from a real WordPress, with a persistent
  object cache on, from a single site and from a network, in the test
  suite, and by scanning every file for code PHP 7.4 cannot run.

= 1.4.1 =
* Gravity Forms: "Send them straight to the signing page" and "Show the
  form's own confirmation, with a link to sign" now happen. The plugin
  started the agreement from `gform_after_submission`, which Gravity Forms
  runs only after it has decided what the visitor sees, so the visitor got
  the form's usual confirmation and had to find the link in SignSealer's
  email. It now starts the agreement as soon as the entry is saved, before
  the confirmation is chosen.
* Gravity Forms: a submission Gravity Forms marks as spam no longer starts
  an agreement. Until now a bot's submission sent a real signing request to
  whatever address it typed.
* Checked against the real Gravity Forms, with forms submitted through its
  own submission process, rather than only against a stand-in for it.

= 1.4.0 =
* WooCommerce can ask for the signature before payment. With "Before
  payment" chosen under Settings -> SignSealer, a customer whose cart holds
  a product that needs an agreement signs it on a page of your site, in a
  frame, and the classic checkout and the checkout block will not place the
  order until SignSealer says it is signed. The order then carries that
  document instead of starting another.
* The connection asks for four scopes, not five: the plugin lists templates
  and never changes one, so it no longer asks to.
* SignSealer's own sentence is shown when it refuses something. Until now
  the plugin read the wrong part of the answer and showed only the status.

= 1.3.2 =
* Reconnecting a site no longer registers a second webhook endpoint. The
  check for the one already there read the wrong key in SignSealer's answer,
  so it never found it, and each reconnect added an endpoint that delivered
  every event again.

= 1.3.1 =
* The block's editor script now declares what it needs and carries the
  plugin's version. Without that, a browser kept the previous release's
  editor script until WordPress itself updated, and the block's own words
  in the editor could never be translated, because WordPress only sets up
  a script's translations when it depends on `wp-i18n`.
* Checked against WordPress 7.1.2 with the directory's Plugin Check (every
  category, low severity included: nothing found), the block loaded in the
  editor with no console errors, and the WooCommerce, WPForms, Fluent Forms
  and Contact Form 7 integrations driven end to end.

= 1.3.0 =
* **Connecting is one button.** The settings screen asked for an application
  id and secret, and nothing a site owner could reach issued them. Now the
  plugin registers itself: it mints a one-time token, serves it at
  `/wp-json/signsealer/v1/site`, and SignSealer fetches that page over https
  to confirm the plugin is running here before registering an application
  named after this site. Press Connect, sign in, approve, done. A partner
  with an application of their own can still paste it, under a fold.
* The screen says plainly when the site is not on https, since that is the
  one thing that stops the connection.

= 1.2.0 =
* **WooCommerce Bookings.** A booking the shop confirms starts its agreement
  at once, paid or not; a paid booking starts it under the "paid" trigger.
  The booking's date, time, number of people and resource go to the
  template, and the booking's own screen shows where the agreement stands.
* **Contact Form 7.** The fourth form plugin on Settings → SignSealer forms.
  Its fields are listed by tag name; a sent submission starts the workflow;
  the signing link rides on the form's own answer to a small script that
  sends the person on or adds the link under the message, with the address
  in the message itself when the form is submitted without its script.

= 1.1.0 =
* **WooCommerce.** A product can need an agreement; the order starts it when
  paid or when placed, offers it on the thank-you page, in the customer's
  order email and under My Account, and carries its status on the order
  screen and in the order notes. Compatible with WooCommerce's own order
  tables (HPOS).
* **Gravity Forms, WPForms and Fluent Forms.** One screen under Settings maps
  a form to a workflow: the email, name and phone fields, template blanks
  filled from fields, and whether the person is sent straight to the signing
  page or given a link in the confirmation. The entry keeps the document and
  its status, with a note for what was sent and what happened.
* **The way back.** A document started here carries the page to return the
  signer to — the order, or the page the form was on — which SignSealer
  honours because this site is the one the connection was made on. Needs
  https; on http the signed page simply has no button.
* A `signsealer_woocommerce_participant` filter and a
  `signsealer_form_participant` filter, for a site that keeps a template's
  blank somewhere the plugin cannot guess.

= 1.0.1 =
* **The settings screen told you to do something that cost money.** It said
  "In SignSealer under Developers → Webhooks, add this address" on a screen
  where connecting had already added it. Following that made a second endpoint
  for the same address, and two endpoints deliver every event twice and are
  counted twice. It now says it is registered, says not to add another, and
  keeps the manual form for the one case it is for.
* **The templates screen said you had no forms when it could not ask.** If the
  API did not answer, the screen showed the error and then both tables saying
  "None yet. Make one in SignSealer under Workflows" — so a business with forty
  forms was told it had none and invited to make them again. A failure now
  replaces the tables rather than captioning them.
* **A connection with no application behind it reported itself as connected.**
  Refreshing a token needs the application id and secret beside the refresh
  token; without them the plugin emitted two PHP notices, posted an empty
  `client_id`, and put the API's answer — "client_id is required" — at the top
  of an admin screen. Such a connection is now simply not a connection, and the
  screen offers connecting again.
* `wp_safe_redirect` with an `allowed_redirect_hosts` filter on the OAuth
  hand-off, fenced to the host `SIGNSEALER_API_BASE` resolves to.
* Tested up to WordPress 7.1. Translation template added.

= 1.0.0 =
* First release. OAuth connection, a self-registering and verified webhook receiver, the templates and forms screen, a block and a shortcode.

== Upgrade Notice ==

= 1.17.1 =
Saving a form's settings keeps every line of its extra blanks, which 1.17.0 joined into one. Automator's "Any form" is the business's forms only.

= 1.17.0 =
A form's answers for your own code and for Uncanny Automator recipes, asked for when a document completes. The plugin stores none of them.

= 1.16.2 =
Stylesheets and scripts in files of their own, output escaped as it is printed, and no token on the plugin's public page.

= 1.16.1 =
Nonces on the forms the plugin draws for visitors and on Amelia's question; fewer admin notices.

= 1.16.0 =
Amelia and Simply Schedule Appointments: the person who booked signs on the page, Amelia before it books.

= 1.15.0 =
An optional "Signed with SignSealer" line under the signing button, off unless you turn it on.

= 1.14.5 =
Connecting finishes by itself when SignSealer did not answer at first, and the signing button keeps its business after the token is refreshed.

= 1.14.4 =
Security and reliability fixes from a review: no unserializing of form answers, one token refresh at a time, and a limit on agreements started by one visitor.

= 1.14.3 =
Wording on SignSealer → Bookings, and new screenshots.

= 1.14.2 =
No change in what it does: Plugin Check reports nothing at any severity.

= 1.14.1 =
Start here: a card and a guide for each of Amelia, LatePoint and Simply Schedule Appointments.

= 1.14.0 =
Bookly: an appointment booked on its form can now start its agreement.

= 1.13.0 =
MotoPress Hotel Booking: a confirmed stay can now start its rental agreement.

= 1.12.0 =
FluentBooking: a meeting or lesson booked on its pages can now start its agreement.

= 1.11.0 =
Booking Calendar: a booking on its calendar can now start its agreement.

= 1.10.0 =
Events Manager: a booking for an event can now start its waiver or agreement.

= 1.9.0 =
Event Tickets: an RSVP or a ticket for an event can now start its waiver or agreement.

= 1.8.0 =
Forminator, MetForm, Everest Forms and JetFormBuilder: a form submission in each can now start a signing, before or after the form is sent. Amelia, LatePoint and Simply Schedule Appointments: a booking can start its agreement.

= 1.7.1 =
A rental agreement's pickup and return boxes, filled in by the sender, are listed with the form's other blanks.

= 1.7.0 =
Formidable Forms, Ninja Forms and SureForms. A form can sign before it is sent. Form settings move into each form plugin, the shop's into WooCommerce → Settings. A template's extra blanks are answered by you or asked of the person. The link to sign is a button.

= 1.6.3 =
WooCommerce no longer marks the plugin incompatible with its block cart and checkout.

= 1.6.2 =
With signing before payment, the cart sends customers to sign first, and the signing page looks like part of your shop.

= 1.6.1 =
An order's agreement no longer shows as "draft" for a moment after it is sent.

= 1.6.0 =
Customers can ask for the signing link by text as well as email, at checkout or on a form, when your SignSealer plan includes texting.

= 1.5.1 =
The Sign button is styled on block themes, and the thank-you page asks for the signature once, near the top.

= 1.5.0 =
SignSealer moves from Settings to its own menu item, with a Start here page that explains each integration. Old links still work.

= 1.4.2 =
Deleting the plugin now removes everything it stored.

= 1.4.1 =
Gravity Forms submissions now go straight to the signing page, and spam entries start nothing.

= 1.4.0 =
WooCommerce can require the agreement to be signed before payment.

= 1.3.2 =
Reconnecting no longer adds a duplicate webhook endpoint.

= 1.3.1 =
The block's editor script updates with the plugin and can be translated.

= 1.3.0 =
Connecting no longer asks for an application id and secret. Already
connected sites are unaffected.

= 1.2.0 =
WooCommerce Bookings and Contact Form 7. Nothing changes for a site that uses
neither.

= 1.1.0 =
WooCommerce, Gravity Forms, WPForms and Fluent Forms integrations, and the
signer is sent back to your site afterwards. Nothing changes for a site that
uses none of them.

= 1.0.1 =
Three screens that told you something untrue. One of them, if you did what it
said, registered a second webhook endpoint and doubled what you were billed
for deliveries.

= 1.0.0 =
First release.
