Appearance
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
| Method | URL path | Required access |
|---|---|---|
POST | /api/v1/brand/verify/product/:authCode | Origin + Brand key |
POST | /api/v1/user/verify/product/:authCode | Origin + 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:
| Field | Type | Required | Rules / meaning |
|---|---|---|---|
body.payload | object | yes | — |
body.payload.latitude | number | optional | — |
body.payload.longitude | number | optional | — |
body.payload.nfc_identifier | string | optional | Whitespace trimmed; Converted to lowercase |
body.payload.event_count | number | optional | — |
path.authCode | string | yes | Whitespace trimmed |
query.method | string | optional | No 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
| Method | URL path | Required access |
|---|---|---|
POST | /api/v1/user/redeem-point/product | Origin + Brand key + Customer |
Request fields:
| Field | Type | Required | Rules / meaning |
|---|---|---|---|
body.payload | object | yes | — |
body.payload.authCode | string | yes | Whitespace trimmed |
body.payload.customer | object | optional | At least one of ("email" , "phoneNumber") |
body.payload.customer.firstName | string | optional | Whitespace trimmed |
body.payload.customer.lastName | string | optional | Whitespace trimmed |
body.payload.customer.fullName | string | optional | Whitespace trimmed |
body.payload.customer.password | string | optional | Whitespace trimmed; Minimum (8) |
body.payload.customer.email | string | optional | Email address; Converted to lowercase; Whitespace trimmed |
body.payload.customer.phoneNumber | string | optional | replace(/\D/g , ""); Whitespace trimmed; Minimum (8) |
body.payload.customer.phone_prefix | string | conditional | Required when phoneNumber is supplied; otherwise optional |
body.payload.customer.dateOfBirth | date | optional | ISO date |
body.payload.customer.tags | string | optional | Whitespace trimmed |
body.payload.customer.user_profile | string | optional | Whitespace trimmed |
body.payload.customer.user_description | string | optional | Whitespace trimmed |
body.payload.customer.username | string | optional | Whitespace 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
| Method | URL path | Required access |
|---|---|---|
POST | /api/v1/user/post_verify/product/:brl_id | Origin + Brand key + Customer |
Request fields:
| Field | Type | Required | Rules / meaning |
|---|---|---|---|
body.payload.pvl_id | number | optional | Integer |
path.brl_id | number | yes | Integer |
body.payload.event_count | number | optional | Integer |
body.payload.nfc_identifier | string | optional | — |
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
| Method | URL path | Required access |
|---|---|---|
POST | /api/v1/user/redeem-collectible/product | Origin + Brand key + Customer |
Request fields:
| Field | Type | Required | Rules / meaning |
|---|---|---|---|
body.payload | object | yes | — |
body.payload.authCode | string | yes | Whitespace 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
| Method | URL path | Required access |
|---|---|---|
POST | /api/v1/user/hold/points-collectible | Origin + Brand key + Customer |
Request fields:
| Field | Type | Required | Rules / meaning |
|---|---|---|---|
body.payload | object | yes | — |
body.payload.authCode | string | yes | Whitespace 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
| Method | URL path | Required access |
|---|---|---|
POST | /api/v1/user/release/points-collectible | Origin + Brand key + Customer |
Request fields:
| Field | Type | Required | Rules / meaning |
|---|---|---|---|
body.payload | object | yes | — |
body.payload.authCode | string | yes | Whitespace trimmed |
body.payload.receiptId | number | optional | — |
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
| Method | URL path | Required access |
|---|---|---|
GET | /api/v1/brand/verify/authcode/:authCode | Origin + Brand key |
Request fields:
| Field | Type | Required | Rules / meaning |
|---|---|---|---|
path.authCode | string | yes | Whitespace 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
| Method | URL path | Required access |
|---|---|---|
POST | /api/v1/brand/verify/authcode-by-ocr | Origin + Brand key |
Request fields:
| Field | Type | Required | Rules / meaning |
|---|---|---|---|
multipart.file | file | yes | No 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:
| Call | Refused when |
|---|---|
redeem-point/product | The code's points are already approved — You have already claimed points for this Auth Code |
redeem-collectible/product | Any customer already holds this code's collectible; the collectible is at its maximum supply; the code has no collectible |
hold/points-collectible | This customer already holds the code; the points are already approved; the collectible is pending or claimed |
release/points-collectible | This 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 release | The 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.