Skip to content

Profile API

User profile view, update, PDPL data portability export, and account deletion.

Per T-06-07: No endpoint accepts userId from the request body. All operations are scoped to the authenticated user's JWT.


GET /profile

Return the authenticated user's profile aggregate, including activated SIM count and eSIM-store currency preference.

Requires authentication.

Example Request

GET /profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Response

200 OK

json
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "phone": "+966501234567",
  "email": "ahmed@example.com",
  "name": "Ahmed Al-Rashid",
  "identityType": "citizen",
  "appRole": "end_user",
  "preferredCurrency": "SAR",
  "activatedSimCount": 3,
  "createdAt": "2026-04-30T12:00:00.000Z"
}

For email-only users, phone is null. For phone-only users, email is null. preferredCurrency is USD, SAR, AED, EUR, GBP, EGP, or null. null means store browse uses the explicit request currency first, then the USD base default. On store checkout it is the fallback order currency when the request sends none.

Error Responses

CodeStatusCondition
AUTH_REQUIRED401Missing or invalid token

PUT /profile

Update allowed profile fields. name, email, and preferredCurrency can be updated here. Phone changes require POST /auth/change-phone with OTP verification.

Requires authentication.

Per T-06-08: Zod validation and whitelist — only name, email, and preferredCurrency are accepted.

Request Body

FieldTypeRequiredDescription
namestringNoUpdated name (1–255 characters)
emailstringNoUpdated email address
preferredCurrencyUSD | SAR | AED | EUR | GBP | EGP | nullNoPersistent eSIM-store presentment preference. Send null to clear it

Example Request

PUT /profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
json
{
  "name": "Ahmed Mohammed Al-Rashid",
  "email": "ahmed.new@example.com",
  "preferredCurrency": "SAR"
}

Partial update (name only):

json
{
  "preferredCurrency": null
}

Response

200 OK

json
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "phone": "+966501234567",
  "email": "ahmed.new@example.com",
  "name": "Ahmed Mohammed Al-Rashid",
  "identityType": "citizen",
  "appRole": "end_user",
  "preferredCurrency": "SAR",
  "activatedSimCount": 3,
  "createdAt": "2026-04-30T12:00:00.000Z"
}

Error Responses

CodeStatusCondition
AUTH_REQUIRED401Missing or invalid token
VALIDATION_ERROR400Invalid name or email format

GET /profile/export

PDPL (Personal Data Protection Law) data portability export. Returns all user data in a structured format with compliance metadata.

Requires authentication.

Per T-06-07: Export is scoped to the JWT owner only. No cross-user lookup path exists.

Query Parameters

ParameterTypeDefaultDescription
formatstringjsonExport format (currently only json supported)

Example Request

GET /profile/export?format=json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Response

200 OK

json
{
  "format": "json",
  "exportedAt": "2026-05-05T08:30:00.000Z",
  "data": {
    "profile": {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "phone": "+966501234567",
      "email": "ahmed@example.com",
      "name": "Ahmed Al-Rashid",
      "identityType": "citizen",
      "appRole": "end_user",
      "preferredCurrency": "SAR",
      "createdAt": "2026-04-30T12:00:00.000Z"
    },
    "activations": [
      {
        "id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
        "iccid": "LPA:1$SMDP.DEV.SKYTE.SA$***",
        "simType": "esim",
        "smdpAddress": "SMDP.DEV.SKYTE.SA",
        "matchingId": "SKYTE-DEV-0001",
        "activationCodeRaw": "LPA:1$SMDP.DEV.SKYTE.SA$SKYTE-DEV-0001",
        "status": "activated",
        "createdAt": "2026-05-05T08:30:00.000Z"
      }
    ],
    "orders": [],
    "payments": [],
    "storeOrders": [
      {
        "orderId": "550e8400-e29b-41d4-a716-44665544e401",
        "orderStatus": "completed",
        "product": {
          "id": "550e8400-e29b-41d4-a716-44665544e101",
          "nameEn": "Saudi Arabia 3 GB",
          "nameAr": "السعودية 3 جيجابايت"
        },
        "presentmentCurrency": "SAR",
        "presentmentAmount": "18.71",
        "fxRateUsed": "3.75",
        "retailUsdSnapshot": "4.99",
        "smdpAddress": "SMDP.STORE.DEV.SKYTE.SA",
        "matchingId": "STORE-8F3A1C2B",
        "activationCodeRaw": "1$SMDP.STORE.DEV.SKYTE.SA$STORE-8F3A1C2B",
        "iccid": "8900000000000000001",
        "issuedAt": "2026-05-05T08:32:00.000Z",
        "createdAt": "2026-05-05T08:30:00.000Z"
      }
    ]
  },
  "metadata": {
    "pdplCompliant": true,
    "requestId": "export-a1b2c3d4-20260505",
    "retentionPolicyDays": 90
  }
}

Error Responses

CodeStatusCondition
AUTH_REQUIRED401Missing or invalid token

DELETE /profile

Request account deletion. This is a soft delete — the user record is marked inactive with a deletionRequestedAt timestamp. Data is retained during the mandatory PDPL retention period, then purged.

Requires authentication.

The request also stamps the retention lifecycle on the caller's records. Activations and store orders both get deletionRequestedAt, and store orders additionally get retainUntil set to the request time plus the 365-day retention policy. Once that date passes, POST /compliance/retention/sweep scrubs the store order's eSIM payload — smdpAddress, matchingId, activationCodeRaw and iccid are nulled and deletedAt is stamped. The order row itself is kept because the purchase and its payment are a financial record.

Per T-06-09: Auditable with PROFILE_DELETION_REQUESTED event. Per T-06-07: Uses JWT context userId only.

Request Body (Optional)

FieldTypeRequiredDescription
reasonstringNoOptional reason for deletion

Example Request

DELETE /profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
json
{
  "reason": "No longer need the service"
}

Without body:

DELETE /profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Response

200 OK

json
{
  "deleted": true,
  "purgedAt": null,
  "message": "Account deletion requested. Your data will be retained during the mandatory retention period, then permanently deleted."
}

Arabic response (Accept-Language: ar):

json
{
  "deleted": true,
  "purgedAt": null,
  "message": "تم طلب حذف الحساب. ستُحتفظ بياناتك خلال فترة الاحتفاظ الإلزامية ثم تُحذف نهائيًا."
}

purgedAt is null while data retention is pending. Once fully purged, purgedAt contains the timestamp.

Error Responses

CodeStatusCondition
AUTH_REQUIRED401Missing or invalid token

Internal documentation - Activation System