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": "eSIM activation",
"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
Registers and activates a SIM or eSIM number. Performs ICC validation (SIM only), document/age validation, and the activation call. Checks wallet balance before activation, but does not charge the wallet nor trigger recharge or bundle in this step.
After a successful activation, follow the corresponding flow depending on the SIM type:
| SIM type | Required steps (in order) |
|---|---|
| eSIM | /bundlecash |
| Physical SIM — product price > facial value | /recharge → /bundle |
| Physical SIM — product price ≤ facial value | /bundlecash |
Orange brand is not available for this endpoint and will return
BRAND_NOT_AVAILABLE.
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-..."
},
"message": "Activation completed successfully.",
"meta": { "requestId": "..." }
}
Success data fields:
| Field | Type | Description |
|---|---|---|
| msisdnId | string | Assigned phone number |
| qrCode | string | null | QR code for eSIM activation (null for physical SIM) |
⏱️ The generated QR code (qrCode) is valid for 24 hours
from the moment of activation. After that period, the QR expires and cannot be used to install the eSIM.
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| BRAND_NOT_AVAILABLE | 400 | Orange brand is not available for this endpoint |
| WALLET_NOT_FOUND | 500 | No wallet associated to user |
| PRODUCT_NOT_FOUND | 400 | Requested product not found |
| ICC_ID_REQUIRED | 400 | iccId missing when simType is "sim" |
| ACTIVATION_COST_UNAVAILABLE | 400 | Could not determine the activation cost for the SIM |
| ICC_ID_NOT_AVAILABLE | 400 | The provided ICC ID is not available for activation |
| INSUFFICIENT_BALANCE | 400 | Wallet balance too low — retry after topping up the wallet |
| ACTIVATION_SAVE_FAILED | 500 |
SIM activated but DB record failed — contact support with the msisdnId in
error.details
|
/api/v2/msmvl/activation/recharge
Step 2 — Charge the user's wallet and trigger the external recharge for the number. Call this after a
successful
POST /activation.
For physical SIM: charges only the difference between the product price and the SIM facial value. If the
facial value already covers the full product price, the wallet is not charged and the operation succeeds
immediately. In that case, you may also skip this endpoint entirely and call
/bundlecash directly instead of invoking /recharge +
/bundle separately.
Body (JSON):
{
"mobileNumber": "612345678"
}
Body fields:
| Field | Type | Description |
|---|---|---|
| mobileNumber | string | Mobile number from the activation step (required) |
Success response:
{
"data": {
"msisdnId": "612345678",
"valueCharged": 5.00
},
"message": "Recharge completed successfully. 5 EUR have been deducted from the wallet.",
"meta": { "requestId": "..." }
}
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| ACTIVATION_NOT_FOUND | 404 | No activation registered for this mobile number |
| FORBIDDEN | 403 | The activation belongs to a different user |
| ACTIVATION_PRODUCT_MISSING | 500 | Activation has no product associated |
| PRODUCT_NOT_FOUND | 400 | Requested product not found |
| ICC_ID_MISSING | 500 | Physical SIM activation has no ICCID associated |
| ACTIVATION_COST_UNAVAILABLE | 400 | Could not determine the recharge cost for this SIM |
| WALLET_NOT_FOUND | 500 | No wallet associated to user |
| INSUFFICIENT_BALANCE | 400 | Wallet balance too low — retry after topping up the wallet |
| WALLET_UPDATE_FAILED | 500 | Failed to deduct from wallet |
| BRAND_NOT_MAPPED | 400 | Brand could not be mapped to the configured recharge product |
| RECHARGE_FAILED | 500 | External recharge call failed |
/api/v2/msmvl/activation/bundle
Step 3a (physical SIM) — Purchases the bundle to apply the product tariff to the number.
Body (JSON):
{
"mobileNumber": "612345678"
}
Body fields:
| Field | Type | Description |
|---|---|---|
| mobileNumber | string | Mobile number from the activation step (required) |
Success response:
{
"data": {
"msisdnId": "612345678",
"provisionId": "PROV-123456"
},
"message": "Bundle purchased successfully.",
"meta": { "requestId": "..." }
}
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| ACTIVATION_NOT_FOUND | 404 | No activation registered for this mobile number |
| FORBIDDEN | 403 | The activation belongs to a different user |
| ACTIVATION_PRODUCT_MISSING | 500 | Activation has no product associated |
| PRODUCT_NOT_FOUND | 400 | Requested product not found |
| BUNDLE_FAILED | 500 | Bundle purchase failed — contact support |
/api/v2/msmvl/activation/bundlecash
Combines the recharge (/recharge) and bundle purchase (/bundle) into a single
call. Can be used in two scenarios:
/recharge and
/bundle.
/recharge and /bundle and call this endpoint directly
to apply the bundle in one step.
Body (JSON):
{
"mobileNumber": "612345678"
}
Body fields:
| Field | Type | Description |
|---|---|---|
| mobileNumber | string | Mobile number from the activation step (required) |
Success response:
{
"data": {
"msisdnId": "612345678",
"basketReference": "REF-123",
"basketId": "BKT-456",
"localReference": "LOC-789"
},
"message": "BundleCash applied successfully.",
"meta": { "requestId": "..." }
}
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| ACTIVATION_NOT_FOUND | 404 | No activation registered for this mobile number |
| FORBIDDEN | 403 | The activation belongs to a different user |
| BUNDLECASH_REQUIRES_ESIM | 400 | BundleCash is only valid for eSIM activations or physical SIM activations where the product price ≤ facial value |
| ACTIVATION_PRODUCT_MISSING | 500 | Activation has no product associated |
| PRODUCT_NOT_FOUND | 400 | Requested product not found |
| BUNDLECASH_FAILED | 500 | BundleCash application failed — contact support |
/api/v2/msmvl/activation/deactivation-roaming
Step 4 — Deactivates roaming control for the activated number. Call this after bundle/bundlecash succeeds. For Lyca Globe products, the operation is skipped automatically and success is returned.
Body (JSON):
{
"mobileNumber": "612345678"
}
Body fields:
| Field | Type | Description |
|---|---|---|
| mobileNumber | string | Mobile number from the activation step (required) |
Success response:
{
"data": { "msisdnId": "612345678" },
"message": "Roaming deactivated successfully.",
"meta": { "requestId": "..." }
}
Possible errors:
| Code | HTTP | Description |
|---|---|---|
| ACTIVATION_NOT_FOUND | 404 | No activation registered for this mobile number |
| FORBIDDEN | 403 | The activation belongs to a different user |
/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": "..." }
}
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": "..." }
}