Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.closient.com/llms.txt

Use this file to discover all available pages before exploring further.

Experimental (v1): This linkType response shape is published as a v1 experimental contract. The auth-tier split, response fields, and verificationStatus enum may change before the first external integration freezes the shape. Closient will announce a stable v1.0 once an external scanner or 2D-cert tool integrates against the response.
The gs1:verificationService linkType returns the verification status of a serialized trade item — a GTIN + AI 21 serial pair scanned against the Closient resolver. Two tiers are exposed:
TierCallerAuthRate limitPayload
MinimalConsumer scan (browser, native scanner)none60 / hour / IP5 fields, no scan history
FullBrand dashboard, retailer POS, 2D-cert toolX-API-Keyper-key (default 300/min)scan history, anomaly entries, prior-event hints

Endpoint

GET https://www.closient.com/resolver/api/v1/verify/01/{gtin}/21/{serial}
Path parameters mirror the GS1 Digital Link AI ordering used elsewhere in the resolver (01 = GTIN, 21 = serial).
ParameterFormatNotes
gtin8–14 digit GTINGTIN-8/12/13/14; non-digit input returns 422 invalid_gtin.
serial1–20 printable ASCII charactersAI 21. Out-of-range characters return 422 invalid_serial.

Authentication

Authenticated calls supply an organization API key in the X-API-Key header. The same key shape used elsewhere in the Closient API is accepted (csb_*).
GET /resolver/api/v1/verify/01/09521101530018/21/SN001 HTTP/1.1
Host: www.closient.com
X-API-Key: csb_<body>_<checksum>
Calls without X-API-Key (or with an unknown key) fall through to the minimal-tier response and are subject to the IP rate limit.

Unauthenticated response (consumer)

{
  "verificationStatus": "authentic",
  "gtin": "09521101530018",
  "serialNumber": "SN001",
  "verifiedAt": "2026-05-09T20:00:00Z",
  "recommendation": "proceed"
}
FieldTypeDescription
verificationStatusenumauthentic, suspect, counterfeit_suspected, serialization_error
gtinstringEchoed GTIN from the request path
serialNumberstringEchoed AI 21 serial from the request path
verifiedAtISO 8601 timestampWhen this response was generated
recommendationenumproceed for authentic / unverified / unknown serials, flag_for_review otherwise

Enumeration protection

Serials we have never seen return the same shape as known-authentic serials (verificationStatus: "authentic", recommendation: "proceed"). Consumer-facing scanners cannot use this endpoint to probe whether a particular serial is in the Closient database. Brands needing the truthful “we have not seen this serial” signal must authenticate — the auth-tier response returns scanHistory: null for never-seen serials.

Rate limit

Unauthenticated calls are limited to 60 requests per hour per client IP. The 61st call returns 429 Too Many Requests with a Retry-After header indicating the seconds remaining in the bucket.

Authenticated response (brand / retailer)

{
  "verificationStatus": "suspect",
  "gtin": "09521101530018",
  "serialNumber": "DUPE001",
  "verifiedAt": "2026-05-09T20:00:00Z",
  "scanHistory": {
    "totalScans": 5,
    "retailerScans": 2,
    "consumerScans": 3,
    "distinctRetailLocations": 2,
    "firstSeen": "2026-04-01T10:00:00Z"
  },
  "anomalies": [
    {
      "type": "duplicate_retail_scan",
      "description": "Serial previously scanned at POS at a different retail location.",
      "priorEvent": {
        "location": "49.2827,-123.1207",
        "retailer": "RetailerA",
        "scannedAt": "2026-04-10T14:30:00Z"
      }
    }
  ],
  "recommendation": "flag_for_review"
}
The auth-tier response is a strict superset of the unauth-tier response — every consumer field is preserved verbatim.

scanHistory

FieldTypeDescription
totalScansint ≥ 0All scan-context counters summed
retailerScansint ≥ 0Authenticated retailer-system scans
consumerScansint ≥ 0Browser / unauthenticated scans
distinctRetailLocationsint ≥ 0Unique POS locations that have scanned this serial
firstSeenISO 8601 timestampEarliest observed scan
scanHistory is null when the serial has never been observed by the resolver (auth tier only — the unauth tier omits the field entirely).

anomalies

Empty array when no rule has fired. Phase 1 emits a single rule:
typeTriggerpriorEvent
duplicate_retail_scanretailerScans ≥ 2 AND distinctRetailLocations ≥ 2Most recent retailer scan from a different POS
Each anomaly entry carries:
FieldTypeDescription
typestringStable rule identifier
descriptionstringHuman-readable explanation
priorEvent.locationstringlat,lon coordinates (4 decimal places), GLN:<gln> when only a GLN is captured, or empty string
priorEvent.retailerstringRetailer organization name when the prior scan was authenticated, empty otherwise
priorEvent.scannedAtISO 8601 timestampPrior event time (UTC)
Phase 3 (tracked in C-2292) layers on the remaining rules — excessive scans, geographic impossibility, post-sale re-entry, serialization errors, mass-scan — each with its own type value.

Status values

ValueMeaningDefault recommendation
authenticNo negative signals; treat as genuineproceed
suspectAt least one anomaly rule has firedflag_for_review
counterfeit_suspectedOperator-confirmed counterfeit (Phase 3+)flag_for_review
serialization_errorBrand serialization scheme violated (Phase 3+)flag_for_review
The unverified internal state is never returned to consumers — it collapses to authentic for the public contract until Phase 3 ships positive-authentication rules.

Errors

StatusBodyWhen
200Verification payloadAlways for valid path parameters
422{"error": "invalid_gtin", "detail": "..."}GTIN is not 8–14 digits
422{"error": "invalid_serial", "detail": "..."}Serial not 1–20 printable ASCII characters
429Rate-limit envelope, Retry-After headerAnonymous IP exceeded 60/hour

Stability guarantees

This linkType is experimental v1. Until at least one external scanner / 2D-cert tool pins to the contract, the following may change with notice in the changelog:
  • Field names (verificationStatus, recommendation, etc.)
  • The verificationStatus enum set
  • The auth-tier split (which fields are unauth vs auth)
  • The recommendation mapping table
  • The shape of anomalies entries
Stable in all v1 revisions:
  • The path layout (/resolver/api/v1/verify/01/<gtin>/21/<serial>)
  • The X-API-Key auth scheme
  • The 60/hour anonymous rate limit
  • The enumeration-protection guarantee (unknown serial = known-authentic shape)
When the contract freezes, Closient will announce v1.0 in the API changelog.