=== Post Coverage Claim Lookup ===
Contributors: postcoverage
Tags: claims, delivery, shipping, customer service, package protection
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 1.2.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Let customers check a Post Coverage delivery claim on any WordPress page, with a shortcode or a block. WooCommerce is not required.

== Description ==

Post Coverage is package protection for online stores. When a delivery goes missing, arrives damaged, or is stolen, the customer has a coverage reference and a private access code, and this plugin turns those into an answer on your own site.

Add the Claim lookup block to a page, or use the shortcode:

`[post_coverage_claim]`

The shortcode accepts `heading`, `heading_level` (2, 3 or 4) and `class`, for example `[post_coverage_claim heading="Where is my parcel?" heading_level="3"]`.

The visitor enters their reference and access code and sees the claim's status, its progress so far, the customer-visible updates from the Post Coverage support team, and a link to continue on Post Coverage, where replies and photos are handled.

**Sandbox release.** The Post Coverage API is in sandbox and does not issue live coverage yet.

= No store required =

This plugin does not need WooCommerce, or any store at all. It works on a marketing site, a help centre, a brand's contact page: anywhere a customer might go looking for their parcel. If you do run a WooCommerce store, the separate Post Coverage for WooCommerce plugin adds protection at checkout; the two work side by side.

= How the calls are made =

The Post Coverage API accepts browser requests from Post Coverage's own sites only. A page on your domain cannot call it directly, so this plugin calls it from PHP and adds REST routes under `post-coverage/v1` on your site for the form to talk to.

Every visitor's lookup therefore leaves through your server's address, and Post Coverage counts requests per address: 40 every five minutes. The plugin is built around that number:

* Repeat lookups of the same reference are answered from a cache that lives a minute, and cost nothing.
* Each visitor has a small allowance of their own, so one person refreshing cannot spend the site's.
* The plugin stops at 20 of the 40 by default, leaving room for any other Post Coverage integration on the same server. The Post Coverage for WooCommerce plugin counts its requests in the same place, and this plugin's ceiling is measured against the two plugins' requests together.
* When the allowance is gone the visitor is asked, plainly, to come back in a few minutes.

= What this plugin does not do =

It holds no API key. The claim routes it uses are authenticated by the reference and access code the customer already has, and a merchant key would add risk while buying nothing.

It does not accept replies or evidence. Those belong on Post Coverage, and every result links there, carrying the reference and code in the link's fragment so they never reach a server log.

It sends no email and stores no customer details.

= Source code =

The plugin has no build step. The block editor script, `src/js/block.js`, and the front-end script, `assets/js/claim.js`, are the files WordPress loads, exactly as written.

== External services ==

This plugin connects to the Post Coverage API, a service run by Post Coverage, to look up delivery claims. The lookup form cannot work without it. The API address is set under **Settings > Post Coverage**. It defaults to the Post Coverage sandbox API at `https://3feo7wip5b.execute-api.us-east-1.amazonaws.com`, an Amazon Web Services (API Gateway) address that Post Coverage runs its API on. That is the host to allow if your server restricts outgoing connections.

Every call is made from your web server, never from the visitor's browser, and only when a visitor submits the form. Merely showing the form on a page sends nothing.

What is sent, and when:

* **Claim lookup** (`POST /public/claims/lookup`): when a visitor submits the form. Sends the coverage reference and the access code the visitor typed, and a page size for the claim's history.
* **Reporting an issue** (`POST /public/claims`): only if you have turned on "Reporting an issue", and only when a visitor whose reference and code have just been checked chooses to report a problem. Sends the reference, the access code, the kind of problem (lost, damaged or stolen) and, only if the visitor chose one, whether they would like a replacement or a refund. Nothing is chosen for them. When the store sent the order's products, the visitor also ticks which shipped items were affected (all are ticked to start with), and their positions in the order and quantities are sent. If the Post Coverage API does not accept those items or that choice yet, it refuses the report without saving anything; the plugin then sends the report again without the items (the report is then about the whole parcel) and, if that is refused too, without the choice, and tells the visitor what was not kept. Each attempt counts against the same request allowances.

Every request carries a user agent naming this plugin, its version and your site's home address. No API key is sent, because none is held.

Never sent: the visitor's name, email address, phone number, postal address, payment details or IP address. The form does not ask for any of them.

The result also links the visitor to the Post Coverage website, at the site address in the settings (https://www.postcoverage.com by default), where they can reply and add photos. That link is only followed if the visitor clicks it.

Post Coverage terms of service: https://www.postcoverage.com/terms/
Post Coverage privacy policy: https://www.postcoverage.com/privacy/

== Installation ==

1. In **Plugins > Add New > Upload Plugin**, upload `post-coverage-wp.zip`, or copy the `post-coverage-wp` folder into `wp-content/plugins/`.
2. Activate it.
3. Visit **Settings > Post Coverage** and confirm the API base URL and the Post Coverage site address.
4. Add the Claim lookup block, or the `[post_coverage_claim]` shortcode, to any page.

There is nothing to build and nothing to install alongside it. No Composer, no npm, no API key.

== Frequently Asked Questions ==

= Does this need WooCommerce? =

No. It has no dependency on WooCommerce or on any store plugin.

= Why does my server make the call instead of the browser? =

Post Coverage's API allows browser requests from its own origins. A request from your domain is refused before it starts, so the form posts to WordPress and WordPress calls the API.

= Why might a visitor be asked to wait? =

Because everyone on your site shares one allowance at Post Coverage: 40 requests every five minutes from one server address. The plugin caches recent answers and gives each visitor a small allowance of their own so that ceiling is rarely felt, but when it is, the message says so calmly and the wait is minutes, not hours.

= Is the access code stored anywhere? =

No. It is sent to Post Coverage to open the claim and is never written to the database, the page, a log or a cache key. The cache that holds a recent answer is keyed by a hash of the code, not the code.

= Can a customer reply, or upload a photo, from my site? =

Not from this form. Replies and evidence are handled on Post Coverage, and every result carries a link there with the reference and code already filled in.

= Can a customer report a new issue from my site? =

Optionally. Turn on "Reporting an issue" in Settings > Post Coverage. The option to report only appears after a reference and access code have been checked and found to have no claim against them yet. The customer can also say whether they would like a replacement or a refund, or leave it for later.

= What happens if Post Coverage cannot be reached? =

A lookup says so and can be tried again. A report is different: if the answer is ambiguous the plugin never repeats it, and asks the customer to check their claim before reporting again, so one delivery problem cannot become two reports.

= Is the plugin translatable? =

Yes. The text domain is `post-coverage-wp` and a template is in `languages/post-coverage-wp.pot`. Translations placed in the plugin's `languages/` folder are loaded, including those for the block editor script.

== Privacy ==

When a visitor uses the form, their coverage reference and private access code are sent from your server to the Post Coverage API over HTTPS. Nothing about the visitor's identity, contact details or payment is sent, or asked for.

Stored on your site, briefly:

* The claim summary that was shown, for up to a minute, so a repeat view costs nothing. It is keyed by a hash of the reference and code.
* Counters for the request allowance: one per visitor, keyed by a hash of the visitor's IP address, which expire within five minutes, and one count for the whole site, which holds a number and nothing else. The Post Coverage for WooCommerce plugin, when it is installed, counts in that same site-wide count.

Not stored, at any point: the access code itself, or the visitor's IP address.

Uninstalling the plugin removes the settings and all of this stored data. The one exception is the site-wide count while Post Coverage for WooCommerce is still installed: that plugin still counts in it, and removes it when it is uninstalled itself.

== Changelog ==

= 1.2.0 =
* When the store sends an order's products, the issue-report form asks "Which items were affected?", with every shipped item ticked and a quantity for items ordered more than once. The claim view lists them as "Affected items". Product names are shown as plain text.
* The issue-report form now asks "What would you prefer?" and offers store credit or a replacement. Post Coverage starts with store credit, then a replacement (shipping paid by Post Coverage), and refunds only when neither works, so a refund is no longer offered on the form. A claim filed earlier with "A refund" still shows it. If Post Coverage's API does not take store credit yet, the report is sent again without the preference and the visitor is told.

= 1.1.0 =
* The issue-report form asks "Would you like a replacement or a refund?", with "Decide later" selected and no other choice made for the visitor. The claim view shows the answer as "You asked for".
* Until Post Coverage's next update accepts that answer, the form sends the report once more without it and tells the visitor their choice was not kept. That second attempt counts against the same request allowances as any other.

= 1.0.0 =
* First release: claim lookup and status by shortcode or block, a server-side proxy with a short cache, per-visitor and site-wide request allowances, links that carry credentials in the URL fragment, and optional issue reporting.

== Upgrade Notice ==

= 1.2.0 =
Issue reports can name which items were affected, and the form offers store credit or a replacement instead of a refund. No settings change.

= 1.1.0 =
Issue reports can carry the customer's choice of a replacement or a refund. No settings change.

= 1.0.0 =
First release.
