# Scan API

The Scan API records a barcode or QR scan, then correlates it to a pass. This creates a reliable “in-store / at-venue” signal that downstream systems can use for redemption flows, attendance tracking, or CRM automation.

<details>

<summary><strong>Real-world examples</strong></summary>

* **Retail loyalty**: record a scan at checkout to trigger post-visit automation.
* **Event entry**: record gate scans to track attendance and prevent reuse.
* **Voucher redemption**: record scans to mark an offer as consumed.

</details>

### When Scan API is needed

Barcode/QR hardware can read the value displayed on a pass. The Scan API is the piece that makes that scan actionable in The Wallet Crew.

When the Scan API is invoked, The Wallet Crew can:

* identify which pass was scanned
* record the scan event with timestamp and symbology
* emit downstream events for connected systems

{% hint style="info" %}
The Scan API does not replace operational validation logic. It provides a scan record and correlation. Redemption rules, anti-fraud, and privilege consumption depend on the chosen workflow.
{% endhint %}

### Endpoint

The Scan API is exposed as a tenant-scoped endpoint:

```http
POST /api/{tenantId}/scans
```

### Authentication and authorization

The Scan API requires an identity allowed to record scans.

Common patterns are:

* **API key** authentication (`X-API-KEY`) for server-to-server calls from a POS backend.
* **OAuth 2.0 Bearer token** for admin/user identities.

The effective authorization model depends on tenant configuration. In the OpenAPI definition, this endpoint requires the `PassScan.Scan` scope.

### Request payload

The request is a JSON object with two fields:

* `data`: the raw decoded value read by the scanner.
* `type`: the scan input type (symbology).

Example:

```json
{
  "data": "0123456789012",
  "type": "code128"
}
```

#### `type` values

`type` is an enum. Common values are:

* `qrcode`
* `pdf417`
* `code128`
* `ean13`
* `datamatrix`
* `nfc`
* `manual` (when staff types a code)

{% hint style="warning" %}
`data` is treated as an opaque identifier. Keeping it stable matters more than keeping it human-readable. Formatting changes (trim, leading zeros, separators) are common causes of correlation failures.
{% endhint %}

### Response

On success, the API responds with the pass identifier correlated from the scan:

```json
{
  "passId": "..."
}
```

If correlation fails, the API can return `404`.

### Implementation notes

A scanning system can call the Scan API either directly (when network access is available) or via a backend relay.

Calling from a backend relay is common. It keeps secrets out of scanning devices and allows enrichment, logging, and retry policies.

### Validate the integration

A minimal validation sequence is:

1. Use a real pass issued by The Wallet Crew.
2. Scan its barcode/QR and capture the decoded value.
3. Call `POST /api/{tenantId}/scans` with `data` and `type`.
4. Confirm a `201` response and a non-null `passId`.
5. Confirm the downstream signal is received (for example, `wallet_scanned` in Bloomreach).

### Troubleshooting

#### `404 Not Found`

The scanned value did not match any pass.

Common causes are barcode formatting differences, missing prefixes/suffixes, or a mismatch between template barcode configuration and scanner decoding.

#### `400 Bad Request`

The payload failed validation.

Common causes are missing fields, `data` length outside limits, or an invalid `type`.

#### `401 Unauthorized`

The credentials are missing, invalid, or do not have the required scope.

### FAQ

<details>

<summary><strong>Does every barcode scan trigger a CRM event?</strong></summary>

Only scans recorded through the Scan API are known to The Wallet Crew as scan events.

When recorded, the scan can be forwarded to connected systems such as Bloomreach as a `wallet_scanned` event.

</details>

<details>

<summary><strong>Should the Scan API be called from the scanning device or from a backend?</strong></summary>

A backend relay is the most common setup because it keeps API keys server-side and allows retries.

Direct calls from devices can work, but it increases secret handling and device management constraints.

</details>

<details>

<summary><strong>What should be stored in <code>data</code>?</strong></summary>

The raw decoded value that is configured in the pass barcode/QR.

Keeping that value stable across systems is the key requirement.

</details>
