--- title: "Connect module: player" description: The player lookup OneHazel calls for currency, country, status and restrictions. Headers, signature, conformance scenarios and samples. --- For the operator's engineer building the player module. # player The player module answers one question: what does OneHazel need to know about this player right now? Game studios, KYC vendors and responsible-gaming vendors use it for currency, country, account status and active restrictions. Nothing beyond those fields is requested. ## Who calls whom OneHazel calls you, at `POST /player/lookup` under the base URL you register for `player`. The response carries `player_external_id`, `currency`, `country` (ISO-3166-1 alpha-2), `status` (`active`, `suspended`, `self_excluded` or `closed`) and `restrictions`: an array of active restrictions, each with a `kind` such as `deposit_limit` or `self_exclusion`. The array is empty only when the player has none. An unknown player is `404` with the error envelope. ## Headers and signature The player module uses the same three headers as the [wallet](/connect/modules/wallet#headers-and-signature): - `Authorization: Bearer ` - `X-OneHazel-Signature: t=,v1=`, HMAC-SHA256 of `"." + raw body`, 300 s tolerance, constant-time compare, verified before parsing - `X-OneHazel-Env: test` or `live` ## Registration Register the base URL with two extra fields: - `testPlayerId`: a player in your `test` ledger. - `restrictedPlayerId`: a second test player with an active restriction (a self-exclusion, a block or a limit), at most 128 characters. Both are required: a player registration that would leave either unset is refused with `VALIDATION_ERROR` "player registration requires testPlayerId" (or `restrictedPlayerId`), and `connect_status` lists a missing one under the module's `requiredInputs` by the same rule. A row registered before this rule may still lack one; a conformance run against it ends `errored` with reason `missing_input`. Registering again keeps any field you omit, so a call that changes only the base URL leaves both test players in place; send `null` to clear a field. Registering again also keeps the signing secret and callback key, so the change needs no restart. ## Conformance | Scenario | Severity | Passing looks like | |---|---|---| | `lookup.ok` | blocker | 200 with all five fields for your test player | | `lookup.unknown_404` | major | 404 with the error envelope, never a 200 with empty fields | | `lookup.restricted_flag` | major | a non-empty `restrictions` array for your restricted player | ## Samples | Stack | Sample | |---|---| | TypeScript + Express | [player](/connect/samples/typescript/express/player) | | TypeScript + Fastify | [player](/connect/samples/typescript/fastify/player) | | Python + FastAPI | [player](/connect/samples/python/fastapi/player) | | PHP (no framework) | [player](/connect/samples/php/plain/player) | | PHP + Laravel | [player](/connect/samples/php/laravel/player) | The samples seed a test player and a restricted test player; set `ONEHAZEL_RESTRICTED_TEST_PLAYER_ID` to match the `restrictedPlayerId` you register.