Called when a customer pastes a payment reference from a previous attempt — typically
after a scan that was paid for but never completed.
The reference may be Oyster's own, or the external_reference the vendor
supplied when confirming a collection on its own gateway. The vendor's is
matched only within that vendor and only against its own collections: the
vendor chooses the value, so two vendors collide on one routinely.
Rate limited per caller and email. A vendor-chosen reference may be
sequential, so the email check cannot be the only ceiling.
Checks, in order (the first failure wins):
- Reference exists, as either of the two above → else
not_found - Belongs to this vendor → else
wrong_vendor - Terminal status (a pending row is refreshed against the provider first) →
elsepending, orfailedfor a payment that did not succeed - A storefront-collected payment still unconfirmed long after it was raised →
unconfirmed - Email matches the one captured at payment → else
wrong_email - Value not yet delivered → else
used
Step 4 applies only to payments collected on the vendor's own gateway. Oyster
has no way to settle one, so once enough time has passed pending would be
telling the customer to wait for something that cannot arrive.
Resumable (resumable: true): the customer paid but never got their scan. The widget
skips checkout and threads batch_id + the reference into POST /skin/analyze.
Used (reason: "used"): the reference is spent — it buys exactly one scan and that
scan already ran. The response carries the delivered batch_id when the scan is still
readable, so the widget can show the customer the results they already paid for rather
than a dead end. Re-running the analysis is NOT offered; this is a read.
Because the email check runs before both outcomes, a leaked reference alone reveals
nothing — the results read is gated on the same proof of identity as a resume.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||