VLT Client Registration
POST /api/clientes/register
Registers the client with their essential information. It does not ask for a card, email, phone or address: those arrive later through their own endpoints, Contact Details and Card Assignment.
Two contracts side by side
The endpoint accepts the decoupled contract (this document) and the previous one (Spanish payload with codigoClienteVLT), still live while VLT migrates. The presence of playerId decides which one applies; the two never mix. See Previous contract.
Request
Headers
| Header | Value | Required |
|---|---|---|
Content-Type | application/json | Yes |
Accept | application/json | Yes |
Public Endpoint
Publicly accessible. It does not require X-Client-Secret or any token. Protected by rate limiting (60 requests per minute per IP).
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
playerId | integer | Yes | Player identifier in the counterparty system. Unique |
documentType | integer | Yes | 1 = National ID · 2 = Foreigner ID · 3 = Passport |
documentNumber | string | Yes | Document number (max 20 chars) |
firstName | string | Yes | First name(s) |
paternalLastName | string | Yes | Father's last name |
maternalLastName | string | null | Present | Mother's last name. Must be sent, may be empty or null |
birthDate | string (date) | Yes | Birth date (YYYY-MM-DD or ISO 8601) |
gender | integer | Yes | Gender identifier |
Request Example
curl -X POST 'https://api.syssoft1.com/api/clientes/register' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"documentType": 1,
"documentNumber": "87654321",
"firstName": "John",
"paternalLastName": "Doe",
"maternalLastName": "Smith",
"birthDate": "1985-05-15",
"gender": 1,
"playerId": 1
}'Identity rules
| Rule | Detail |
|---|---|
| Unique document | The documentType + documentNumber pair identifies a person. The same number under a different type is a different person |
Unique playerId | Two distinct profiles cannot share it |
| Idempotency | If the document and playerId already exist and point to the same record, the request answers 200 without creating anything |
| Identity collision | If each identifier points to a different profile, the request is aborted without writing |
Responses
Both success scenarios return the same two identifiers: id is ours, playerId is the counterparty's.
New Client — 201 Created
{
"id": 1024,
"playerId": 1
}Existing Client / Idempotency — 200 OK
The document and playerId sent already exist and match the same record.
{
"id": 1024,
"playerId": 1
}Error Responses
Branch on code, not on message
code is the stable part of the contract: it does not change. message is informative and may be reworded without notice — in fact ERR_MISSING_REQUIRED_FIELDS shares a single text across the three endpoints. When the response carries errors, the per-field detail is there.
| HTTP | code | When |
|---|---|---|
400 | ERR_MISSING_REQUIRED_FIELDS | A required field is missing or malformed |
409 | ERR_DUPLICATE_DOCUMENT | The document is already registered under a different playerId |
409 | ERR_DUPLICATE_PLAYER_ID | The playerId is already in use by a different document |
409 | ERR_IDENTITY_COLLISION | The document belongs to one profile and the playerId to another |
429 | — | Rate limit exceeded (60 per minute per IP) |
503 | — | The target operator is not configured. Contact support |
500 | — | Internal error while processing the registration |
409 Conflict Example
{
"code": "ERR_DUPLICATE_DOCUMENT",
"message": "El documento ingresado ya se encuentra registrado."
}400 Bad Request Example
errors states exactly which field failed.
{
"code": "ERR_MISSING_REQUIRED_FIELDS",
"message": "Faltan campos obligatorios para actualizar el perfil",
"errors": {
"documentNumber": ["The document number field is required."]
}
}Try It
Request Body
Request URL
https://api.syssoft1.com/api/clientes/registerRecommended flow
POST /api/clientes/register→ keep the returnedid.PUT /api/clientes/contact-info→ fill in contact, location and preferences.PUT /api/clientes/card→ bind the RFID card once the client receives it.
Steps 2 and 3 are independent of each other and may be repeated as often as needed.
Previous contract
Being replaced
Kept only so the current integration is not interrupted. New registrations should use the decoupled contract described above.
It applies when the body includes codigoClienteVLT. In that case the endpoint requires correo, the three preferences and tarjeta, and answers with the old shape ({ id, tarjeta, mensaje, esDuplicado }) and with Laravel's 422 on a validation error.
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
codigoClienteVLT | integer | Yes | Internal unique client identifier in the VLT system |
correo | string | Yes | Client's email address |
enviarWhatsApp | boolean | Yes | Consent to receive WhatsApp communications |
enviarCorreo | boolean | Yes | Consent to receive email communications |
enviarSms | boolean | Yes | Consent to receive SMS communications |
tarjeta | string | Yes | Physical RFID card identifier |
tipoDocumento | integer | No | Document type identifier |
dni | string | No | National document number (max 20 chars) |
password | string | No | Lobby access password: 4 to 8 characters, no spaces |
pin | string | No | Alias of password. The field's former name |
nombre | string | No | Client's first name(s) |
apellidoPaterno | string | No | Father's last name |
apellidoMaterno | string | No | Mother's last name |
fechaNacimiento | string (ISO 8601) | No | Birth date |
direccion | string | No | Residential address |
telefono | string | No | Contact phone number |
ubigeo | string | No | Geographic location code |
sexo | integer | No | Gender identifier |
currency | string (ISO 4217) | No | Player currency. Defaults to PEN |
Access password
The password is the second way into the terminal, for the player who arrives without their card. It is bound to whichever card ends up active.
At the terminal the player types their document and then their password: the password alone identifies nobody, because it is not unique, and it is the document + password pair that resolves the account. To use this route the player must have a dni on record.
| Rule | Detail |
|---|---|
| Format | 4 to 8 characters, no spaces. Letters allowed and case-sensitive: "Ab12" is not "ab12" |
| Length on the floor | The terminal types exactly 4, which is what the identity system issues. Registration accepts more so that no sign-up is ever rejected |
| Type | Send it as a string. As a number, a password with a leading zero ("0421") would lose it |
| Uniqueness | Not unique. A password repeated by another player registers normally |
| Optional | A registration without password keeps whatever the player already had |
| New card | If the new card carries no password, it inherits the player's |
The field used to be called pin
pin is still accepted as an alias, so an existing integration needs no changes. If both arrive, password wins. Validation errors are always reported against password.
Changing or removing a password
To change it, send a new registration with the desired password. There is no way to delete it through the API: omitting the field keeps the existing one, it does not remove it.
Responses
| Scenario | HTTP | mensaje | esDuplicado |
|---|---|---|---|
| New client | 201 | "cliente nuevo" | false |
| Card added to an existing client | 201 | "tarjeta agregada al cliente existente" | false |
| Card already registered | 200 | "registro duplicado" | true |
{
"id": 11,
"tarjeta": "A0C2BBCA",
"mensaje": "cliente nuevo",
"esDuplicado": false
}Errors
| Code | Description |
|---|---|
422 | Validation failed, with the detail in errors |
429 | Rate limit exceeded |
503 | Target operator not configured |
500 | Internal error |
Notes for the VLT Integrator
- The endpoint never duplicates a player. With the new contract, repeating the same identity answers
200; with the previous one, repeating the same card answers200 registro duplicado. - The card identifier must be the physical UID returned by the RFID reader. It is the same value the lobby will later send as
cardIdentifierwhen authenticating. - The
passwordnever travels back: it appears neither in this endpoint's response nor in any other.