Resolve Scan Test Cases
- Resolve Scan API Test Cases
- Overview
- 1. Successful Scan Resolution (200)
- 2. Bad Request — Validation Errors (400)
- 2.1 Missing requestId
- 2.2 Invalid requestId Format
- 2.3 Missing storeId
- 2.4 storeId Exceeds 255 Characters
- 2.5 Missing scanEvent
- 2.6 Missing scanEvent.id
- 2.7 Invalid scanEvent.id Format
- 2.8 Missing scanEvent.timestamp
- 2.9 Invalid scanEvent.timestamp Format
- 2.10 Missing scanEvent.location
- 2.11 Invalid scanEvent.location Value
- 2.12 Missing scanEvent.value
- 2.13 scanEvent.value Exceeds 1000 Characters
- 2.14 scanEvent.value Not Valid Base64 (OPTICAL Channel)
- 2.15 Missing scanEvent.channel
- 2.16 Invalid scanEvent.channel Value
- 2.17 Empty Request Body
- 2.18 Unknown storeId
- 3. Input Validation — Additional Error Cases
- 4. Internal Server Error (500)
- 5. Response Validation
- 6. Performance
- Test Data Requirements
- Test Execution Notes
- Expected HTTP Status Codes Summary
Disclaimer: This document contains sample content for illustrative purposes only. Organizations should follow their own established best practices, security requirements, and compliance standards to ensure solutions are production-ready.
Resolve Scan API Test Cases
Overview
These test cases validate the ResolveScan API (POST /v1/identity/scan), which Amazon calls whenever a shopper scans their Scan Key Code at the JWO gate or when a store associate scans the associate device to identify the shopper. The API is the company's Identity Connector — it receives the scan event data and returns a resolution that determines whether the shopper is accepted or rejected.
Note: The ResolveScan specification defines two response codes: 200 (resolution) and 500 (server error). The 400 test cases in sections 2 and 3 are recommended input validation for your connector. They are not part of the ResolveScan contract, and the error
messagetext is up to you. Confirm with the Amazon team how the gate behaves when your connector returns a non-200 response.
1. Successful Scan Resolution (200)
1.1 Shopper Entry — ACCEPT via OPTICAL Scan
Objective: Verify a valid shopper scan is accepted and the gate opens
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T17:53:57Z",
"location": "ENTRY",
"value": "dmFsaWRfc2hvcHBlcl9rZXk=",
"channel": "OPTICAL"
}
}
Expected Response (200):
{
"id": "shopper-uuid-001",
"type": "SHOPPER",
"action": "ACCEPT"
}
Expected Result: Gate opens. Shopper is allowed to enter the store.
1.2 Associate Scan — ACCEPT
Objective: Verify a store associate scan is accepted with type ASSOCIATE
Request:
{
"requestId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"storeId": "STORE-001",
"scanEvent": {
"id": "22222222-3333-4444-5555-666666666666",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "YXNzb2NpYXRlX2tleQ==",
"channel": "OPTICAL"
}
}
Expected Response (200):
{
"id": "associate-uuid-001",
"type": "ASSOCIATE",
"action": "ACCEPT"
}
Expected Result: Gate opens.
1.3 Cash Shopper Scan — ACCEPT
Objective: Verify a cash shopper scan is accepted with type CASH (store must support this type)
Request:
{
"requestId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"storeId": "CASH-ENABLED-STORE-001",
"scanEvent": {
"id": "33333333-4444-5555-6666-777777777777",
"timestamp": "2024-02-09T18:05:00Z",
"location": "ENTRY",
"value": "Y2FzaF9zaG9wcGVyX2tleQ==",
"channel": "OPTICAL"
}
}
Expected Response (200):
{
"id": "cash-shopper-uuid-001",
"type": "CASH",
"action": "ACCEPT"
}
Expected Result: Gate opens. Only return the CASH type for stores that support it (see Test Execution Notes).
1.4 Loyalty Scan — ACCEPT
Objective: Verify a loyalty scan is accepted with type LOYALTY
Request:
{
"requestId": "d4e5f6a7-b8c9-0123-defa-234567890123",
"storeId": "STORE-001",
"scanEvent": {
"id": "44444444-5555-6666-7777-888888888888",
"timestamp": "2024-02-09T18:10:00Z",
"location": "ENTRY",
"value": "bG95YWx0eV9zY2FuX2tleQ==",
"channel": "OPTICAL"
}
}
Expected Response (200):
{
"id": "loyalty-uuid-001",
"type": "LOYALTY",
"action": "ACCEPT"
}
Expected Result: Gate opens.
1.5 Exit Gate Scan
Objective: Verify scan resolution at the EXIT gate location
Request:
{
"requestId": "e5f6a7b8-c9d0-1234-efab-345678901234",
"storeId": "STORE-001",
"scanEvent": {
"id": "55555555-6666-7777-8888-999999999999",
"timestamp": "2024-02-09T18:30:00Z",
"location": "EXIT",
"value": "dmFsaWRfc2hvcHBlcl9rZXk=",
"channel": "OPTICAL"
}
}
Expected Response (200):
{
"id": "shopper-uuid-001",
"type": "SHOPPER",
"action": "ACCEPT"
}
Expected Result: Your connector returns a valid resolution for the EXIT location.
1.6 Manual In-Store Scan
Objective: Verify scan resolution when a store associate scans the shopper in-store (MANUAL_IN_STORE)
Request:
{
"requestId": "f6a7b8c9-d0e1-2345-fabc-456789012345",
"storeId": "STORE-001",
"scanEvent": {
"id": "66666666-7777-8888-9999-aaaaaaaaaaaa",
"timestamp": "2024-02-09T18:15:00Z",
"location": "MANUAL_IN_STORE",
"value": "dmFsaWRfc2hvcHBlcl9rZXk=",
"channel": "OPTICAL"
}
}
Expected Response (200):
{
"id": "shopper-uuid-001",
"type": "SHOPPER",
"action": "ACCEPT"
}
Expected Result: Shopper is identified via associate-assisted scan.
1.7 RADIO Channel Scan
Objective: Verify scan resolution when channel is RADIO (e.g., badge scan)
Request:
{
"requestId": "a7b8c9d0-e1f2-3456-abcd-567890123456",
"storeId": "STORE-001",
"scanEvent": {
"id": "77777777-8888-9999-aaaa-bbbbbbbbbbbb",
"timestamp": "2024-02-09T18:20:00Z",
"location": "ENTRY",
"value": "radio_badge_key_plain_text",
"channel": "RADIO"
}
}
Expected Response (200):
{
"id": "badge-shopper-uuid-001",
"type": "SHOPPER",
"action": "ACCEPT"
}
Expected Result: Gate opens. Note: Base64 encoding is not applicable when channel is RADIO.
1.8 CONTACT Channel Scan
Objective: Verify scan resolution when channel is CONTACT
Request:
{
"requestId": "b8c9d0e1-f2a3-4567-bcde-678901234567",
"storeId": "STORE-001",
"scanEvent": {
"id": "88888888-9999-aaaa-bbbb-cccccccccccc",
"timestamp": "2024-02-09T18:25:00Z",
"location": "ENTRY",
"value": "Y29udGFjdF9zY2FuX2tleQ==",
"channel": "CONTACT"
}
}
Expected Response (200):
{
"id": "contact-shopper-uuid-001",
"type": "SHOPPER",
"action": "ACCEPT"
}
Expected Result: Gate opens. CONTACT channel scan is processed correctly.
1.9 REJECT — Unrecognized Scan Value
Objective: Verify the API returns REJECT when the scan data cannot be validated
Request:
{
"requestId": "c9d0e1f2-a3b4-5678-cdef-789012345678",
"storeId": "STORE-001",
"scanEvent": {
"id": "99999999-aaaa-bbbb-cccc-dddddddddddd",
"timestamp": "2024-02-09T18:35:00Z",
"location": "ENTRY",
"value": "aW52YWxpZF9sb3lhbHR5X2tleQ==",
"channel": "OPTICAL"
}
}
Expected Response (200):
{
"id": "unknown",
"type": "SHOPPER",
"action": "REJECT"
}
Expected Result: Gate remains closed. The scan was processed but the company rejected the shopper.
1.10 Unrecognized Request Fields
Objective: Verify your connector ignores attributes it does not recognize. Amazon might add new attributes to the request in the future.
Request:
{
"requestId": "d0e1f2a3-b4c5-6789-defa-890123456789",
"storeId": "STORE-001",
"newTopLevelAttribute": "future-value",
"scanEvent": {
"id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"timestamp": "2024-02-09T18:40:00Z",
"location": "ENTRY",
"value": "dmFsaWRfc2hvcHBlcl9rZXk=",
"channel": "OPTICAL",
"newScanEventAttribute": "future-value"
}
}
Expected Response (200):
{
"id": "shopper-uuid-001",
"type": "SHOPPER",
"action": "ACCEPT"
}
Expected Result: Your connector returns the same resolution it would return without the extra attributes. It does not return a 400 or 500.
2. Bad Request — Validation Errors (400)
2.1 Missing requestId
Objective: Verify 400 when requestId is omitted
Request:
{
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.2 Invalid requestId Format
Objective: Verify 400 when requestId does not match UUID format
Request:
{
"requestId": "not-a-valid-uuid",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.3 Missing storeId
Objective: Verify 400 when storeId is omitted
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.4 storeId Exceeds 255 Characters
Objective: Verify 400 when storeId exceeds the maximum length
Request: Submit a request with a storeId longer than 255 characters
Expected Response (400):
{
"message": "string"
}
2.5 Missing scanEvent
Objective: Verify 400 when the entire scanEvent object is omitted
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001"
}
Expected Response (400):
{
"message": "string"
}
2.6 Missing scanEvent.id
Objective: Verify 400 when scanEvent.id is omitted
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.7 Invalid scanEvent.id Format
Objective: Verify 400 when scanEvent.id does not match UUID format
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "not-a-uuid",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.8 Missing scanEvent.timestamp
Objective: Verify 400 when scanEvent.timestamp is omitted
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.9 Invalid scanEvent.timestamp Format
Objective: Verify 400 when scanEvent.timestamp is not valid UTC format
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "not-a-timestamp",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.10 Missing scanEvent.location
Objective: Verify 400 when scanEvent.location is omitted
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.11 Invalid scanEvent.location Value
Objective: Verify 400 when scanEvent.location is not ENTRY, EXIT, or MANUAL_IN_STORE
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "INVALID",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.12 Missing scanEvent.value
Objective: Verify 400 when scanEvent.value is omitted
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.13 scanEvent.value Exceeds 1000 Characters
Objective: Verify 400 when scanEvent.value exceeds the maximum length
Request: Submit a request with a scanEvent.value longer than 1000 characters
Expected Response (400):
{
"message": "string"
}
2.14 scanEvent.value Not Valid Base64 (OPTICAL Channel)
Objective: Verify 400 when scanEvent.value is not a valid Base64-encoded string for OPTICAL channel
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "!!!not-base64!!!",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
2.15 Missing scanEvent.channel
Objective: Verify 400 when scanEvent.channel is omitted
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "dmFsaWRfa2V5"
}
}
Expected Response (400):
{
"message": "string"
}
2.16 Invalid scanEvent.channel Value
Objective: Verify 400 when scanEvent.channel is not OPTICAL, RADIO, or CONTACT
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "STORE-001",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "BLUETOOTH"
}
}
Expected Response (400):
{
"message": "string"
}
2.17 Empty Request Body
Objective: Verify 400 when the request body is empty
Request:
{}
Expected Response (400):
{
"message": "string"
}
2.18 Unknown storeId
Objective: Verify 400 when storeId is not one of the store IDs assigned to you during onboarding
Request:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"storeId": "UNKNOWN-STORE-ID",
"scanEvent": {
"id": "11111111-2222-3333-4444-555555555555",
"timestamp": "2024-02-09T18:00:00Z",
"location": "ENTRY",
"value": "dmFsaWRfa2V5",
"channel": "OPTICAL"
}
}
Expected Response (400):
{
"message": "string"
}
Expected Result: If your connector validates storeId, use the store IDs listed under store details in the merchant portal. If they don't match, valid shoppers are rejected during connectivity testing.
3. Input Validation — Additional Error Cases
3.1 Empty String Values (400)
Objective: Test empty string input validation
Request:
{
"requestId": "",
"storeId": "",
"scanEvent": {
"id": "",
"timestamp": "",
"location": "",
"value": "",
"channel": ""
}
}
Expected Response (400):
{
"message": "string"
}
3.2 Null Values (400)
Objective: Test null input validation
Request:
{
"requestId": null,
"storeId": null,
"scanEvent": null
}
Expected Response (400):
{
"message": "string"
}
3.3 Whitespace Only Values (400)
Objective: Test whitespace-only input validation
Request:
{
"requestId": " ",
"storeId": " ",
"scanEvent": {
"id": " ",
"timestamp": " ",
"location": " ",
"value": " ",
"channel": " "
}
}
Expected Response (400):
{
"message": "string"
}
4. Internal Server Error (500)
4.1 Server Error
Objective: Verify your connector returns 500 when it cannot process the request because of a server issue
Test Method: Simulate an internal server error (e.g., identity backend unavailable)
Expected Response (500):
{
"message": "Internal server error"
}
Expected Result: Your connector returns 500 rather than a 200 with an ACCEPT or REJECT it couldn't determine. Confirm with the Amazon team how the gate behaves for your store when your connector returns 500.
5. Response Validation
5.1 Verify Response id Length
Objective: Verify the response id does not exceed 255 characters
Test Steps:
- Send a valid request
- Confirm the response id field is ≤ 255 characters
5.2 Verify Response type Enum
Objective: Verify the response type is one of the valid enum values
Test Steps:
- Send valid requests for each shopper type
- Confirm the response type is one of:
SHOPPER,ASSOCIATE,CASH,LOYALTY
5.3 Verify Response action Enum
Objective: Verify the response action is one of the valid enum values
Test Steps:
- Send valid requests that trigger both accept and reject
- Confirm the response action is one of:
ACCEPT,REJECT
6. Performance
Note: The ResolveScan specification does not define a latency target. Confirm the target for your store with the Amazon team before running these tests. The shopper is waiting at the gate while your connector responds.
6.1 Response Time
Objective: Verify the Identity Connector responds within the latency target agreed with the Amazon team
Test Steps:
- Send 100 valid requests sequentially
- Measure response time for each
- Calculate the p99 response time
Expected Result: p99 response time is within the agreed latency target.
6.2 Concurrent Load
Objective: Verify performance under peak concurrent scan volume
Test Steps:
- Send 50 concurrent valid requests
- Measure response times and success rates
- Verify no timeouts or dropped requests
Expected Result: All requests succeed within the agreed latency target.
Test Data Requirements
| Data Item | Description |
|---|---|
| Valid shopper scan value | Base64-encoded value mapped to a known SHOPPER |
| Valid associate scan value | Base64-encoded value mapped to a known ASSOCIATE |
| Valid cash shopper scan value | Base64-encoded value mapped to a known CASH type (cash-enabled store only) |
| Valid loyalty scan value | Base64-encoded value mapped to a known LOYALTY type |
| Invalid scan value | Base64-encoded value that does not map to any known identity |
| RADIO channel scan value | Plain text value for badge/RADIO scan |
| Valid store IDs | At least 2 store IDs assigned during onboarding |
| Invalid store ID | A store ID that does not exist (test 2.18) |
| Cash-enabled store ID | A store ID that supports CASH type |
Test Execution Notes
- Base64 Encoding: All scanEvent.value values must be Base64-encoded for OPTICAL and CONTACT channels. Base64 encoding is not applicable for RADIO channel.
- UUID Format: Both requestId and scanEvent.id must follow the pattern
[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12} - Location Values: scanEvent.location supports
ENTRY,EXIT, andMANUAL_IN_STORE. - Channel Values: scanEvent.channel supports
OPTICAL,RADIO, andCONTACT. - CASH Type: Confirm with the Amazon team whether your store supports the CASH visitor type before running test 1.3.
- Non-200 Responses: Confirm with the Amazon team how the gate behaves when your connector returns a 400 or 500 before running sections 2–4.
Expected HTTP Status Codes Summary
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Successful scan resolution (returns id, type, action) |
| 400 | Bad Request | Recommended for validation errors, missing or invalid fields. Not defined in the ResolveScan specification |
| 500 | Internal Server Error | Service exceptions, unhandled errors |

