# Best practices

Checks to run on the scan page once the flow is built.


Run these checks on the page a customer sees after a tap. They cover private
browsing, a reload during the request, and the session the second tap reuses.

Build the scan from the brief on
[Verifications](/docs/api/verifications#hand-it-to-your-coding-agent).
Run this page once that flow is written.

## Hand the checklist to your coding agent

Once the build is done, copy this brief into Claude Code, Cursor, or whatever
you build with. It walks the same checks as the table below.

```text
The TAGBASE scan flow is in place. Run this checklist on the page a
customer sees. Fix anything that fails. Read these pages first:

https://platform.tagbase.io/docs/guides/best-practices
https://platform.tagbase.io/docs/api/verifications
https://platform.tagbase.io/docs/api/sessions

1. Private browsing. Open the result page in a private window after a
   first tap that returned pending. The page tells the customer to leave
   private browsing and tap again. Pending in that window is not a step
   that is still working. The page does not ask the customer to keep
   tapping. TAGBASE returns no private-browsing field. The check runs in
   the customer's browser.
2. Reload while loading. Start a tap and reload before the verdict
   arrives. The page finishes the one request already in flight, or it
   reads the verification you already stored. It does not send a second
   POST for that tap.
3. Reload while pending. With status pending, reload the stable page
   (the address is the verification id, vrf_…). The page still shows
   pending and the same session id (ses_…). It does not POST, and it
   does not open a new session.
4. One POST per tap. Each tap produces one
   POST /api/v1/tags/:tag_id/verifications from your server. A reload, a
   second render, or a return to the tap URL with the same query string
   does not POST those parameters again. A second tap is a new URL with
   new parameters, and it sends the stored session id in
   relationships.session.
5. Session reuse. The second tap sends the session id from the first
   response. The session id in that response matches the one you sent,
   and the status is valid or invalid.
6. Stale session. Hold a session id older than the tag's
   session_duration (600 seconds unless the tag sets another value) and
   submit a new tap with it. TAGBASE returns pending and a new session
   id. Store that id. Drop the old one. Show pending for the new session.
7. Terminal status. valid shows the item as genuine. invalid warns the
   customer that the item may be a copy. Neither state shows a spinner,
   a second-tap prompt, or the private-browsing message.
```

## What each check looks for

| Check | Passes when |
| --- | --- |
| Private browsing | A private window with `pending` asks the customer to leave private browsing and tap again. |
| Reload while loading | A reload during the request finishes that one POST, or reads the stored verification. |
| Reload while pending | The stable page still shows `pending` and the same session id. |
| One POST per tap | The same query string is posted once. The next tap posts new parameters with the stored session. |
| Session reuse | The second tap sends the stored session id, and the response session id matches it. |
| Stale session | A session older than `session_duration` comes back as a new `pending` session. You store the new id. |
| Terminal status | `valid` shows the item as genuine. `invalid` warns that the item may be a copy. The loading spinner, the second-tap prompt, and the private-browsing message are hidden. |

POST the scan from your server. The customer's page reads the verdict you
stored. A reload of the tap URL, with the same query string, redirects to the
verification you already created.

