Amazon Developer

as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
Ring
AWS
Documentation
Support
Contact Us
My Cases
Docs
Resources
Ecommerce Plug-ins
Publish
Connect

Resolve Scan Test Cases

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 message text 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:

  1. Send a valid request
  2. 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:

  1. Send valid requests for each shopper type
  2. 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:

  1. Send valid requests that trigger both accept and reject
  2. 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:

  1. Send 100 valid requests sequentially
  2. Measure response time for each
  3. 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:

  1. Send 50 concurrent valid requests
  2. Measure response times and success rates
  3. 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

  1. Base64 Encoding: All scanEvent.value values must be Base64-encoded for OPTICAL and CONTACT channels. Base64 encoding is not applicable for RADIO channel.
  2. 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}
  3. Location Values: scanEvent.location supports ENTRY, EXIT, and MANUAL_IN_STORE.
  4. Channel Values: scanEvent.channel supports OPTICAL, RADIO, and CONTACT.
  5. CASH Type: Confirm with the Amazon team whether your store supports the CASH visitor type before running test 1.3.
  6. 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