All v2 endpoints use Bearer token authentication and return a standard response envelope.
Header required in all requests:
Authorization: Bearer <your_token>
All v2 endpoints wrap responses in a consistent envelope:
// Success (2xx)
{
"data": { },
"meta": { "requestId": "..." },
"message": "Additional message" // Optional
}
// Error (4xx / 5xx)
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description",
"details": { }
},
"meta": { "requestId": "..." }
}
User profile, permissions and wallet endpoints. Prefix: /api/v2/user
/api/v2/user/permissions
Returns the list of permissions assigned to the authenticated user.
Response:
{
"data": {
"permissions": ["acceso_srcm", "acceso_msmvl"]
},
"meta": { "requestId": "..." }
}
/api/v2/user/wallet
Returns wallet information (balance, currency) for the authenticated user.
Response:
{
"data": {
"balance": 50000,
"currency": "EUR"
},
"meta": { "requestId": "..." }
}
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid authentication token |
| WALLET_NOT_FOUND | 404 | No wallet associated to the authenticated user |
/api/v2/user/wallet/history
Returns the wallet balance change history for the authenticated user.
Query params:
| Name | Type | Description |
|---|---|---|
| limit | number | Items per page (default: 10) |
| offset | number | Offset for pagination, max 100 (default: 0) |
Response:
{
"data": [
{
"name": "John Doe",
"amount": 1500,
"type": "debit",
"description": "Activación eSIM",
"createdAt": "2026-03-11T10:00:00.000Z"
}
],
"meta": { "requestId": "..." }
}
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid authentication token |
| INVALID_QUERY | 400 | Invalid limit or offset query parameters |
| WALLET_NOT_FOUND | 404 | No wallet associated to the authenticated user |
| internal_error | 500 | Failed to retrieve wallet history |
SIM/eSIM activation via MSMVL. Prefix: /api/v2/msmvl/activation. Requires
acceso_msmvl permission.
Compatibility note: for compatibility, the brand value "Lyca" also covers
Llamaya. The API parameter must still be sent as "Lyca".
/api/v2/msmvl/activation
Activate a SIM or eSIM card. Performs the full flow: ICC validation (SIM only), document/age validation, activation with the telecom platform, wallet charge, recharge and bundle purchase when applicable.
If the external activation succeeds but a later step fails, the error response will include a
recovery object with an activationId and a step field indicating
where the process stopped. The client must call POST /api/v2/msmvl/activation/resume with
just { "activationId": ... } to resume.
Body (JSON):
{
"productId": "PO_Mali_M",
"brand": "Lebara",
"name": "Juan",
"surname": "Pérez",
"surname2": "García",
"documentNumber": "12345678A",
"dateOfBirth": "1990-05-15",
"nationalityId": "ES",
"iccId": "89340712341234567890",
"simType": "sim",
"identificationType": "personal-identity-code",
"email": "user@example.com",
"language": "eng"
}
Body fields:
| Field | Type | Description |
|---|---|---|
| productId | string | Product/plan identifier (required) |
| brand | "Lebara" | "Lyca" | "Orange" |
Brand (required). Use "Lyca" when referring to Llamaya. |
| name | string | Customer first name (required) |
| surname | string | Customer first surname (required) |
| surname2 | string | Customer second surname (optional) |
| documentNumber | string | Document number (required) |
| dateOfBirth | string | Date of birth (required) |
| nationalityId | string | Nationality code, 2 chars ISO (required) |
| iccId | string | ICC ID, 19–20 chars (required when simType is sim) |
| simType | "sim" | "esim" |
SIM type (required) |
| identificationType | "business-identity-code" | "nie" | "passport" | "personal-identity-code" |
Document type (required) |
| string | Customer email (required) | |
| language | string | Contact language, 3 chars ISO 639-2/T (required, e.g. "eng") |
Success response:
{
"data": {
"msisdnId": "612345678",
"qrCode": "LPA:1$sm-...",
"valueCharged": 5.00,
"provisionId": "PROV-123456"
},
"message": "Activation completed successfully. The amount has been deducted from the wallet...",
"meta": { "requestId": "..." }
}
Success data fields:
| Field | Type | Description |
|---|---|---|
| msisdnId | string | Assigned phone number |
| qrCode | string | QR code for eSIM activation (present for eSIM) |
| valueCharged | number | Amount charged from wallet in EUR (only present when a charge was made) |
| provisionId | string | Bundle provision ID (only for non-Orange brands) |
Error response (with step recovery):
{
"error": {
"code": "WALLET_UPDATE_FAILED",
"message": "Failed to process the activation charge.",
"recovery": {
"activationId": 42,
"step": "charge",
"partialData": {
"msisdnId": "612345678",
"qrCode": "LPA:1$sm-..."
}
}
},
"meta": { "requestId": "..." }
}
When the response includes error.recovery, call the resume endpoint with the
activationId:
POST /api/v2/msmvl/activation/resume
{ "activationId": 42 }
Possible values of recovery.step:
| Step | Meaning |
|---|---|
"charge" |
Wallet charge failed. Resume will run: charge + recharge + bundle. |
"recharge" |
Wallet already charged, recharge failed. Resume will run: recharge + bundle. |
"bundle" |
Wallet and recharge done, bundle failed. Resume will run: bundle only. |
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| WALLET_NOT_FOUND | 500 | No wallet associated to user |
| ICC_ID_REQUIRED | 400 | iccId missing when simType is "sim" |
| ICC_ID_NOT_AVAILABLE | 400 | The provided ICC ID is not available for activation |
| BRAND_NOT_MAPPED | 400 | Brand could not be mapped to the configured recharge product |
| PRODUCT_NOT_FOUND | 400 | Requested product not found |
| ACTIVATION_COST_UNAVAILABLE | 400 | Could not determine the activation cost for the SIM |
| INSUFFICIENT_BALANCE | 400 | Wallet balance too low (a pending recharge is created) |
| WALLET_UPDATE_FAILED | 500 | Failed to deduct from wallet (step: charge) |
| RECHARGE_FAILED | 500 | External recharge failed (a pending recharge is created) |
| BUNDLE_FAILED | 500 | Bundle purchase failed (step: bundle) |
| ACTIVATION_SAVE_FAILED | 500 |
SIM activated successfully but DB record failed — no recovery available, contact support with the
msisdnId in details
|
| PENDING_RECHARGE_SAVE_FAILED | 500 | Failed to save the pending recharge record |
/api/v2/msmvl/activation/resume
Resume an activation that stopped mid-way. Use this when a previous call to
POST /api/v2/msmvl/activation returned an error that included
error.recovery.activationId. The server reads the activation state from the database and
continues from the step where it stopped.
Body (JSON):
{
"activationId": 42
}
Body fields:
| Field | Type | Description |
|---|---|---|
| activationId | number (integer) | Activation ID obtained from error.recovery.activationId (required) |
Success response:
{
"data": {
"msisdnId": "612345678",
"qrCode": "LPA:1$sm-...",
"valueCharged": 5.00,
"provisionId": "PROV-123456"
},
"message": "Activation completed successfully. The amount has been deducted from the wallet...",
"meta": { "requestId": "..." }
}
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| BAD_REQUEST | 400 | Body validation failed (activationId missing or not a positive integer) |
| ACTIVATION_NOT_FOUND | 404 | No activation found for the given activationId |
| FORBIDDEN | 403 | The activation belongs to a different user |
| ACTIVATION_FAILED | 500 | This activation was permanently marked as failed — contact support |
| WALLET_NOT_FOUND | 500 | No wallet associated to user |
| BRAND_NOT_MAPPED | 400 | Brand could not be mapped to the configured recharge product |
| PRODUCT_NOT_FOUND | 400 | Requested product not found |
| ACTIVATION_COST_UNAVAILABLE | 400 | Could not determine the activation cost |
| INSUFFICIENT_BALANCE | 400 | Wallet balance too low (a pending recharge is created) |
| WALLET_UPDATE_FAILED | 500 | Failed to deduct from wallet — response includes recovery |
| RECHARGE_FAILED | 500 | External recharge failed — response includes recovery |
| BUNDLE_FAILED | 500 | Bundle purchase failed — response includes recovery |
/api/v2/msmvl/activation/facial/:iccId
Get the facial value (activation cost) for a given ICC ID. Used to determine how much balance the SIM already has before activation.
Path params:
| Name | Type | Description |
|---|---|---|
| iccId | string | ICC ID, 19–20 chars (required) |
Query params:
| Name | Type | Description |
|---|---|---|
| brand | "Lebara" | "Lyca" | "Orange" |
Brand name (required) |
| language | string | Language code, 2 chars ISO 639-1 (required) |
Response:
{
"data": {
"value": 10.00
},
"meta": { "requestId": "..." }
}
/api/v2/msmvl/activation/history
Get MSMVL activation history for the authenticated user.
Query params:
| Name | Type | Description |
|---|---|---|
| page | number | Page number, min 1 (default: 1) |
| limit | number | Items per page, 1–100 (default: 10) |
| dateFrom | date | Filter from date (optional, ISO format) |
| dateTo | date | Filter to date (optional, ISO format) |
Response:
{
"data": {
"activationHistory": [
{
"id": 1,
"msisdnId": "612345678",
"qrCode": "LPA:1$sm-...",
"createdAt": "2026-03-11T10:00:00.000Z"
}
],
"total": 42
},
"message": "Activation history retrieved successfully.",
"meta": { "requestId": "..." }
}
/api/v2/msmvl/activation/recharge-pending
Get pending recharges for incomplete MSMVL activations. A pending recharge record is created only when the
user had insufficient wallet balance at activation time (INSUFFICIENT_BALANCE). Other failure
cases (recharge API errors, BundleCash errors) are handled via the
/resume endpoint and do not create a pending recharge record.
Query params:
| Name | Type | Description |
|---|---|---|
| limit | number | Items to return (optional) |
| offset | number | Offset for pagination, max 100 (optional) |
Response:
{
"data": [...],
"message": "Pending activation recharges retrieved successfully.",
"meta": { "requestId": "..." }
}
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| PENDING_RECHARGES_RETRIEVE_FAILED | 500 | Failed to retrieve pending recharges |
/api/v2/msmvl/activation/recharge-pending
Admin-only endpoint. Completes an activation left pending due to insufficient wallet
balance (INSUFFICIENT_BALANCE). Bypasses the wallet and calls Masmovil directly (Topup for
physical SIM, BundleCash for eSIM). On success, the pending recharge record is deleted and the activation
status in msmvl_historial_activaciones is updated to completed. If the SIM
facial value already covers the product price, no external call is made but cleanup is still applied. For
other failure types use POST /resume instead.
Body (JSON):
{
"mobileNumber": "612345678"
}
Body fields:
| Field | Type | Description |
|---|---|---|
| mobileNumber | string | Mobile number, 9 digits (required) |
Success response:
{
"data": {
"msisdnId": "612345678",
"amount": 500
},
"message": "Recarga realizada correctamente para completar el proceso de activación.",
"meta": { "requestId": "..." }
}
Success data fields:
| Field | Type | Description |
|---|---|---|
| msisdnId | string | The mobile number |
| amount | number | Amount recharged (in cents) |
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| PENDING_RECHARGE_NOT_FOUND | 404 | No pending recharge found for this mobile number |
| PENDING_RECHARGE_RETRIEVE_FAILED | 500 | Failed to retrieve the pending recharge |
| PRODUCT_NOT_FOUND | 500 | Product associated to the pending recharge not found |
| ACTIVATION_REFERENCE_NOT_FOUND | 500 | Activation reference not found for this mobile number |
| ACTIVATION_REFERENCE_RETRIEVE_FAILED | 500 | Failed to retrieve the activation reference |
| BUNDLE_CASH_FAILED | 500 | Failed to apply BundleCash in Masmovil Services (eSIM) |
| FACIAL_VALUE_RETRIEVE_FAILED | 500 | Failed to retrieve the facial value for the physical SIM |
| ICCID_NOT_FOUND | 500 | ICCID not found for physical SIM recharge |
| RECHARGE_FAILED | 500 | External recharge (Topup) failed |
| BUNDLE_FAILED | 500 | Bundle purchase failed after recharge |
Validation utilities. Prefix: /api/v2/msmvl/validate. Requires
acceso_msmvl permission.
/api/v2/msmvl/validate/:iccid
Validate if an ICC ID (SIM card identifier) is available for activation.
Query params:
| Name | Type | Description |
|---|---|---|
| brand | "Lebara" | "Lyca" | "Orange" |
Brand (required) |
/api/v2/msmvl/validate/age
Validate minimum age requirement (must be at least 18 years old).
Query params:
| Name | Type | Description |
|---|---|---|
| dateOfBirth | string | Date of birth in YYYY-MM-DD format (required) |
/api/v2/msmvl/validate/document
Validate an identification document number.
Query params:
| Name | Type | Description |
|---|---|---|
| documentNumber | string | Document number (required) |
| identificationType | "business-identity-code" | "nie" | "passport" | "personal-identity-code" |
Document type (required) |
Product catalog. Prefix: /api/v2/msmvl/products. Requires acceso_msmvl permission.
/api/v2/msmvl/products
Get the list of available products for a brand.
Query params:
| Name | Type | Description |
|---|---|---|
| brand | "Lebara" | "Lyca" | "Orange" |
Brand (required). Use "Lyca" when referring to Llamaya. |
| language | "en" | "es" |
Language for product names (optional. 'es' by default) |
Phone number management. Prefix: /api/v2/msmvl/msisdn-op. Requires
acceso_msmvl permission.
/api/v2/msmvl/msisdn-op/operator/:msisdn
Get the operator info for a phone number (current operator, origin, portability status).
/api/v2/msmvl/msisdn-op/balance/:msisdn
Get balance for a phone number.
Query params:
| Name | Type | Description |
|---|---|---|
| brand | "Lebara" | "Lyca" | "Orange" |
Brand (required) |
/api/v2/msmvl/msisdn-op/msisdn/:msisdn
Get comprehensive MSISDN info (ICC ID, IMSI, PINs, PUKs, status, product, balance, bonuses, QR code).
Query params:
| Name | Type | Description |
|---|---|---|
| brand | "Lebara" | "Lyca" | "Orange" |
Brand (required) |
/api/v2/msmvl/msisdn-op/msisdn/:mobileNumber/services
Get active services for a phone number.
Query params:
| Name | Type | Description |
|---|---|---|
| brand | "Lebara" | "Lyca" | "Orange" |
Brand (required) |
/api/v2/msmvl/msisdn-op/msisdn/:mobileNumber/esimQr
Get eSIM activation QR info (URL and request date) for a phone number.
Query params:
| Name | Type | Description |
|---|---|---|
| brand | "Lebara" | "Lyca" | "Orange" |
Brand (required) |
Inventory lookup. Prefix: /api/v2/msmvl/inventory. Requires
acceso_msmvl permission.
/api/v2/msmvl/inventory/:mobileNumber
Get inventory info (ID and brand) for a mobile number.
Path params:
| Name | Type | Description |
|---|---|---|
| mobileNumber | string | Mobile number, exactly 9 digits (required) |
Response:
{
"data": {
"id": "INV_12345",
"brand": "Lebara"
},
"meta": { "requestId": "..." }
}