> ## Documentation Index
> Fetch the complete documentation index at: https://opencals.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Get current customer profile



## OpenAPI

````yaml /api-reference/openapi.json get /storefront/self-service/profile
openapi: 3.0.0
info:
  title: Opencals API
  description: >
    # Opencals Storefront API


    Build custom booking storefronts with the Opencals Storefront API. Browse
    services, check real-time availability, manage carts, process payments, and
    complete bookings — all programmatically.


    ---


    ## Getting Started


    ### 1. Create an Account


    Sign up at [app.opencals.com](https://app.opencals.com) and set up your
    store with services, staff members, locations, and schedules.


    ### 2. Generate a Storefront API Key


    Navigate to **Settings > API Keys** in your dashboard. Create a new
    **Storefront API Key**. Each key is scoped to your store and starts with
    `sfk_`.


    ### 3. Make Your First Request


    ```bash

    curl -H "X-Api-Key: sfk_your_key_here" \
      https://api.opencals.com/customer/products
    ```


    This returns a paginated list of your store's active services.


    ---


    ## Authentication


    ### Storefront API Key


    All requests require a **Storefront API Key** in the `X-Api-Key` header:


    ```

    X-Api-Key: sfk_your_key_here

    ```


    This key identifies your store. It should be kept server-side (e.g., in
    environment variables) and never exposed to the browser.


    ### Customer Authentication


    Some endpoints require a logged-in customer (viewing appointments, managing
    profile). Customers authenticate via credentials and receive JWT tokens:


    ```http

    POST /auth/customer/sign-in

    X-Api-Key: sfk_your_key_here

    Content-Type: application/json


    {
      "email": "customer@example.com",
      "password": "securepassword"
    }

    ```


    **Response:**

    ```json

    {
      "accessToken": "eyJhbGciOi...",
      "refreshToken": "eyJhbGciOi..."
    }

    ```


    Include the customer token alongside the API key for authenticated requests:

    ```

    Authorization: Bearer <customer_access_token>

    X-Api-Key: sfk_your_key_here

    ```


    ### Customer Auth Endpoints


    | Method | Endpoint | Description |

    |--------|----------|-------------|

    | `POST` | `/auth/customer/sign-up` | Register a new customer (sends
    verification email) |

    | `POST` | `/auth/customer/sign-in` | Sign in with email + password |

    | `POST` | `/auth/customer/oauth` | Sign in/register via OAuth provider
    (e.g., Google) |

    | `POST` | `/auth/customer/verify-email` | Verify email with token from
    verification email |

    | `POST` | `/auth/customer/request-email-verification` | Resend verification
    email |

    | `POST` | `/auth/customer/request-password-reset` | Send password reset
    email |

    | `POST` | `/auth/customer/reset-password` | Reset password with token |

    | `GET`  | `/auth/customer/refresh` | Refresh tokens (pass refresh token as
    Bearer) |


    ---


    ## Booking Flows


    The booking flow depends on your product configuration. Below are the common
    patterns.


    ### Standard Booking (Single Time Slot)


    The most common flow — customer picks a service, selects a date/time, and
    books.


    ```

    1. GET  /customer/products                              → Browse services

    2. GET  /customer/products/:id/current-availabilities    → Get available
    time slots for a date
          ?date=2026-06-15&timezone=America/New_York
    3. POST /customer/appointments                           → Create
    appointment with chosen slot
          { slot: { productId, fromDate, fromTime, toDate, toTime }, numberOfAttendees: 1 }
    4. POST /customer/cart                                   → Create or get
    cart

    5. POST /customer/cart/items                             → Add appointment
    to cart
          { appointmentId: "..." }
    6. POST /customer/cart/checkout/start                    → Start checkout
    with payment provider
          { provider: "stripe" }
    7. POST /customer/cart/checkout/save-customer            → Save customer
    info
          { customer: { email, firstName, lastName } }
    8. POST /customer/cart/checkout/submit                   → Complete booking
    & capture payment

    ```


    ### Custom Duration / Date Range Booking


    When a product has **custom duration** enabled (e.g., car rentals, venue
    bookings), customers select a date range instead of a single time slot.


    **How to detect:** The product's `isCustomDuration` field is `true`.


    ```

    1. GET /customer/products/:id/current-availability-ranges   → Get available
    date ranges
          ?timezone=America/New_York
    2. UI shows a date range picker instead of individual slots

    3. POST /customer/appointments
          { slot: { productId, fromDate: "2026-06-15", fromTime: "09:00:00",
                    toDate: "2026-06-18", toTime: "17:00:00" } }
    4. Continue with cart → checkout flow as above

    ```


    ### Group Appointments


    When a product supports multiple attendees (`maxAttendees > 1`), display an
    attendees selector.


    ```

    POST /customer/appointments

    {
      "slot": { ... },
      "numberOfAttendees": 4
    }

    ```


    ### Location-First Flow


    When a store has multiple locations, let the customer pick a location first,
    then filter services and availability by location.


    ```

    1. GET /customer/locations                                → List all
    locations

    2. User selects a location

    3. GET /customer/products?locationId=<locationId>         → Products at that
    location

    4. GET /customer/products/:id/current-availabilities
          ?date=2026-06-15&locationId=<locationId>            → Slots at that location
    5. POST /customer/appointments
          { slot: { ..., locationId: "<locationId>" } }
    ```


    ### Staff-First Flow


    When staff member selection is important (e.g., hair salons), let customers
    choose their preferred staff member.


    ```

    1. GET /customer/staff-members                            → List staff
    members

    2. User selects a staff member

    3. GET /customer/products/:id/current-availabilities
          ?date=2026-06-15&staffMemberId=<staffMemberId>      → Slots with that staff member
    4. POST /customer/appointments
          { slot: { ..., staffMemberId: "<staffMemberId>" } }
    ```


    ### Combined Flow (Location + Staff + Service)


    All filters can be combined:


    ```

    GET /customer/products/:id/current-availabilities
        ?date=2026-06-15
        &locationId=<locationId>
        &staffMemberId=<staffMemberId>
        &timezone=America/New_York
    ```


    ---


    ## Product Configuration Flags


    Products have configuration fields that determine which UI elements to
    display. Check these fields when rendering your booking interface:


    | Field | Type | UI Behavior |

    |-------|------|-------------|

    | `isCustomDuration` | `boolean` | `true` → show date range picker; `false`
    → show single time slot picker |

    | `maxAttendees` | `number` | `> 1` → show attendees selector; `1` → hide it
    |

    | `skipCheckout` | `boolean` | `true` → skip payment step, book directly;
    `false` → normal checkout |

    | `fixedStartTimes` / `fixedEndTimes` | `string[]` | If present, only these
    specific times are bookable |

    | `locations` | `Location[]` | If populated, show location selector |

    | `staffMembers` | `StaffMember[]` | If populated, show staff member
    selector |

    | `price` | `number` | Service price; `0` = free |

    | `minPrice` / `maxPrice` | `number` | Price range for variable-priced
    services |

    | `duration` | `number` | Service duration in seconds |

    | `minDuration` / `maxDuration` | `number` | Duration range for custom
    duration services |

    | `images` | `Image[]` | Product images for gallery display |

    | `description` | `string` | Product description (may contain markdown) |


    ---


    ## Endpoint Reference


    ### Products


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/products` | API key | List all active products
    (paginated) |

    | `GET` | `/customer/products/:id` | API key | Get product by ID |

    | `GET` | `/customer/products/slug/:slug` | API key | Get product by URL
    slug |

    | `GET` | `/customer/products/:id/current-availabilities` | API key | Get
    bookable time slots for a date |

    | `GET` | `/customer/products/:id/current-availability-ranges` | API key |
    Get available date ranges (for custom duration) |

    | `GET` | `/customer/products/:id/nearest-availability` | API key | Find
    next available slot |


    **Availability query parameters:**


    | Parameter | Required | Description |

    |-----------|----------|-------------|

    | `date` | Yes (for current-availabilities) | Date in `YYYY-MM-DD` format |

    | `locationId` | No | Filter by location |

    | `staffMemberId` | No | Filter by staff member |

    | `timezone` | No | Timezone for date/time calculations (e.g.,
    `America/New_York`) |


    ### Product Collections


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/product-collections` | API key | List all collections
    (paginated) |

    | `GET` | `/customer/product-collections/slug/:slug` | API key | Get
    collection by slug |


    ### Locations


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/locations` | API key | List all locations (paginated) |

    | `GET` | `/customer/locations/:id` | API key | Get location by ID |

    | `GET` | `/customer/locations/slug/:slug` | API key | Get location by slug
    |


    ### Staff Members


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/staff-members` | API key | List all staff members
    (paginated) |

    | `GET` | `/customer/staff-members/slug/:slug` | API key | Get staff member
    by slug |


    ### Cart


    All cart endpoints use the `X-Cart-Id` header to identify the cart.


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `POST` | `/customer/cart` | API key | Create or retrieve a cart |

    | `GET` | `/customer/cart` | API key | Get current cart |

    | `POST` | `/customer/cart/items` | API key | Add an appointment to the cart
    |

    | `DELETE` | `/customer/cart/items/:itemId` | API key | Remove item from
    cart |

    | `POST` | `/customer/cart/extend` | API key | Extend cart expiration (5
    min) |


    **Adding items to cart:**

    ```json

    POST /customer/cart/items

    X-Cart-Id: <cart_id>


    { "appointmentId": "appointment-uuid-here" }

    ```


    ### Add-Ons


    Add-ons are optional extras customers can attach to a cart item at checkout
    (equipment rentals, upgrades, accessories, etc.). Add-ons are scoped to
    products — only add-ons assigned to the booked service appear.


    **Storefront (listing):**


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/storefront/add-ons` | API key | List add-ons (filter by
    `productId`) |

    | `GET` | `/storefront/add-ons/:id` | API key | Get add-on by ID |

    | `GET` | `/storefront/add-ons/slug/:slug` | API key | Get add-on by slug |

    | `GET` | `/storefront/products/:id/add-ons` | API key | List add-ons for a
    specific product |


    **Cart (selection):**


    All cart add-on endpoints require the `X-Cart-Id` header.


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `POST` | `/storefront/cart/add-ons` | API key | Add an add-on to a cart
    item |

    | `PATCH` | `/storefront/cart/add-ons/:id` | API key | Update add-on
    quantity |

    | `DELETE` | `/storefront/cart/add-ons/:id` | API key | Remove add-on from
    cart |


    **Adding an add-on to a cart item:**

    ```json

    POST /storefront/cart/add-ons

    X-Cart-Id: <cart_id>


    {
      "cartItemId": "uuid-of-cart-item",
      "addOnId": "uuid-of-add-on",
      "quantity": 1
    }

    ```


    The system validates that the add-on is assigned to the cart item's product
    and that `quantity` does not exceed `maxQuantity` (if set). For
    duration-multiplied add-ons, quantity is auto-set to match the service
    duration units — send any value and it will be overridden.


    **Add-on object (storefront response):**

    ```json

    {
      "id": "addon-uuid",
      "slug": "deep-conditioning",
      "title": "Deep Conditioning Treatment",
      "description": "Intensive moisture treatment added to any color or cut service.",
      "price": 20.00,
      "taxable": true,
      "durationMultiplied": false,
      "maxQuantity": 1,
      "status": "active",
      "imageId": "img-uuid-or-null"
    }

    ```


    **Pricing notes:**

    - `price` — unit price. For duration-multiplied add-ons, multiply by
    duration units to get the total.

    - `durationMultiplied: true` — quantity is auto-set to the number of
    base-duration units booked (useful for per-day or per-hour charges).

    - Prices are snapshotted at cart/order creation. Later catalog price changes
    do not affect existing orders.


    **In the order response**, add-ons appear as `addOnLineItems` on each line
    item:

    ```json

    {
      "lineItems": [
        {
          "id": "...",
          "appointmentId": "...",
          "addOnLineItems": [
            {
              "id": "...",
              "addOnId": "...",
              "title": "Deep Conditioning Treatment",
              "quantity": 1,
              "originalUnitPrice": 20.00,
              "unitTaxAmount": 3.33,
              "totalPrice": 20.00
            }
          ]
        }
      ]
    }

    ```


    ### Checkout


    All checkout endpoints require the `X-Cart-Id` header.


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `POST` | `/customer/cart/checkout/start` | API key | Start checkout
    (initialize payment) |

    | `POST` | `/customer/cart/checkout/save-customer` | API key | Save customer
    info to cart |

    | `GET` | `/customer/cart/checkout/questions/:language` | API key | Get
    checkout questions |

    | `POST` | `/customer/cart/checkout/save-answers` | API key | Save checkout
    question answers |

    | `POST` | `/customer/cart/checkout/submit` | API key | Submit checkout
    (capture payment, create order) |


    **Start checkout:**

    ```json

    POST /customer/cart/checkout/start

    X-Cart-Id: <cart_id>


    {
      "provider": "stripe",
      "customer": {
        "email": "john@example.com",
        "firstName": "John",
        "lastName": "Smith"
      }
    }

    ```


    The `provider` field accepts: `stripe`, `cash`, or other configured payment
    providers.


    **Submit checkout response** includes order details and optionally
    auto-generated customer auth tokens:

    ```json

    {
      "order": { "id": "...", "name": "#1001", ... },
      "tokens": {
        "accessToken": "eyJ...",
        "refreshToken": "eyJ..."
      }
    }

    ```


    ### Appointments (Customer Authenticated)


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `POST` | `/customer/appointments` | API key (+ optional customer token) |
    Create appointment |

    | `GET` | `/customer/appointments` | Customer token | List customer
    appointments (paginated) |

    | `GET` | `/customer/appointments/:id` | Customer token | Get appointment
    details |

    | `PUT` | `/customer/appointments/:id/reschedule` | Customer token |
    Reschedule appointment |

    | `PUT` | `/customer/appointments/:id/cancel` | Customer token | Cancel
    appointment |

    | `POST` | `/customer/appointments/:id/feedback` | Customer token | Submit
    feedback |

    | `GET` | `/customer/appointments/preferences/booking-history` | Customer
    token | Get booking preferences |


    ### Orders (Customer Authenticated)


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/orders` | Customer token | List customer orders
    (paginated) |

    | `GET` | `/customer/orders/:id` | Customer token | Get order details |


    ### Customer Profile (Customer Authenticated)


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/profile` | Customer token | Get customer profile |

    | `PUT` | `/customer/profile` | Customer token | Update customer profile |

    | `PUT` | `/customer/password` | Customer token | Change password |


    ### Store


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/stores/public-settings` | API key | Get store public
    settings |


    **Public settings response includes:**

    - `name` — store display name

    - `domain` — store domain

    - `currency` — store currency code (e.g., `USD`)

    - `settings` — general store settings (timezone, locale, etc.)

    - `storefrontSettings` — presentation config (logo, colors, banners, etc.)

    - `contactInfo` — store contact information

    - `features` — enabled plan features


    ### Payment


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/payment/providers` | API key | List available payment
    providers |

    | `GET` | `/customer/payment/settings` | API key | Get public payment
    settings |


    ### Images


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/images/:id` | API key | Get image metadata by ID |


    ### Checkout Questions


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/checkout-questions/:productId/translations/:language` |
    API key | Get checkout questions for a product |


    ### Feedback Questions


    | Method | Endpoint | Auth | Description |

    |--------|----------|------|-------------|

    | `GET` | `/customer/feedback-questions/:productId/translations/:language` |
    Customer token | Get feedback questions for a product |


    ---


    ## Checkout Flow Detail


    ### Step 1: Create Appointment


    Before adding to a cart, create the appointment with the selected time slot:


    ```json

    POST /customer/appointments

    {
      "slot": {
        "productId": "product-uuid",
        "fromDate": "2026-06-15",
        "fromTime": "09:00:00",
        "toDate": "2026-06-15",
        "toTime": "10:00:00",
        "locationId": "location-uuid-or-null",
        "staffMemberId": "staff-uuid-or-null"
      },
      "numberOfAttendees": 1
    }

    ```


    All date/time values are in **UTC**. Convert from the user's timezone before
    sending.


    ### Step 2: Create Cart & Add Items


    ```json

    POST /customer/cart

    → Returns { "id": "cart-uuid", ... }


    POST /customer/cart/items

    X-Cart-Id: cart-uuid

    { "appointmentId": "appointment-uuid" }

    ```


    Carts expire automatically. Use `POST /customer/cart/extend` to add 5
    minutes.


    ### Step 3: Start Checkout


    ```json

    POST /customer/cart/checkout/start

    X-Cart-Id: cart-uuid

    {
      "provider": "stripe",
      "customer": { "email": "john@example.com", "firstName": "John", "lastName": "Smith" }
    }

    ```


    Response includes payment provider details (e.g., Stripe `clientSecret` for
    Elements).


    ### Step 4: Save Customer Info


    If not provided in start, save customer details separately:


    ```json

    POST /customer/cart/checkout/save-customer

    X-Cart-Id: cart-uuid

    {
      "customer": { "email": "john@example.com", "firstName": "John", "lastName": "Smith" }
    }

    ```


    For logged-in customers, pass `{ "customer": { "customerId":
    "existing-customer-uuid" } }`.


    ### Step 5: Checkout Questions (Optional)


    If the store has checkout questions configured:


    ```

    GET /customer/cart/checkout/questions/en

    X-Cart-Id: cart-uuid

    → Returns array of questions with types (text, select, checkbox, etc.)


    POST /customer/cart/checkout/save-answers

    X-Cart-Id: cart-uuid

    { "answers": [{ "questionId": "...", "value": "..." }] }

    ```


    ### Step 6: Submit Checkout


    ```json

    POST /customer/cart/checkout/submit

    X-Cart-Id: cart-uuid

    {}

    ```


    Response includes the created order and optionally customer auth tokens for
    auto-login.


    ---


    ## Payment Integration


    ### Available Providers


    Fetch configured payment providers for your store:


    ```

    GET /customer/payment/providers

    → [{ "name": "stripe", "displayName": "Credit Card", ... }]

    ```


    ### Stripe Integration


    1. Get Stripe publishable key from `GET /customer/payment/settings`

    2. Start checkout with `provider: "stripe"` — response includes
    `clientSecret`

    3. Use Stripe Elements / Payment Element with the `clientSecret`

    4. After Stripe confirms payment client-side, call `POST /checkout/submit`


    ### Cash / Pay at Venue


    Start checkout with `provider: "cash"`. No payment processing needed —
    submit directly.


    ### Redirect-Based Payments


    Some providers redirect the customer to an external page. The start response
    includes a `redirectUrl`. After payment, the customer is redirected back to
    your `thankYouUrl`.


    ---


    ## Store Settings


    Use `GET /customer/stores/public-settings` to retrieve store configuration
    for your template:


    - **Store name** → display in header/navbar

    - **Logo** → from `storefrontSettings`

    - **Currency** → format prices correctly (e.g., `USD`, `EUR`)

    - **Timezone** → convert availability times to/from the store's timezone

    - **Contact info** → display in footer or contact page

    - **Features** → check which features are enabled (e.g., customer portal)


    ---


    ## Rate Limiting


    Requests are rate-limited per API key:


    | Category | Limit |

    |----------|-------|

    | General | 100 requests / 60 seconds |

    | Authentication | 20 requests / 10 seconds |

    | Password reset | 5 requests / hour |

    | Registration | 10 requests / minute |


    When rate-limited, you'll receive a `429 Too Many Requests` response.


    ---


    ## Response Format


    All responses use **camelCase** property names:


    ```json

    {
      "id": "abc-123",
      "title": "Haircut",
      "maxAttendees": 1,
      "duration": 3600,
      "staffMembers": [
        { "id": "staff-1", "firstName": "John", "lastName": "Doe" }
      ]
    }

    ```


    ### Pagination


    List endpoints return paginated collections:


    ```json

    {
      "data": [ ... ],
      "meta": {
        "total": 42,
        "page": 1,
        "limit": 10,
        "totalPages": 5
      }
    }

    ```


    Use `?page=2&limit=20` query parameters to paginate.


    ---


    ## Error Responses


    ```json

    {
      "statusCode": 400,
      "message": "Validation failed",
      "errors": [
        { "property": "email", "messages": ["Email is required"] }
      ]
    }

    ```


    | Status | Meaning |

    |--------|---------|

    | 400 | Validation error |

    | 401 | Invalid or missing API key / customer token |

    | 404 | Resource not found |

    | 429 | Rate limit exceeded |


    ---


    ## Timezone Handling


    - All date/time values in API requests and responses are in **UTC**

    - Pass the `timezone` query parameter to availability endpoints to get slots
    converted to a specific timezone

    - Use the store's timezone from public settings as the default display
    timezone

    - Convert user-selected times to UTC before creating appointments


    ---


    ## Webhooks (Coming Soon)


    Webhook support for real-time notifications is planned. Events will include:


    - `product.created`, `product.updated`, `product.deleted`

    - `staff_member.created`, `staff_member.updated`, `staff_member.deleted`

    - `location.created`, `location.updated`, `location.deleted`

    - `store.settings_updated`

    - `collection.updated`


    Use webhooks to invalidate cached data in your deployed storefronts.
  version: '1.0'
  contact: {}
servers:
  - url: https://api.opencals.com
security:
  - Storefront API key: []
tags: []
paths:
  /storefront/self-service/profile:
    get:
      tags:
        - Self-Service
      summary: Get current customer profile
      operationId: selfService_getProfile
      parameters: []
      responses:
        '200':
          description: Customer profile returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SelfServiceProfileResponse'
        '401':
          description: Unauthorized
      security:
        - bearer: []
components:
  schemas:
    SelfServiceProfileResponse:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier of the customer
          example: 123e4567-e89b-12d3-a456-426614174000
        externalId:
          type: string
          description: External customer identifier from integrated system
          example: '1234567890'
        firstName:
          type: string
          description: Customer first name
          example: John
          nullable: true
        lastName:
          type: string
          description: Customer last name
          example: Smith
          nullable: true
        email:
          type: string
          description: Customer email address
          example: john.smith@example.com
          nullable: true
        phone:
          type: string
          description: Customer phone number
          example: '+12135550123'
          nullable: true
        password:
          type: string
          description: Hashed password of the customer
          nullable: true
        storeId:
          type: string
          description: ID of the store that owns this customer record
          example: store-uuid
        language:
          $ref: '#/components/schemas/LanguageCode'
          example: en
        refreshToken:
          type: string
          description: Customer refresh token for authentication
          example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
          nullable: true
          writeOnly: true
        createdAt:
          format: date-time
          type: string
          description: Date when the customer record was created
          example: '2023-01-15T10:30:00Z'
        updatedAt:
          format: date-time
          type: string
          description: Date when the customer record was last updated
          example: '2023-02-20T14:15:00Z'
          nullable: true
        emailVerifiedAt:
          format: date-time
          type: string
          description: Date and time when the customer verified email
          example: '2023-01-02T00:00:00Z'
          nullable: true
        deletedAt:
          format: date-time
          type: string
          description: Date and time when the order was soft-deleted
          example: '2023-06-03T09:45:00Z'
          nullable: true
        isEmailVerified:
          type: boolean
          description: Indicates whether customer email is verified
        isPasswordSet:
          type: boolean
          description: Indicates whether customer password is set
      required:
        - id
        - externalId
        - firstName
        - lastName
        - email
        - phone
        - password
        - storeId
        - language
        - refreshToken
        - createdAt
        - updatedAt
        - emailVerifiedAt
        - deletedAt
        - isEmailVerified
        - isPasswordSet
    LanguageCode:
      type: string
      description: Language code for this translation
      enum:
        - af
        - ak
        - am
        - ar
        - as
        - az
        - be
        - bg
        - bm
        - bn
        - bo
        - br
        - bs
        - ca
        - ce
        - cs
        - cu
        - cy
        - da
        - de
        - dz
        - ee
        - el
        - en
        - eo
        - es
        - et
        - eu
        - fa
        - ff
        - fi
        - fo
        - fr
        - fy
        - ga
        - gd
        - gl
        - gu
        - gv
        - ha
        - he
        - hi
        - hr
        - hu
        - hy
        - ia
        - id
        - ig
        - ii
        - is
        - it
        - ja
        - jv
        - ka
        - ki
        - kk
        - kl
        - km
        - kn
        - ko
        - ks
        - ku
        - kw
        - ky
        - lb
        - lg
        - ln
        - lo
        - lt
        - lu
        - lv
        - mg
        - mi
        - mk
        - ml
        - mn
        - mr
        - ms
        - mt
        - my
        - nb
        - nd
        - ne
        - nl
        - nn
        - 'no'
        - om
        - or
        - os
        - pa
        - pl
        - ps
        - pt
        - pt_br
        - pt_pt
        - qu
        - rm
        - rn
        - ro
        - ru
        - rw
        - sd
        - se
        - sg
        - si
        - sk
        - sl
        - sn
        - so
        - sq
        - sr
        - su
        - sv
        - sw
        - ta
        - te
        - tg
        - th
        - ti
        - tk
        - to
        - tr
        - tt
        - ug
        - uk
        - ur
        - uz
        - vi
        - vo
        - wo
        - xh
        - yi
        - yo
        - zh
        - zh_cn
        - zh_tw
        - zu
  securitySchemes:
    Storefront API key:
      type: apiKey
      in: header
      name: x-api-key
      description: Storefront API key (sfk_...)
      x-default: sfk_your_api_key

````