Skip to content

Product scanning and authenticity ​

Verify a product authentication code, record scans, and claim or hold related points and collectibles. authCode identifies a product authentication code; brl_id identifies the batch-range log record used by follow-up actions.

Access labels such as Origin + Brand key + Customer are defined in Headers and access. Each endpoint ends in a Try it console; set the host and keys once in its Settings tab or on the overview.

Verify product and update view ​

MethodURL pathRequired access
POST/api/v1/brand/verify/product/:authCodeOrigin + Brand key
POST/api/v1/user/verify/product/:authCodeOrigin + Customer

No brand key on this route

/api/v1/user/verify/product/:authCode is listed although its route does not check api-key: the scan to claim flow calls it. Sending the key anyway is harmless.

Request fields:

FieldTypeRequiredRules / meaning
body.payloadobjectyes—
body.payload.latitudenumberoptional—
body.payload.longitudenumberoptional—
body.payload.nfc_identifierstringoptionalWhitespace trimmed; Converted to lowercase
body.payload.event_countnumberoptional—
path.authCodestringyesWhitespace trimmed
query.methodstringoptionalNo controller schema

Example (first URL):

bash
curl -X POST "$BASE_URL/api/v1/brand/verify/product/<AUTH_CODE>" \
  -H "Origin: $ORIGIN" \
  -H "api-key: $API_KEY" \
  -H 'Content-Type: application/json' \
  --data-raw '{"payload":{}}'

Response: JSON with success: true and result containing the operation’s service data.

Source: app/v1/controller/authenticator_controller.js:16 → verifyProductAndUpdateView; routes: routes/v1/authenticator_route.js:176; service: _verifyProductAndUpdateView (app/v1/service/authenticator_service.js:71).

Scan auth and claim points ​

MethodURL pathRequired access
POST/api/v1/user/redeem-point/productOrigin + Brand key + Customer

Request fields:

FieldTypeRequiredRules / meaning
body.payloadobjectyes—
body.payload.authCodestringyesWhitespace trimmed
body.payload.customerobjectoptionalAt least one of ("email" , "phoneNumber")
body.payload.customer.firstNamestringoptionalWhitespace trimmed
body.payload.customer.lastNamestringoptionalWhitespace trimmed
body.payload.customer.fullNamestringoptionalWhitespace trimmed
body.payload.customer.passwordstringoptionalWhitespace trimmed; Minimum (8)
body.payload.customer.emailstringoptionalEmail address; Converted to lowercase; Whitespace trimmed
body.payload.customer.phoneNumberstringoptionalreplace(/\D/g , ""); Whitespace trimmed; Minimum (8)
body.payload.customer.phone_prefixstringconditionalRequired when phoneNumber is supplied; otherwise optional
body.payload.customer.dateOfBirthdateoptionalISO date
body.payload.customer.tagsstringoptionalWhitespace trimmed
body.payload.customer.user_profilestringoptionalWhitespace trimmed
body.payload.customer.user_descriptionstringoptionalWhitespace trimmed
body.payload.customer.usernamestringoptionalWhitespace trimmed

Example:

bash
curl -X POST "$BASE_URL/api/v1/user/redeem-point/product" \
  -H "Origin: $ORIGIN" \
  -H "api-key: $API_KEY" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H 'Content-Type: application/json' \
  --data-raw '{"payload":{"authCode":"<AUTH_CODE>"}}'

Response: JSON with success: true and result containing the operation’s service data. Result fields/details: message, userId, authCode.

Source: app/v1/controller/authenticator_controller.js:154 → scanAuthAndClaimPoints; routes: routes/v1/authenticator_route.js:204; service: _scanAuthAndClaimPoints (app/v1/service/authenticator_service.js:741).

Post verify scan auth ​

MethodURL pathRequired access
POST/api/v1/user/post_verify/product/:brl_idOrigin + Brand key + Customer

Request fields:

FieldTypeRequiredRules / meaning
body.payload.pvl_idnumberoptionalInteger
path.brl_idnumberyesInteger
body.payload.event_countnumberoptionalInteger
body.payload.nfc_identifierstringoptional—

Example:

bash
curl -X POST "$BASE_URL/api/v1/user/post_verify/product/1" \
  -H "Origin: $ORIGIN" \
  -H "api-key: $API_KEY" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H 'Content-Type: application/json' \
  --data-raw '{"payload":{"pvl_id":1,"event_count":1,"nfc_identifier":"example"}}'

Response: JSON with success: true and result containing the operation’s service data. Result fields/details: message, campaigns.

Source: app/v1/controller/authenticator_controller.js:79 → postVerifyScanAuth; routes: routes/v1/authenticator_route.js:224; service: _postVerifyScanAuth (app/v1/service/authenticator_service.js:522).

Scan auth and claim collectible ​

MethodURL pathRequired access
POST/api/v1/user/redeem-collectible/productOrigin + Brand key + Customer

Request fields:

FieldTypeRequiredRules / meaning
body.payloadobjectyes—
body.payload.authCodestringyesWhitespace trimmed

Example:

bash
curl -X POST "$BASE_URL/api/v1/user/redeem-collectible/product" \
  -H "Origin: $ORIGIN" \
  -H "api-key: $API_KEY" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H 'Content-Type: application/json' \
  --data-raw '{"payload":{"authCode":"<AUTH_CODE>"}}'

Response: JSON with success: true and result containing the operation’s service data. Result fields/details: message, user_id, authCode, claiming_asset.

Source: app/v1/controller/authenticator_controller.js:223 → scanAuthAndClaimCollectible; routes: routes/v1/authenticator_route.js:214; service: _scanAuthAndClaimCollectible (app/v1/service/authenticator_service.js:894).

Hold points and collectible ​

MethodURL pathRequired access
POST/api/v1/user/hold/points-collectibleOrigin + Brand key + Customer

Request fields:

FieldTypeRequiredRules / meaning
body.payloadobjectyes—
body.payload.authCodestringyesWhitespace trimmed

Example:

bash
curl -X POST "$BASE_URL/api/v1/user/hold/points-collectible" \
  -H "Origin: $ORIGIN" \
  -H "api-key: $API_KEY" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H 'Content-Type: application/json' \
  --data-raw '{"payload":{"authCode":"<AUTH_CODE>"}}'

Response: JSON with success: true and result containing the operation’s service data. Result fields/details: message, authCode, brl_id.

Source: app/v1/controller/authenticator_controller.js:259 → holdPointsAndCollectible; routes: routes/v1/authenticator_route.js:186; service: _holdPointsAndCollectible (app/v1/service/authenticator_service.js:1130).

Release points after verify ​

MethodURL pathRequired access
POST/api/v1/user/release/points-collectibleOrigin + Brand key + Customer

Request fields:

FieldTypeRequiredRules / meaning
body.payloadobjectyes—
body.payload.authCodestringyesWhitespace trimmed
body.payload.receiptIdnumberoptional—

Example:

bash
curl -X POST "$BASE_URL/api/v1/user/release/points-collectible" \
  -H "Origin: $ORIGIN" \
  -H "api-key: $API_KEY" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H 'Content-Type: application/json' \
  --data-raw '{"payload":{"authCode":"<AUTH_CODE>"}}'

Response: JSON with success: true and result containing the operation’s service data. Result fields/details: message, authCode, brl_id.

Source: app/v1/controller/authenticator_controller.js:295 → releasePointsAfterVerify; routes: routes/v1/authenticator_route.js:195; service: _releasePointsAfterVerify (app/v1/service/authenticator_service.js:1336).

Verify authcode ​

MethodURL pathRequired access
GET/api/v1/brand/verify/authcode/:authCodeOrigin + Brand key

Request fields:

FieldTypeRequiredRules / meaning
path.authCodestringyesWhitespace trimmed

Example:

bash
curl -X GET "$BASE_URL/api/v1/brand/verify/authcode/<AUTH_CODE>" \
  -H "Origin: $ORIGIN" \
  -H "api-key: $API_KEY"

Response: JSON with success: true and result containing the operation’s service data. Result fields/details: valid_authcode, allocated_authcode, authCode.

Source: app/v1/controller/authenticator_controller.js:332 → verify_authcode; routes: routes/v1/authenticator_route.js:254; service: _verify_authcode (app/v1/service/authenticator_service.js:1650).

Read and verify an authentication code from an image ​

MethodURL pathRequired access
POST/api/v1/brand/verify/authcode-by-ocrOrigin + Brand key

Request fields:

FieldTypeRequiredRules / meaning
multipart.filefileyesNo controller schema

Example:

bash
curl -X POST "$BASE_URL/api/v1/brand/verify/authcode-by-ocr" \
  -H "Origin: $ORIGIN" \
  -H "api-key: $API_KEY" \
  -F "file=@/path/to/image.jpg"

Response: JSON with success: true and result containing the operation’s service data.

Source: app/v1/controller/authenticator_controller.js:360 → verify_authcode_by_ocr; routes: routes/v1/authenticator_route.js:264; service: _verify_authcode_by_ocr (app/v1/service/authenticator_service.js:1703).

Lifecycle ​

Each authentication code has one batch-range log row (brl_id). Claims against it are recorded per customer with a status of pending or approved, and a collectible claim adds an ownership row:

CallRefused when
redeem-point/productThe code's points are already approved — You have already claimed points for this Auth Code
redeem-collectible/productAny customer already holds this code's collectible; the collectible is at its maximum supply; the code has no collectible
hold/points-collectibleThis customer already holds the code; the points are already approved; the collectible is pending or claimed
release/points-collectibleThis customer has no hold on the code; a receiptId is sent that is not this customer's approved receipt for this code
redeem-point, redeem-collectible and releaseThe code is age-restricted and the customer's identity is not verified. hold does not check

A release with no receiptId is granted as a gift; the code carries a TODO to gate that path. The receipt that normally unlocks a hold is judged on submission — see Receipts. Claiming a collectible — directly, or by releasing a hold — also makes the customer the product's first owner, which starts the ownership lifecycle. The journey is the scan-to-claim web flow.

Batch platform, Shopify app and API documentation