openapi: 3.0.3
info:
  title: OpenTiendas API
  version: 1.2.11
  description: OpenTiendas REST API documentation.
paths:
  /api/v1/brands/:
    get:
      operationId: List Brands
      description: >-
        Retrieve a paginated list of brands with optional filtering and
        ordering.
      parameters:
        - in: query
          name: brand_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter brands by a comma-separated list of brand IDs. Exact match on
            <code>brand.id</code>. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: internal_ids
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter brands by a comma-separated list of brand internal IDs. Exact
            match on <code>brand.internal_id</code>. Max 200 IDs.
          explode: false
          style: form
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
        - in: query
          name: slug
          schema:
            type: array
            items:
              type: string
          description: Filter brands by a comma-separated list of slugs. Max 200 slugs.
          explode: false
          style: form
        - name: sort
          required: false
          in: query
          description: >-
            Which field to use when ordering the results. Use '_asc' or '_desc'
            suffix to specify ascending or descending order. Valid values are:
            `name_asc`, `name_desc`.<p>Default value: ``name_asc``
          schema:
            type: string
      tags:
        - Brands
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedBrandList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - id: 2
                          name: Marca de Ejemplo
                          internal_id: BRAND-001
                          translations:
                            es-ES:
                              url: https://example.es/brand/example-brand
                            en-GB:
                              url: https://example.com/brand/example-brand
                            fr-FR:
                              url: https://example.fr/brand/example-brand
                  summary: Default fields
                AllFields(e.g.?fields=name,internalId,slug,...):
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - id: 2
                          name: Marca de Ejemplo
                          internal_id: BRAND-001
                          slug: marca-de-ejemplo
                          delivery_time_in_stock: 1
                          delivery_time_out_of_stock: 3
                          image_url: https://media.example.com/brand/brand-001.jpg
                          translations:
                            es-ES:
                              url: https://example.es/brand/example-brand
                              description: Descripción de la marca de ejemplo en español.
                              body_html: >-
                                <p>Descripción de la marca de ejemplo en formato
                                HTML.</p>
                              long_name: Marca de Ejemplo - Productos Ecológicos
                              meta_title: Marca de Ejemplo · Moda y Estilo de Vida
                              meta_description: >-
                                Descubre la Marca de Ejemplo, la elección número
                                1 para productos ecológicos.
                              size_guide_file:
                                name: guia_tallas.pdf
                                url: https://example.com/guia_tallas.pdf
                            en-GB:
                              url: https://example.com/brand/example-brand
                              description: This is an example brand.
                              body_html: <p>Example brand description in HTML format.</p>
                              long_name: Example Brand - Ecologically Friendly Goods
                              meta_title: Example Brand · Fashion and Lifestyle
                              meta_description: >-
                                Discover Example Brand, the #1 choice for
                                eco-friendly products.
                              size_guide_file:
                                name: size_guide.pdf
                                url: https://example.com/size_guide.pdf
                            fr-FR:
                              url: https://example.fr/brand/example-brand
                              description: Ceci est une marque d'exemple.
                              body_html: >-
                                <p>Description de la marque d'exemple en format
                                HTML.</p>
                              size_guide_file:
                                name: guide_des_tailles.pdf
                                url: https://example.com/guide_des_tailles.pdf
                  summary: All fields (e.g. ?fields=name,internal_id,slug,...)
          description: OK
    post:
      operationId: Create Brand
      description: Create a new brand with the provided details.
      tags:
        - Brands
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Brand'
            examples:
              POSTExample:
                value:
                  name: Marca de Ejemplo
                  internal_id: BRAND-001
                  image_url: https://external.server.com/brand_logo.jpg
                  delivery_time_in_stock: 1
                  delivery_time_out_of_stock: 3
                  translations:
                    es-ES:
                      description: Descripción de la marca de ejemplo en español.
                      body_html: >-
                        <p>Descripción de la marca de ejemplo en formato
                        HTML.</p>
                      long_name: Marca de Ejemplo - Productos Ecológicos
                      meta_title: Marca de Ejemplo · Moda y Estilo de Vida
                      meta_description: >-
                        Descubre la Marca de Ejemplo, la elección número 1 para
                        productos ecológicos.
                      size_guide_file:
                        name: guia_tallas.pdf
                        url: https://example.com/guia_tallas.pdf
                    en-GB:
                      description: This is an example brand.
                      body_html: <p>Example brand description in HTML format.</p>
                      size_guide_file:
                        name: size_guide.pdf
                        url: https://example.com/size_guide.pdf
                    fr-FR:
                      description: Ceci est une marque d'exemple.
                      body_html: >-
                        <p>Description de la marque d'exemple en format
                        HTML.</p>
                      size_guide_file:
                        name: guide_des_tailles.pdf
                        url: https://example.com/guide_des_tailles.pdf
                summary: POST Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Brand'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/Brand'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Brand'
              examples:
                POST201Example:
                  value:
                    - id: 2
                      name: Marca de Ejemplo
                      internal_id: BRAND-001
                      translations:
                        es-ES:
                          url: https://example.es/brand/example-brand
                        en-GB:
                          url: https://example.com/brand/example-brand
                        fr-FR:
                          url: https://example.fr/brand/example-brand
                  summary: POST 201 Example
          description: Created
  /api/v1/brands/{id}/:
    get:
      operationId: Get Brand Detail
      description: Retrieve detailed information about a specific brand by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Brands
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Brand'
              examples:
                DefaultFields:
                  value:
                    id: 2
                    name: Marca de Ejemplo
                    internal_id: BRAND-001
                    translations:
                      es-ES:
                        url: https://example.es/brand/example-brand
                      en-GB:
                        url: https://example.com/brand/example-brand
                      fr-FR:
                        url: https://example.fr/brand/example-brand
                  summary: Default fields
                AllFields(e.g.?fields=name,internalId,slug,...):
                  value:
                    id: 2
                    name: Marca de Ejemplo
                    internal_id: BRAND-001
                    slug: marca-de-ejemplo
                    delivery_time_in_stock: 1
                    delivery_time_out_of_stock: 3
                    image_url: https://media.example.com/brand/brand-001.jpg
                    translations:
                      es-ES:
                        url: https://example.es/brand/example-brand
                        description: Descripción de la marca de ejemplo en español.
                        body_html: >-
                          <p>Descripción de la marca de ejemplo en formato
                          HTML.</p>
                        long_name: Marca de Ejemplo - Productos Ecológicos
                        meta_title: Marca de Ejemplo · Moda y Estilo de Vida
                        meta_description: >-
                          Descubre la Marca de Ejemplo, la elección número 1
                          para productos ecológicos.
                        size_guide_file:
                          name: guia_tallas.pdf
                          url: https://example.com/guia_tallas.pdf
                      en-GB:
                        url: https://example.com/brand/example-brand
                        description: This is an example brand.
                        body_html: <p>Example brand description in HTML format.</p>
                        long_name: Example Brand - Ecologically Friendly Goods
                        meta_title: Example Brand · Fashion and Lifestyle
                        meta_description: >-
                          Discover Example Brand, the #1 choice for eco-friendly
                          products.
                        size_guide_file:
                          name: size_guide.pdf
                          url: https://example.com/size_guide.pdf
                      fr-FR:
                        url: https://example.fr/brand/example-brand
                        description: Ceci est une marque d'exemple.
                        body_html: >-
                          <p>Description de la marque d'exemple en format
                          HTML.</p>
                        size_guide_file:
                          name: guide_des_tailles.pdf
                          url: https://example.com/guide_des_tailles.pdf
                  summary: All fields (e.g. ?fields=name,internal_id,slug,...)
          description: OK
    patch:
      operationId: Update Brand
      description: Update an existing brand's details.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Brands
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedBrand'
            examples:
              PATCHExample:
                value:
                  name: Other Brand Name
                  internal_id: new_internal_id
                  translations:
                    en-GB:
                      description: Updated description for the example brand.
                    es-ES:
                      description: Descripción actualizada en español.
                summary: PATCH Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedBrand'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedBrand'
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Brand'
              examples:
                PATCH200Example:
                  value:
                    id: 2
                    name: Other Brand Name
                    internal_id: new_internal_id
                    translations:
                      es-ES:
                        url: https://example.es/brand/example-brand
                      en-GB:
                        url: https://example.com/brand/example-brand
                      fr-FR:
                        url: https://example.fr/brand/example-brand
                  summary: PATCH 200 Example
          description: OK
    delete:
      operationId: Delete Brand
      description: Delete a specific brand by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Brands
      security:
        - ApiKeyAuth: []
      responses:
        '204':
          description: No Content
  /api/v1/catalog/link-ids/:
    post:
      operationId: Bulk Link IDs
      description: >-
        <p>Links existing OpenTiendas products and variants with identifiers
        from external systems such as a PIM or ERP.</p><p>This endpoint is
        typically used during the initial migration or first synchronization to
        populate <code>internal_id</code> values for existing catalog
        records.</p><h3>Asynchronous processing</h3><p>This endpoint does not
        process the link operation within the request cycle. Before creating the
        job, OpenTiendas performs an initial validation of the request,
        including JSON format, payload structure, payload size and required
        top-level fields.</p><p>If the request fails this initial validation, no
        job is created and an error response is returned. The response may be
        <code>413 Request Entity Too Large</code> if the payload exceeds the
        maximum allowed size, or <code>400 Bad Request</code> for other
        validation errors.</p><p>If the request passes this initial validation,
        the endpoint creates and queues a job, then returns <code>202
        Accepted</code> with the corresponding <code>job_id</code>. This
        confirms that the request has been accepted for asynchronous processing,
        but does not mean that all identifiers have already been linked
        successfully.</p><p>Record-level matching, validations, and link
        operations are performed later, during job processing.</p><h3>Link
        behavior</h3><p>Each item attempts to match an existing variant using
        <code>ean</code> or <code>sku</code> +
        <code>supplier_internal_id</code>.</p><p>When exactly one matching
        variant is found, the provided <code>internal_id</code> values are
        assigned to the variant and/or its parent product.</p><p>If no matching
        variant is found, or if the match is ambiguous, the item is not linked
        and the result is reported in the job log.</p><p>This endpoint only
        links identifiers. It does not create, update, or delete catalog
        data.</p><p>Once linked, the assigned <code>internal_id</code> values
        can be used for bulk catalog updates and other operations.</p><h3>Job
        result</h3><p>The progress and result of the operation can be reviewed
        using the returned <code>job_id</code>.</p><p>The job log includes
        processing information, validation errors, match errors, affected
        product or variant identifiers when available, and a final summary with
        the total processed and failed records.</p><h3>Limits</h3><p>Maximum
        request payload: 10 MB. Requests exceeding this limit are rejected.</p>
      tags:
        - Products
        - Variants
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LinkIDs'
            examples:
              LinkIDsByEAN:
                value:
                  items:
                    - ean: '8431234567890'
                      product_internal_id: PIM-P-123
                      variant_internal_id: PIM-V-987
                summary: Link IDs by EAN
              LinkIDsBySKUAndSupplierInternalID:
                value:
                  items:
                    - sku: SKU-001
                      supplier_internal_id: SUP-9
                      product_internal_id: PIM-P-123
                      variant_internal_id: PIM-V-987
                summary: Link IDs by SKU and Supplier internal ID
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/LinkIDs'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/LinkIDs'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkJobCreationResponse'
              examples:
                POST202Example:
                  value:
                    - job_id: 91233456-9c4b-4d2a-8f1e-abcdef123456
                      status: pending
                  summary: POST 202 Example
          description: Accepted. The bulk link IDs job has been created.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LinkIDsErrorResponse'
              examples:
                POST400Example-Missing'productInternalId'Or'variantInternalId':
                  value:
                    detail: >-
                      Either 'product_internal_id' or 'variant_internal_id' must
                      be provided.
                  summary: >-
                    POST 400 Example - Missing 'product_internal_id' or
                    'variant_internal_id'
          description: >-
            Bad Request. The request payload is invalid or missing required
            fields.
        '413':
          description: >-
            Payload Too Large. The request payload exceeds the maximum allowed
            size.
  /api/v1/categories/:
    get:
      operationId: List Categories
      description: >-
        Retrieve a paginated list of categories with optional filtering and
        ordering.
      parameters:
        - in: query
          name: category_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter categories by a comma-separated list of category IDs. Exact
            match on <code>category.id</code>. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: internal_ids
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter categories by a comma-separated list of category internal
            IDs. Exact match on <code>category.internal_id</code>. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: is_root_folder
          schema:
            type: boolean
          description: Filter categories that are root folders (i.e., have no parent).
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - in: query
          name: parent_id
          schema:
            type: number
          description: Filter categories by parent category ID.
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
        - in: query
          name: slug
          schema:
            type: string
          description: Filter categories by a comma-separated list of slugs. Max 200 slugs.
        - name: sort
          required: false
          in: query
          description: >-
            Which field to use when ordering the results. Use '_asc' or '_desc'
            suffix to specify ascending or descending order. Valid values are:
            `name_asc`, `name_desc`.<p>Default value: ``name_asc``
          schema:
            type: string
        - in: query
          name: status
          schema:
            type: string
            enum:
              - published
              - unpublished
          description: |-
            Filter categories by publication status.

            * `published` - published
            * `unpublished` - unpublished
      tags:
        - Categories
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedCategoryList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 1
                        internal_id: CAT-001
                        translations:
                          en-GB:
                            name: Electronics
                            url: https://example.com/electronics-a1
                          es-ES:
                            name: Electrónica
                            url: https://example.es/electronica-a1
                  summary: Default fields
                AllFields(e.g.?fields=internalId,imageUrl,parentId,...):
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 1
                        internal_id: CAT-001
                        image_url: ''
                        parent_id: null
                        status: published
                        merchant_categories:
                          google:
                            id: '123'
                            path: Electronics > Audio > Headphones
                        translations:
                          en-GB:
                            url: https://example.com/electronics-a1
                            name: Electronics
                            description: All electronic items.
                            body_html: <p>All electronic items in one place.</p>
                            long_name: Electronics and Gadgets
                            meta_title: Electronics · Gadgets and Devices
                            meta_description: Explore our wide range of electronics and gadgets.
                            slug_base: electronics
                            slug: electronics-a1
                          es-ES:
                            url: https://example.es/electronica-a1
                            name: Electrónica
                            description: Todos los artículos electrónicos.
                            body_html: >-
                              <p>Todos los artículos electrónicos en un solo
                              lugar.</p>
                            long_name: Electrónica y Gadgets
                            meta_title: Electrónica · Gadgets y Dispositivos
                            meta_description: >-
                              Explora nuestra amplia gama de electrónica y
                              gadgets.
                            slug_base: electronica
                            slug: electronica-a1
                  summary: >-
                    All fields (e.g.
                    ?fields=internal_id,image_url,parent_id,...)
          description: OK
    post:
      operationId: Create Category
      description: Create a new category with the provided details.
      tags:
        - Categories
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Category'
            examples:
              POSTExample:
                value:
                  internal_id: CAT-002
                  image_url: https://example.com/images/new_category.jpg
                  parent_id: 23
                  status: published
                  merchant_categories:
                    google:
                      id: '123'
                  translations:
                    en-GB:
                      name: New Category
                      description: A newly created category
                      body_html: <p>New category description in HTML format.</p>
                      long_name: New Category - Ecologically Friendly Goods
                      meta_title: New Category · Fashion and Lifestyle
                      meta_description: >-
                        Discover New Category, the #1 choice for eco-friendly
                        products.
                    es-ES:
                      name: Nueva Categoría
                      description: Una categoría recién creada
                      body_html: >-
                        <p>Descripción de la nueva categoría en formato
                        HTML.</p>
                      long_name: Nueva Categoría - Productos Ecológicos
                      meta_title: Nueva Categoría · Moda y Estilo de Vida
                      meta_description: >-
                        Descubre Nueva Categoría, la elección número 1 para
                        productos ecológicos.
                summary: POST Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Category'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/Category'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
              examples:
                POST201Example:
                  value:
                    id: 2
                    internal_id: CAT-002
                    translations:
                      en-GB:
                        name: New Category
                        url: https://example.com/new-category
                      es-ES:
                        name: Nueva Categoría
                        url: https://example.es/nueva-categoria
                  summary: POST 201 Example
          description: Created
  /api/v1/categories/{id}/:
    get:
      operationId: Get Category Detail
      description: Retrieve detailed information about a specific category by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Categories
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
              examples:
                DefaultFields:
                  value:
                    id: 1
                    internal_id: CAT-001
                    translations:
                      en-GB:
                        url: https://example.com/electronics-a1
                        name: Electronics
                      es-ES:
                        url: https://example.es/electronica-a1
                        name: Electrónica
                  summary: Default fields
                AllFields(e.g.?fields=internalId,imageUrl,parentId,...):
                  value:
                    id: 1
                    internal_id: CAT-001
                    image_url: https://example.com/images/electronics.jpg
                    parent_id: null
                    status: published
                    merchant_categories:
                      google:
                        id: '123'
                        path: Electronics > Audio > Headphones
                    translations:
                      en-GB:
                        url: https://example.com/electronics-a1
                        name: Electronics
                        description: All electronic items.
                        body_html: <p>All electronic items in one place.</p>
                        long_name: Electronics and Gadgets
                        meta_title: Electronics · Gadgets and Devices
                        meta_description: Explore our wide range of electronics and gadgets.
                        slug_base: electronics
                        slug: electronics-a1
                      es-ES:
                        url: https://example.es/electronica-a1
                        name: Electrónica
                        description: Todos los artículos electrónicos.
                        body_html: >-
                          <p>Todos los artículos electrónicos en un solo
                          lugar.</p>
                        long_name: Electrónica y Gadgets
                        meta_title: Electrónica · Gadgets y Dispositivos
                        meta_description: Explora nuestra amplia gama de electrónica y gadgets.
                        slug_base: electronica
                        slug: electronica-a1
                  summary: >-
                    All fields (e.g.
                    ?fields=internal_id,image_url,parent_id,...)
          description: OK
    patch:
      operationId: Update Category
      description: Update an existing category's details.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Categories
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedCategory'
            examples:
              PATCHExample:
                value:
                  status: published
                  merchant_categories:
                    google:
                      id: '456'
                  translations:
                    en-GB:
                      name: Updated Electronics
                    es-ES:
                      name: Electrónica Actualizada
                summary: PATCH Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedCategory'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedCategory'
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
              examples:
                PATCH200Example:
                  value:
                    id: 1
                    internal_id: CAT-001
                    translations:
                      en-GB:
                        name: Updated Electronics
                        url: https://example.com/electronics
                      es-ES:
                        name: Electrónica Actualizada
                        url: https://example.es/electronica
                  summary: PATCH 200 Example
          description: OK
    delete:
      operationId: Delete Category
      description: Delete a specific category by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Categories
      security:
        - ApiKeyAuth: []
      responses:
        '204':
          description: No Content
  /api/v1/contacts/:
    get:
      operationId: List Contacts
      description: >-
        Retrieve a paginated list of contacts with optional filtering and
        ordering.<p>The <code>view</code> parameter is required to define the
        subset of contacts to return (e.g. <code>customers</code>,
        <code>subscribers</code>).</p>
      parameters:
        - in: query
          name: contact_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter contacts by a comma-separated list of contact IDs. Exact
            match on <code>contact.id</code>. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: created_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter contacts created from this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T00:00:00Z). If the time component is
            omitted, 00:00:00 is assumed.
        - in: query
          name: created_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter contacts created up to this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T23:59:59Z). If the time component is
            omitted, 23:59:59 is assumed.
        - in: query
          name: customer_type
          schema:
            type: string
          description: >-
            Merchant-defined customer (contact) classification (e.g.
            professional, individual, sector). Selected during registration and
            editable by the customer. Exact case-sensitive match on
            <code>contact.customer_type</code>.
        - in: query
          name: email
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter contacts by a comma-separated list of emails. Max 200 emails.
            Exact match case-insensitive on <code>contact.email</code>.
          explode: false
          style: form
        - in: query
          name: internal_ids
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter contacts by a comma-separated list of contact internal IDs.
            Exact match on <code>contact.internal_id</code>. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: is_active
          schema:
            type: boolean
          description: Filter customers (contacts) by active status.
        - in: query
          name: is_agreed_payment_enabled
          schema:
            type: boolean
          description: Filters customers (contacts) with agreed payment enabled.
        - in: query
          name: is_b2b
          schema:
            type: boolean
          description: Filters B2B customers (contacts).
        - in: query
          name: is_customer
          schema:
            type: boolean
          description: >-
            Filter contacts that have made a purchase or completed a
            registration.
        - in: query
          name: last_login_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter customers (contacts) whose last login was from this date/time
            (inclusive) in ISO 8601 format (e.g. 2023-01-01T00:00:00Z). If the
            time component is omitted, 00:00:00 is assumed.
        - in: query
          name: last_login_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter customers (contacts) whose last login was up to this
            date/time (inclusive) in ISO 8601 format (e.g.
            2023-01-01T23:59:59Z). If the time component is omitted, 23:59:59 is
            assumed.
        - in: query
          name: mkt_state
          schema:
            type: string
            enum:
              - not_subscribed
              - subscribed
              - unsubscribed
          description: |-
            Filter customers (subscribers) by subscription state.

            * `not_subscribed` - not_subscribed
            * `subscribed` - subscribed
            * `unsubscribed` - unsubscribed
        - in: query
          name: orders_count_min
          schema:
            type: number
          description: Filter customers (contacts) with a minimum number of created orders.
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: sort
          required: false
          in: query
          description: >-
            Which field to use when ordering the results. Use '_asc' or '_desc'
            suffix to specify ascending or descending order. Valid values are:
            `email_asc`, `email_desc`, `created_at_asc`, `created_at_desc`,
            `last_login_at_asc`, `last_login_at_desc`.<p>Default value:
            ``created_at_desc``
          schema:
            type: string
        - in: query
          name: view
          schema:
            type: string
            enum:
              - customers
              - subscribers
          description: >-
            Which subset of contacts to return. Must be <code>customers</code>
            or <code>subscribers</code>.
          required: true
      tags:
        - Contacts (customers and subscribers)
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedUserList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 1
                        internal_id: CONT-0001
                        is_active: true
                        email: contact@example.com
                        first_name: Jane
                        last_name: Doe
                        full_name: Jane Doe
                        phone: '600123456'
                        preferred_locale: en-GB
                  summary: Default fields
                AllFields(e.g.?fields=internalId,isActive,deletedAt,...):
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 1
                        internal_id: CONT-0001
                        is_active: true
                        is_customer: true
                        deleted_at: null
                        email: contact@example.com
                        first_name: Jane
                        last_name: Doe
                        full_name: Jane Doe
                        phone: '600123456'
                        preferred_locale: en-GB
                        created_at: '2026-04-28T15:21:12Z'
                        is_b2b: false
                        last_login_at: '2026-04-28T15:21:54Z'
                        birth_date: '1990-01-01'
                        gender: female
                        customer_type: regular
                        is_agreed_payment_enabled: false
                        orders_count: 5
                        mkt_state: not_subscribed
                        default_shipping_address:
                          first_name: Jane
                          last_name: Doe
                          phone: '600123456'
                          address: 123 Main St
                          postal_code: '12345'
                          country_code: US
                          region: California
                          city: Springfield
                          company: ''
                          tax_id: 00000000T
                          notes: Leave at the front desk.
                        default_billing_address:
                          first_name: Jane
                          last_name: Doe
                          phone: '600654321'
                          address: 456 Market Ave, Suite 100
                          postal_code: '54321'
                          country_code: US
                          region: California
                          city: Shelbyville
                          company: Example Corp
                          tax_id: B12345678
                          notes: ''
                  summary: >-
                    All fields (e.g.
                    ?fields=internal_id,is_active,deleted_at,...)
          description: OK
  /api/v1/contacts/{id}/:
    get:
      operationId: Get Contact Detail
      description: Retrieve detailed information about a specific contact by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Contacts (customers and subscribers)
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
              examples:
                DefaultFields:
                  value:
                    id: 1
                    internal_id: CONT-0001
                    is_active: true
                    email: contact@example.com
                    first_name: Jane
                    last_name: Doe
                    full_name: Jane Doe
                    phone: '600123456'
                    preferred_locale: en-GB
                  summary: Default fields
                AllFields(e.g.?fields=internalId,isActive,deletedAt,...):
                  value:
                    id: 1
                    internal_id: CONT-0001
                    is_active: true
                    is_customer: true
                    deleted_at: null
                    email: contact@example.com
                    first_name: Jane
                    last_name: Doe
                    full_name: Jane Doe
                    phone: '600123456'
                    preferred_locale: en-GB
                    created_at: '2026-04-28T15:21:12Z'
                    is_b2b: false
                    last_login_at: '2026-04-28T15:21:54Z'
                    birth_date: '1990-01-01'
                    gender: female
                    customer_type: regular
                    is_agreed_payment_enabled: false
                    orders_count: 5
                    mkt_state: not_subscribed
                    default_shipping_address:
                      first_name: Jane
                      last_name: Doe
                      phone: '600123456'
                      address: 123 Main St
                      postal_code: '12345'
                      country_code: US
                      region: California
                      city: Springfield
                      company: ''
                      tax_id: 00000000T
                      notes: Leave at the front desk.
                    default_billing_address:
                      first_name: Jane
                      last_name: Doe
                      phone: '600654321'
                      address: 456 Market Ave, Suite 100
                      postal_code: '54321'
                      country_code: US
                      region: California
                      city: Shelbyville
                      company: Example Corp
                      tax_id: B12345678
                      notes: ''
                  summary: >-
                    All fields (e.g.
                    ?fields=internal_id,is_active,deleted_at,...)
          description: OK
  /api/v1/jobs/{job_id}/logs/:
    get:
      operationId: List Log Entries
      description: >-
        Retrieve a paginated list of log entries for a specific job, with
        optional filtering and ordering.

        Use this endpoint to inspect processing information, warnings, and
        errors generated during job execution.


        <p>
          Jobs and their logs are retained for 5 days after creation when completed successfully, and for 30 days
          when failed or completed with errors. See <a href="#job-status-values">Job Status Values</a>
          for more information. After the retention period expires, they are automatically deleted.
        </p>


        <hr>

        <div id="severity-values" style="margin-top: 1rem;">
          <strong>Severity Values</strong>
          <p>
            Each log entry includes a severity value to indicate whether it is informational,
            a warning, or an error that affected processing.
          </p>
          <table>
            <thead>
              <tr>
                <th>Value</th>
                <th>Description</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td><code>INFO</code></td>
                <td>Informational messages about job processing progress.</td>
              </tr>
              <tr>
                <td><code>WARNING</code></td>
                <td>Indications of potential issues that did not prevent record processing.</td>
              </tr>
              <tr>
                <td><code>ERROR</code></td>
                <td>Indications of issues that caused record processing to fail.</td>
              </tr>
            </tbody>
          </table>
        </div>


        <hr>

        <div id="log-codes" style="margin-top: 1rem;">
          <strong>Log Codes</strong>
          <p>Each log entry includes a code to identify the specific type of issue detected during processing.</p>
          <table>
            <thead>
              <tr>
                <th>Code</th>
                <th>Description</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td><code>AMBIGUOUS_MATCH</code></td>
                <td>More than one record matches the provided identifier.</td>
              </tr>
              <tr>
                <td><code>INVALID_FIELD_VALUE</code></td>
                <td>A field has an invalid value. Affected field may be included in <code>affected_fields</code>.</td>
              </tr>
              <tr>
                <td><code>INVALID_IDENTIFIER</code></td>
                <td>The identifier used to match the resource is missing or invalid.</td>
              </tr>
              <tr>
                <td><code>MISSING_REQUIRED_FIELD</code></td>
                <td>A required field is missing.</td>
              </tr>
              <tr>
                <td><code>NOT_FOUND</code></td>
                <td>No existing record was found for the provided identifier.</td>
              </tr>
              <tr>
                <td><code>OTHER</code></td>
                <td>An unexpected error occurred during processing.</td>
              </tr>
            </tbody>
          </table>
        </div>
      parameters:
        - in: query
          name: code
          schema:
            type: string
            nullable: true
            enum:
              - AMBIGUOUS_MATCH
              - INVALID_FIELD_VALUE
              - INVALID_IDENTIFIER
              - MISSING_REQUIRED_FIELD
              - NOT_FOUND
              - OTHER
          description: >-
            Filter log entries by log code. <a href='#log-codes'>See values and
            descriptions.</a>


            * `AMBIGUOUS_MATCH` - Ambiguous match

            * `INVALID_FIELD_VALUE` - Invalid field value

            * `INVALID_IDENTIFIER` - Invalid identifier

            * `MISSING_REQUIRED_FIELD` - Missing required field

            * `NOT_FOUND` - Not found

            * `OTHER` - Other
        - in: query
          name: created_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter log entries created from this date/time (inclusive) in ISO
            8601 format (e.g. 2023-01-01T00:00:00Z). If the time component is
            omitted, 00:00:00 is assumed.
        - in: query
          name: created_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter log entries created up to this date/time (inclusive) in ISO
            8601 format (e.g. 2023-01-01T23:59:59Z). If the time component is
            omitted, 23:59:59 is assumed.
        - in: path
          name: job_id
          schema:
            type: string
            format: uuid
          required: true
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 100
            maximum: 500
        - in: query
          name: severity
          schema:
            type: array
            items:
              type: string
              enum:
                - ERROR
                - INFO
                - WARNING
          description: >-
            Filter log entries by severity. <a href='#severity-values'>See
            values and descriptions.</a>


            * `INFO` - Info

            * `WARNING` - Warning

            * `ERROR` - Error
          explode: false
          style: form
        - name: sort
          required: false
          in: query
          description: >-
            Which field to use when ordering the results. Use '_asc' or '_desc'
            suffix to specify ascending or descending order. Valid values are:
            `created_at_asc`, `created_at_desc`.<p>Default value:
            ``created_at_desc``
          schema:
            type: string
      tags:
        - Jobs
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedJobLogEntryList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - - id: 1
                            created_at: '2026-04-29T10:52:44Z'
                            severity: INFO
                            code: null
                            message: Creating chunks of 200 for payload of size 3
                            identifiers: null
                            affected_fields: null
                          - id: 2
                            created_at: '2026-04-29T10:52:44Z'
                            severity: ERROR
                            code: INVALID_FIELD_VALUE
                            message: >-
                              Variant must match the existing variant for simple
                              products.
                            identifiers:
                              product: '{''internal_id'': ''prod-123''}'
                              variant: '{''internal_id'': ''var-456''}'
                            affected_fields:
                              - variants.internal_id
                          - id: 3
                            created_at: '2026-04-29T10:52:44Z'
                            severity: INFO
                            code: null
                            message: >-
                              Bulk upsert job completed: 3 total products, 3
                              products processed, 1 products failed.
                            identifiers: null
                            affected_fields: null
                  summary: Default fields
          description: OK
        '404':
          description: Not Found
  /api/v1/jobs/{id}/:
    get:
      operationId: Get Job Detail
      description: >-
        Retrieve detailed information about a specific job by its ID.<hr><div
        id='job-status-values' style='margin-top: 1rem;'><strong>Status
        Values</strong><table><thead><p>The job status indicates the current
        processing state and whether the job finished successfully, partially,
        or
        failed.</p><tr><th>Value</th><th>Description</th></tr></thead><tbody><tr><td><code>pending</code></td><td>Job
        is waiting to be
        processed.</td></tr><tr><td><code>running</code></td><td>Job is
        currently being
        processed.</td></tr><tr><td><code>done</code></td><td>Job has been
        completed and all records were processed
        successfully.</td></tr><tr><td><code>done_with_errors</code></td><td>Job
        has been completed but some records could not be processed
        successfully.</td></tr><tr><td><code>failed</code></td><td>Job has
        failed and no records were processed
        successfully.</td></tr></tbody></table></div>
      parameters:
        - in: path
          name: id
          schema:
            type: string
            format: uuid
          required: true
      tags:
        - Jobs
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Job'
              examples:
                Job:
                  value:
                    id: 0d1e1658-98c7-470b-a515-bd523cff01f7
                    type: bulk_update_variants
                    status: completed_with_errors
                    created_at: '2026-05-13T18:09:09Z'
                    started_at: '2026-05-13T18:18:43Z'
                    finished_at: '2026-05-13T18:19:52Z'
                    summary:
                      total_records: 2272
                      processed_records: 2272
                      succeeded_records: 2218
                      failed_records: 54
                      log_info_count: 11
                      log_warning_count: 2
                      log_error_count: 63
          description: OK
        '404':
          description: Not Found
  /api/v1/orders/:
    get:
      operationId: List Orders
      description: >-
        Retrieve a paginated list of orders with optional filtering and
        ordering.
      parameters:
        - in: query
          name: created_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter orders created from this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T00:00:00Z). If the time component is
            omitted, 00:00:00 is assumed.
        - in: query
          name: created_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter orders created up to this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T23:59:59Z). If the time component is
            omitted, 23:59:59 is assumed.
        - in: query
          name: delivery_method
          schema:
            type: string
            title: Shipping method
            enum:
              - shipment
              - store_pick_up
          description: |-
            Filter orders by delivery method.

            * `shipment` - Shipment
            * `store_pick_up` - Store pick-up
        - in: query
          name: fulfilled_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter orders fulfilled from this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T00:00:00Z). If the time component is
            omitted, 00:00:00 is assumed.
        - in: query
          name: fulfilled_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter orders fulfilled up to this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T23:59:59Z). If the time component is
            omitted, 23:59:59 is assumed.
        - in: query
          name: fulfillment_status
          schema:
            type: string
            title: Delivery Status
            enum:
              - fulfilled
              - partially_fulfilled
              - unfulfilled
          description: |-
            Filter orders by fulfillment status.

            * `unfulfilled` - unfulfilled
            * `partially_fulfilled` - partially_fulfilled
            * `fulfilled` - fulfilled
        - in: query
          name: is_canceled
          schema:
            type: boolean
          description: >-
            Filter orders by cancellation status. Set to true to get canceled
            orders, false to get non-canceled orders.
        - in: query
          name: order_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter orders by a comma-separated list of order IDs. Exact match on
            <code>order.id</code>. Max 200 IDs.
          explode: false
          style: form
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - in: query
          name: paid_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter orders paid from this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T00:00:00Z). If the time component is
            omitted, 00:00:00 is assumed.
        - in: query
          name: paid_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter orders paid up to this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T23:59:59Z). If the time component is
            omitted, 23:59:59 is assumed.
        - in: query
          name: payment_status
          schema:
            type: string
            enum:
              - paid
              - unpaid
          description: |-
            Filter orders by payment status.

            * `paid` - Paid
            * `unpaid` - Unpaid
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: sort
          required: false
          in: query
          description: >-
            Which field to use when ordering the results. Use '_asc' or '_desc'
            suffix to specify ascending or descending order. Valid values are:
            `created_at_asc`, `created_at_desc`, `id_asc`, `id_desc`,
            `updated_at_asc`, `updated_at_desc`, `paid_at_asc`, `paid_at_desc`,
            `fulfilled_at_asc`, `fulfilled_at_desc`.<p>Default value:
            ``created_at_desc``
          schema:
            type: string
        - in: query
          name: warehouse_release_status
          schema:
            type: string
            title: State in the warehouse
            enum:
              - not_released
              - partially_released
              - released
          description: |-
            Filter orders by warehouse release status.

            * `not_released` - not_released
            * `partially_released` - partially_released
            * `released` - released
      tags:
        - Orders
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedOrderList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 1267
                        payment_status: paid
                        warehouse_release_status: released
                        fulfillment_status: fulfilled
                        created_at: '2026-03-18T10:15:22Z'
                        paid_at: '2026-03-18T10:20:00Z'
                        fulfilled_at: '2026-03-19T15:00:00Z'
                        canceled_at: null
                        delivery_method: shipment
                        locale: es-ES
                        payment_method: card
                        payment_gateway: stripe
                        total:
                          gross:
                            amount: '120.00'
                            currency: EUR
                          net:
                            amount: '99.17'
                            currency: EUR
                          tax:
                            amount: '20.83'
                            currency: EUR
                        shipping:
                          gross:
                            amount: '5.00'
                            currency: EUR
                          net:
                            amount: '4.13'
                            currency: EUR
                          tax:
                            amount: '0.87'
                            currency: EUR
                        fees:
                          gross:
                            amount: '2.00'
                            currency: EUR
                          net:
                            amount: '1.65'
                            currency: EUR
                          tax:
                            amount: '0.35'
                            currency: EUR
                        email: john.smith@example.com
                  summary: Default fields
                AllFields(e.g.?fields=deliveryMethod,locale,paymentMethod...):
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 1267
                        payment_status: paid
                        warehouse_release_status: released
                        fulfillment_status: fulfilled
                        created_at: '2026-03-18T10:15:22Z'
                        paid_at: '2026-03-18T10:20:00Z'
                        fulfilled_at: '2026-03-19T15:00:00Z'
                        canceled_at: null
                        cancel_reason: null
                        estimated_delivery_at: '2026-03-20'
                        initial_estimated_delivery_at: '2026-03-19'
                        delivery_method: shipment
                        locale: es-ES
                        payment_method: card
                        payment_gateway: stripe
                        total:
                          gross:
                            amount: '120.00'
                            currency: EUR
                          net:
                            amount: '99.17'
                            currency: EUR
                          tax:
                            amount: '20.83'
                            currency: EUR
                        shipping:
                          gross:
                            amount: '5.00'
                            currency: EUR
                          net:
                            amount: '4.13'
                            currency: EUR
                          tax:
                            amount: '0.87'
                            currency: EUR
                        fees:
                          gross:
                            amount: '2.00'
                            currency: EUR
                          net:
                            amount: '1.65'
                            currency: EUR
                          tax:
                            amount: '0.35'
                            currency: EUR
                        line_items:
                          - id: 101
                            product_id: 2001
                            variant_id: 3001
                            sku: SKU-12345
                            ean: '8431234567890'
                            display_name: Wireless Mouse
                            tax_rate: '0.21'
                            quantity: 2
                            unit_price:
                              list_price:
                                gross:
                                  amount: '30.00000'
                                  currency: EUR
                              final_price:
                                gross:
                                  amount: '28.00000'
                                  currency: EUR
                                net:
                                  amount: '23.14049'
                                  currency: EUR
                            discounts_applied:
                              - type: voucher
                                amount:
                                  amount: '4.00'
                                  currency: EUR
                                description: Spring Sale Voucher
                            additional_services:
                              - display_name: Gift Wrapping
                                internal_id: GW-001
                                quantity: 2
                                unit_price:
                                  gross:
                                    amount: '2.00000'
                                    currency: EUR
                                  net:
                                    amount: '1.65289'
                                    currency: EUR
                                tax_rate: '0.21'
                            total:
                              gross:
                                amount: '56.00000'
                                currency: EUR
                              net:
                                amount: '46.28099'
                                currency: EUR
                              tax:
                                amount: '9.71901'
                                currency: EUR
                        email: john.smith@example.com
                        customer:
                          id: 501
                          internal_id: CUST-789
                          is_active: true
                          email: john.smith@example.com
                          first_name: John
                          last_name: Smith
                          full_name: John Smith
                          phone: '600123456'
                          preferred_locale: es-ES
                        billing_address:
                          first_name: John
                          last_name: Smith
                          phone: '600123456'
                          company: ''
                          street_address: Calle Mayor 1
                          postal_code: '28013'
                          country_code: ES
                          region: Madrid
                          city: Madrid
                          tax_id: 12345678A
                        shipping_address:
                          first_name: John
                          last_name: Smith
                          phone: '600123456'
                          company: ''
                          street_address: Calle Mayor 1
                          postal_code: '28013'
                          country_code: ES
                          region: Madrid
                          city: Madrid
                          tax_id: ''
                        is_intra_community_vat_requested: false
                        is_intra_community_vat_validated: false
                        customer_note: Please deliver after 5pm.
                        is_b2b: false
                        is_tax_exempt: false
                        source:
                          - organic
                          - automarketing
                  summary: >-
                    All fields (e.g.
                    ?fields=delivery_method,locale,payment_method...)
          description: OK
  /api/v1/orders/{id}/:
    get:
      operationId: Get Order Detail
      description: Retrieve detailed information about a specific order by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Orders
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
              examples:
                DefaultFields:
                  value:
                    id: 1267
                    payment_status: paid
                    warehouse_release_status: released
                    fulfillment_status: fulfilled
                    created_at: '2026-03-18T10:15:22Z'
                    paid_at: '2026-03-18T10:20:00Z'
                    fulfilled_at: '2026-03-19T15:00:00Z'
                    canceled_at: null
                    delivery_method: shipment
                    locale: es-ES
                    payment_method: card
                    payment_gateway: stripe
                    total:
                      gross:
                        amount: '120.00'
                        currency: EUR
                      net:
                        amount: '99.17'
                        currency: EUR
                      tax:
                        amount: '20.83'
                        currency: EUR
                    shipping:
                      gross:
                        amount: '5.00'
                        currency: EUR
                      net:
                        amount: '4.13'
                        currency: EUR
                      tax:
                        amount: '0.87'
                        currency: EUR
                    fees:
                      gross:
                        amount: '2.00'
                        currency: EUR
                      net:
                        amount: '1.65'
                        currency: EUR
                      tax:
                        amount: '0.35'
                        currency: EUR
                    email: john.smith@example.com
                  summary: Default fields
                AllFields(e.g.?fields=deliveryMethod,locale,paymentMethod...):
                  value:
                    id: 1267
                    payment_status: paid
                    warehouse_release_status: released
                    fulfillment_status: fulfilled
                    created_at: '2026-03-18T10:15:22Z'
                    paid_at: '2026-03-18T10:20:00Z'
                    fulfilled_at: '2026-03-19T15:00:00Z'
                    canceled_at: null
                    cancel_reason: null
                    estimated_delivery_at: '2026-03-20'
                    initial_estimated_delivery_at: '2026-03-19'
                    delivery_method: shipment
                    locale: es-ES
                    payment_method: card
                    payment_gateway: stripe
                    total:
                      gross:
                        amount: '120.00'
                        currency: EUR
                      net:
                        amount: '99.17'
                        currency: EUR
                      tax:
                        amount: '20.83'
                        currency: EUR
                    shipping:
                      gross:
                        amount: '5.00'
                        currency: EUR
                      net:
                        amount: '4.13'
                        currency: EUR
                      tax:
                        amount: '0.87'
                        currency: EUR
                    fees:
                      gross:
                        amount: '2.00'
                        currency: EUR
                      net:
                        amount: '1.65'
                        currency: EUR
                      tax:
                        amount: '0.35'
                        currency: EUR
                    line_items:
                      - id: 101
                        product_id: 2001
                        variant_id: 3001
                        sku: SKU-12345
                        ean: '8431234567890'
                        display_name: Wireless Mouse
                        tax_rate: '0.21'
                        quantity: 2
                        unit_price:
                          list_price:
                            gross:
                              amount: '30.00000'
                              currency: EUR
                          final_price:
                            gross:
                              amount: '28.00000'
                              currency: EUR
                            net:
                              amount: '23.14049'
                              currency: EUR
                        discounts_applied:
                          - type: voucher
                            amount:
                              amount: '4.00'
                              currency: EUR
                            description: Spring Sale Voucher
                        additional_services:
                          - display_name: Gift Wrapping
                            internal_id: GW-001
                            quantity: 2
                            unit_price:
                              gross:
                                amount: '2.00000'
                                currency: EUR
                              net:
                                amount: '1.65289'
                                currency: EUR
                            tax_rate: '0.21'
                        total:
                          gross:
                            amount: '56.00000'
                            currency: EUR
                          net:
                            amount: '46.28099'
                            currency: EUR
                          tax:
                            amount: '9.71901'
                            currency: EUR
                    email: john.smith@example.com
                    customer:
                      id: 501
                      internal_id: CUST-789
                      is_active: true
                      email: john.smith@example.com
                      first_name: John
                      last_name: Smith
                      full_name: John Smith
                      phone: '600123456'
                      preferred_locale: es-ES
                    billing_address:
                      first_name: John
                      last_name: Smith
                      phone: '600123456'
                      company: ''
                      street_address: Calle Mayor 1
                      postal_code: '28013'
                      country_code: ES
                      region: Madrid
                      city: Madrid
                      tax_id: 12345678A
                    shipping_address:
                      first_name: John
                      last_name: Smith
                      phone: '600123456'
                      company: ''
                      street_address: Calle Mayor 1
                      postal_code: '28013'
                      country_code: ES
                      region: Madrid
                      city: Madrid
                      tax_id: ''
                    is_intra_community_vat_requested: false
                    is_intra_community_vat_validated: false
                    customer_note: Please deliver after 5pm.
                    is_b2b: false
                    is_tax_exempt: false
                    source:
                      - organic
                      - automarketing
                  summary: >-
                    All fields (e.g.
                    ?fields=delivery_method,locale,payment_method...)
          description: OK
        '404':
          description: Not Found
  /api/v1/price-lists/:
    get:
      operationId: List Price Lists
      description: Retrieve a paginated list of price lists with optional filtering.
      parameters:
        - in: query
          name: internal_ids
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter price lists by a comma-separated list of price list internal
            IDs. Exact match on <code>price_list.internal_id</code>. Max 200
            IDs.
          explode: false
          style: form
        - in: query
          name: is_active
          schema:
            type: boolean
          description: Filter price lists by active status.
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
        - in: query
          name: price_list_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter price lists by a comma-separated list of price list IDs.
            Exact match on <code>price_list.id</code>. Max 200 IDs.
          explode: false
          style: form
      tags:
        - Price Lists
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedPriceListList'
              examples:
                GETPriceListsExample:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 3
                        internal_id: distributor-ESP
                        is_active: true
                        minimum_order_amount: null
                        customers_count: 74
                        variant_prices_count: 1942
                        global_discount: '10.00'
                        category_discounts:
                          - categories:
                              - id: 1
                                internal_id: CAT-001
                                translations:
                                  en-GB:
                                    name: Electronics
                                    url: https://example.com/electronics-a1
                            discount: '5.00'
                        brand_discounts:
                          - brands:
                              - id: 1
                                name: Sample Brand
                                internal_id: BRAND-001
                                translations:
                                  en-GB:
                                    url: https://example.com/brand/example-brand
                            discount: '15.00'
                  summary: GET Price Lists example
          description: OK
    post:
      operationId: Create Price List
      description: >-
        Creates a new price list.<br>This endpoint only creates the price list
        configuration. Fixed prices by product must be managed separately.
      tags:
        - Price Lists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PriceList'
            examples:
              Create/updatePriceListExample:
                value:
                  internal_id: distributor-ESP
                  is_active: true
                  minimum_order_amount:
                    amount: '100.00'
                    currency: EUR
                  global_discount: '10.00'
                  category_discounts:
                    - categories:
                        - 23
                      discount: '5.00'
                  brand_discounts:
                    - brands:
                        - 1
                        - 3
                      discount: '15.00'
                summary: Create/update Price List example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PriceList'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PriceList'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PriceList'
              examples:
                ResponseExampleForCreate/updatePriceList:
                  value:
                    id: 3
                    internal_id: distributor-ESP
                    is_active: true
                    minimum_order_amount:
                      amount: '100.00'
                      currency: EUR
                    customers_count: 74
                    variant_prices_count: 1942
                    global_discount: '10.00'
                    category_discounts:
                      - categories:
                          - id: 23
                            internal_id: CAT-023
                            translations:
                              en-GB:
                                name: Sample Category
                                url: https://example.com/category/sample-category
                        discount: '5.00'
                    brand_discounts:
                      - brands:
                          - id: 1
                            name: Sample Brand
                            internal_id: BRAND-001
                            translations:
                              en-GB:
                                url: https://example.com/brand/example-brand
                          - id: 3
                            name: Another Brand
                            internal_id: BRAND-003
                            translations:
                              en-GB:
                                url: https://example.com/brand/another-brand
                        discount: '15.00'
                  summary: Response example for create/update Price List
          description: Created
        '400':
          description: Bad Request
  /api/v1/price-lists/{id}/:
    get:
      operationId: Get Price List Detail
      description: >-
        Returns a single price list.<br>This endpoint does not return fixed
        prices by variant.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Price Lists
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PriceList'
              examples:
                GETPriceListsExample:
                  value:
                    id: 3
                    internal_id: distributor-ESP
                    is_active: true
                    minimum_order_amount: null
                    customers_count: 74
                    variant_prices_count: 1942
                    global_discount: '10.00'
                    category_discounts:
                      - categories:
                          - id: 1
                            internal_id: CAT-001
                            translations:
                              en-GB:
                                name: Electronics
                                url: https://example.com/electronics-a1
                        discount: '5.00'
                    brand_discounts:
                      - brands:
                          - id: 1
                            name: Sample Brand
                            internal_id: BRAND-001
                            translations:
                              en-GB:
                                url: https://example.com/brand/example-brand
                        discount: '15.00'
                  summary: GET Price Lists example
          description: OK
        '404':
          description: Not Found
    patch:
      operationId: Update Price List
      description: >-
        Updates an existing price list.<br>This endpoint only updates the price
        list configuration. It does not create, update or delete fixed prices by
        product.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Price Lists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedPriceList'
            examples:
              Create/updatePriceListExample:
                value:
                  internal_id: distributor-ESP
                  is_active: true
                  minimum_order_amount:
                    amount: '100.00'
                    currency: EUR
                  global_discount: '10.00'
                  category_discounts:
                    - categories:
                        - 23
                      discount: '5.00'
                  brand_discounts:
                    - brands:
                        - 1
                        - 3
                      discount: '15.00'
                summary: Create/update Price List example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedPriceList'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedPriceList'
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PriceList'
              examples:
                ResponseExampleForCreate/updatePriceList:
                  value:
                    id: 3
                    internal_id: distributor-ESP
                    is_active: true
                    minimum_order_amount:
                      amount: '100.00'
                      currency: EUR
                    customers_count: 74
                    variant_prices_count: 1942
                    global_discount: '10.00'
                    category_discounts:
                      - categories:
                          - id: 23
                            internal_id: CAT-023
                            translations:
                              en-GB:
                                name: Sample Category
                                url: https://example.com/category/sample-category
                        discount: '5.00'
                    brand_discounts:
                      - brands:
                          - id: 1
                            name: Sample Brand
                            internal_id: BRAND-001
                            translations:
                              en-GB:
                                url: https://example.com/brand/example-brand
                          - id: 3
                            name: Another Brand
                            internal_id: BRAND-003
                            translations:
                              en-GB:
                                url: https://example.com/brand/another-brand
                        discount: '15.00'
                  summary: Response example for create/update Price List
          description: OK
        '400':
          description: Bad Request
        '404':
          description: Not Found
    delete:
      operationId: Delete Price List
      description: >-
        Deletes a price list and all associated data, including fixed prices by
        product.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Price Lists
      security:
        - ApiKeyAuth: []
      responses:
        '204':
          description: No Content
        '404':
          description: Not Found
  /api/v1/price-lists/{id}/prices/:
    get:
      operationId: List Variant Prices
      description: >-
        <p>Retrieve a paginated list of variant prices configured for a specific
        price list, with optional filtering and ordering. Use this endpoint to
        inspect fixed prices, minimum quantities and quantity multiples applied
        by the price list to specific variants.</p><p>This endpoint returns
        customer-specific variant prices configured in the selected price list.
        It does not return the standard catalog prices configured for
        variants.</p>
      parameters:
        - in: query
          name: ean
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter price list variant prices by a comma-separated list of
            EAN/UPC codes. Max 200 EANs.
          explode: false
          style: form
        - in: path
          name: id
          schema:
            type: integer
          required: true
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 100
            maximum: 500
        - in: query
          name: product_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter price list variant prices by a comma-separated list of
            product IDs. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: product_internal_ids
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter price list variant prices by a comma-separated list of
            product internal IDs. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: sku
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter price list variant prices by a comma-separated list of SKUs.
            Max 200 SKUs.
          explode: false
          style: form
        - name: sort
          required: false
          in: query
          description: >-
            Which field to use when ordering the results. Use '_asc' or '_desc'
            suffix to specify ascending or descending order. Valid values are:
            `variant_id_asc`, `variant_id_desc`, `variant_internal_id_asc`,
            `variant_internal_id_desc`, `product_id_asc`, `product_id_desc`,
            `product_internal_id_asc`, `product_internal_id_desc`, `ean_asc`,
            `ean_desc`, `sku_asc`, `sku_desc`, `supplier_id_asc`,
            `supplier_id_desc`, `supplier_internal_id_asc`,
            `supplier_internal_id_desc`.<p>Default value: ``variant_id_asc``
          schema:
            type: string
        - in: query
          name: supplier_id
          schema:
            type: integer
          description: Filter price list variant prices by variant's product supplier ID.
        - in: query
          name: supplier_internal_id
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter price list variant prices by variant's product supplier
            internal ID.
          explode: false
          style: form
        - in: query
          name: variant_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter price list variant prices by a comma-separated list of
            variant IDs. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: variant_internal_ids
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter price list variant prices by a comma-separated list of
            variant internal IDs. Max 200 IDs.
          explode: false
          style: form
      tags:
        - Price Lists
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedPriceListVariantPriceList'
              examples:
                GETListVariantPricesExample:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - variant_id: 201
                          variant_internal_id: PIM-V-987
                          product_id: 1204
                          product_internal_id: PROD-001
                          ean: '8431234567890'
                          sku: sneaker-41
                          supplier_id: 15
                          supplier_internal_id: SUP-001
                          display_name: Zapatilla Deportiva Talla 41
                          price:
                            amount: '54.75'
                            currency: EUR
                          min_quantity: 5
                          quantity_factor: 5
                  summary: GET List Variant Prices Example
          description: OK
        '404':
          description: Not Found
    delete:
      operationId: Delete Variant Prices
      description: >-
        <p>Deletes all variant prices configured in the price list.</p><p>This
        operation removes every fixed price by variant from the price list,
        including any variant-level minimum quantity and quantity multiple
        values.</p><p>This endpoint does not delete the price list itself, nor
        does it modify price list configuration fields such as global discounts,
        category discounts, brand discounts, active state or minimum order
        amount.</p><p>After deletion, variants affected by this price list no
        longer have fixed prices from this price list. They may still be
        affected by other price list rules, such as brand, category or global
        discounts.</p>
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Price Lists
      security:
        - ApiKeyAuth: []
      responses:
        '204':
          description: No Content
        '404':
          description: Not Found
  /api/v1/price-lists/{id}/prices/bulk-update/:
    post:
      operationId: Bulk Update Variant Prices
      description: >-
        <p>Creates an asynchronous bulk update job to manage variant prices
        within a price list.</p><p>Use this endpoint to process variant prices
        in bulk. The operation to perform is defined by
        <code>options.mode</code>:</p><ul><li><code>upsert</code>: creates new
        variant prices and updates existing ones. Existing prices that are not
        included in the payload remain unchanged.</li><li><code>delete</code>:
        removes the provided variant prices from the price
        list.</li></ul><p>Variants can be matched using one of the supported
        identifiers defined by <code>options.match_by</code>:
        <code>variant_id</code>, <code>variant_internal_id</code>,
        <code>ean</code> or <code>sku_supplier</code>.</p><p>This endpoint only
        manages customer-specific variant prices configured within a price list.
        Price list configuration fields such as global discounts, category
        discounts, brand discounts, active state and minimum order amount are
        managed through the price list CRUD endpoints.</p><h3>Asynchronous
        processing</h3><p>This endpoint does not process the update within the
        request cycle. Before creating the job, OpenTiendas performs an initial
        validation of the request, including JSON format, payload structure,
        payload size and required top-level fields.</p><p>If the request fails
        this initial validation, no job is created and an error response is
        returned. The response may be <code>413 Request Entity Too Large</code>
        if the payload exceeds the maximum allowed size, or <code>400 Bad
        Request</code> for other validation errors.</p><p>If the request passes
        this initial validation, the endpoint creates and queues a job, then
        returns <code>202 Accepted</code> with the corresponding
        <code>job_id</code>. This confirms that the request has been accepted
        for asynchronous processing, but does not mean that all reference prices
        have already been updated successfully.</p><p>Record-level validations
        and update operations are performed later, during job
        processing.</p><h3>Job result</h3><p>The progress and result of the
        operation can be reviewed using the returned
        <code>job_id</code>.</p><p>The job log includes processing information,
        validation errors, affected variant identifiers when available, and a
        final summary with the total processed and failed
        records.</p><h3>Limits</h3><p>Maximum request payload: 10 MB. Requests
        exceeding this limit are rejected.</p>
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Price Lists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SellablePricingPlanBulkUpdate'
            examples:
              Upsert:
                value:
                  prices:
                    - variant_internal_id: VAR-001
                      price:
                        amount: '4.75'
                        currency_code: EUR
                      minimum_quantity: 5
                      quantity_multiple: 5
                  options:
                    match_by: variant_internal_id
                    mode: upsert
              Delete:
                value:
                  prices:
                    - variant_internal_id: VAR-001
                    - variant_internal_id: VAR-002
                  options:
                    match_by: variant_internal_id
                    mode: delete
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SellablePricingPlanBulkUpdate'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SellablePricingPlanBulkUpdate'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkJobCreationResponse'
              examples:
                POST202Example:
                  value:
                    - job_id: f7c9a6d1-3b2e-4f85-9a71-6d4c8e2b5f03
                      status: pending
                  summary: POST 202 Example
          description: Accepted. The bulk update job has been created.
        '400':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/SellablePricingPlanBulkUpdateErrorResponse
              examples:
                POST400Example-Missing'prices':
                  value:
                    detail: The 'prices' field must be an array.
                  summary: POST 400 Example - Missing 'prices'
          description: >-
            Bad Request. The request payload is invalid or missing required
            fields.
        '413':
          description: >-
            Payload Too Large. The request payload exceeds the maximum allowed
            size.
  /api/v1/products/:
    get:
      operationId: List Products
      description: >-
        Retrieve a paginated list of products with optional filtering and
        ordering.
      parameters:
        - in: query
          name: brand_ids
          schema:
            type: array
            items:
              type: number
          description: >-
            Filter products whose <code>brand_id</code> is in the
            comma-separated list of brand IDs. Max 50 IDs.
          explode: false
          style: form
        - in: query
          name: category_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter products by a comma-separated list of category IDs. Max 50
            IDs.<p>Descendant categories are included. For example, filtering by
            the <i>Clothes</i> category returns all products assigned to that
            category and any of its subcategories (e.g. <i>Trousers</i> and
            <i>Shirts</i>).</p>
          explode: false
          style: form
        - in: query
          name: created_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter products created from the given date and time. Uses
            <code>product.created_at</code>.
        - in: query
          name: created_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter products created up to the given date and time. Uses
            <code>product.created_at</code>.
        - in: query
          name: ean
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter products by a comma-separated list of EAN/UPC codes. Max 200
            EANs.<p>Exact match on <code>variant.ean</code>. Returns the parent
            product. When <code>ean</code> is present, <code>variants</code> is
            trimmed to only the variant(s) that match the <code>ean</code>
            filter.</p>
          explode: false
          style: form
        - in: query
          name: internal_ids
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter products by a comma-separated list of product internal IDs.
            Exact match on <code>product.internal_id</code>. Max 200 IDs.
          explode: false
          style: form
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
        - in: query
          name: product_ids
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter products by a comma-separated list of product IDs. Exact
            match on <code>product.id</code>. Max 200 IDs.
          explode: false
          style: form
        - in: query
          name: product_structure
          schema:
            type: string
            enum:
              - simple
              - with-variants
          description: |-
            Filter products by product structure.

            * `simple` - simple
            * `with-variants` - with-variants
        - in: query
          name: sku
          schema:
            type: array
            items:
              type: string
          description: >-
            Filter products by a comma-separated list of SKUs. Max 200
            SKUs.<p>Exact match case-insensitive on <code>variant.sku</code>
            (does not search product fields). Returns the parent product. When
            <code>sku</code> is present, <code>variants</code> is trimmed to
            only the variant(s) that match the <code>sku</code> filter.</p>
          explode: false
          style: form
        - in: query
          name: slug
          schema:
            type: string
          description: Filter products by a comma-separated list of slugs. Max 200 slugs.
        - name: sort
          required: false
          in: query
          description: >-
            Which field to use when ordering the results. Use '_asc' or '_desc'
            suffix to specify ascending or descending order. Valid values are:
            `name_asc`, `name_desc`.<p>Default value: ``name_asc``
          schema:
            type: string
        - in: query
          name: status
          schema:
            type: string
            enum:
              - published
              - unpublished
          description: |-
            Filter products by publication status.

            * `published` - published
            * `unpublished` - unpublished
        - in: query
          name: supplier_ids
          schema:
            type: array
            items:
              type: number
          description: >-
            Filter products that have at least one supplier in the
            comma-separated list of supplier IDs. Max 50 IDs.
          explode: false
          style: form
        - in: query
          name: updated_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter products updated on or after the given date and time. Uses
            <code>product.updated_at</code>.<p>Useful for incremental
            synchronization and change tracking.</p><p>This filter is intended
            to help detect products that may need to be re-synchronized, but
            should not be treated as a complete change history.</p>
        - in: query
          name: updated_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter products updated on or before the given date and time. Uses
            <code>product.updated_at</code>.<p>Useful for incremental
            synchronization and change tracking.</p><p>This filter is intended
            to help detect products that may need to be re-synchronized, but
            should not be treated as a complete change history.</p>
      tags:
        - Products
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedProductList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - id: 55
                          internal_id: mountain-backpack
                          product_structure: simple
                          status: unpublished
                          product_kind: physical
                          model_code: mtbpk_2026
                          tax_category: reduced
                          images:
                            - id: 201
                              fullsize: >-
                                https://media.example.com/product/mountain-backpack-1.jpg?width=1200
                              position: 0
                            - id: 202
                              fullsize: >-
                                https://media.example.com/product/mountain-backpack-2.jpg?width=1200
                              position: 1
                          variants_count: 1
                          translations:
                            en-GB:
                              url: https://shop.example.com/mountain-backpack-b37/
                              name: Mountain Backpack
                              slug_base: mountain-backpack
                              slug: mountain-backpack-b37
                            es-ES:
                              url: https://tienda.ejemplo.com/mochila-montana-b37/
                              name: Mochila de Montaña
                              slug_base: mochila-montana
                              slug: mochila-montana-b37
                        - id: 56
                          internal_id: city-bike
                          product_structure: simple
                          status: published
                          product_kind: physical
                          model_code: ctybk_2026
                          tax_category: standard
                          images:
                            - id: 301
                              fullsize: >-
                                https://media.example.com/product/city-bike-1.jpg?width=1200
                              position: 0
                          variants_count: 1
                          translations:
                            en-GB:
                              url: https://shop.example.com/city-bike-b38/
                              name: City Bike
                              slug_base: city-bike
                              slug: city-bike-b38
                            es-ES:
                              url: https://tienda.ejemplo.com/bicicleta-urbana-b38/
                              name: Bicicleta Urbana
                              slug_base: bicicleta-urbana
                              slug: bicicleta-urbana-b38
                  summary: Default fields
                AllFields(e.g.?fields=productStructure,status,...&includes=variants,...):
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - id: 55
                          internal_id: mountain-backpack
                          created_at: '2026-01-15T10:00:00Z'
                          updated_at: '2026-05-01T12:00:00Z'
                          product_structure: simple
                          status: unpublished
                          product_kind: physical
                          stock_management: default
                          effective_stock_management: deny-without-own-or-supplier-stock
                          online_availability: shipping-only
                          model_code: mtbpk_2026
                          tax_category: reduced
                          supplier:
                            id: 7
                            name: Outdoor Gear Inc.
                          brand:
                            id: 5
                            name: URBANO
                            internal_id: urbn
                            translations:
                              en-GB:
                                url: https://shop.example.com/brands/urbano/
                              es-ES:
                                url: https://tienda.ejemplo.com/marcas/urbano/
                          categories:
                            - id: 21
                              internal_id: backpacks
                              translations:
                                en-GB:
                                  url: https://shop.example.com/backpacks/
                                  name: Backpacks
                                es-ES:
                                  url: https://tienda.ejemplo.com/mochilas/
                                  name: Mochilas
                          images:
                            - id: 201
                              fullsize: >-
                                https://media.example.com/product/mountain-backpack-1.jpg?width=1200
                              position: 0
                            - id: 202
                              fullsize: >-
                                https://media.example.com/product/mountain-backpack-2.jpg?width=1200
                              position: 1
                          variants_count: 1
                          variants:
                            - id: 301
                              internal_id: null
                              sku: mtbpk-2026
                              ean: '9876543210123'
                              status: unpublished
                              available_stock: 150
                              prices:
                                market_en:
                                  list_price:
                                    amount: '230.00'
                                    currency: EUR
                                  offer_price:
                                    amount: '179.99'
                                    currency: EUR
                                  flash_offer: null
                                  selling_price:
                                    amount: '179.99'
                                    currency: EUR
                                market_es:
                                  list_price:
                                    amount: '230.00'
                                    currency: EUR
                                  offer_price:
                                    amount: '149.99'
                                    currency: EUR
                                  flash_offer: null
                                  selling_price:
                                    amount: '149.99'
                                    currency: EUR
                              translations:
                                en-GB:
                                  name: null
                                es-ES:
                                  name: null
                          translations:
                            en-GB:
                              url: https://shop.example.com/mountain-backpack-b37/
                              name: Mountain Backpack
                              description: The perfect backpack for mountain adventures.
                              body_html: >-
                                <p>The perfect backpack for <b>mountain
                                adventures</b>. Spacious, durable, and
                                comfortable.</p>
                              long_name: Mountain Backpack - Model 2026
                              meta_title: Buy Mountain Backpack Online
                              meta_description: >-
                                Get the Mountain Backpack, the perfect backpack
                                for mountain adventures. Spacious, durable, and
                                comfortable. Available now.
                              slug_base: mountain-backpack
                              slug: mountain-backpack-b37
                            es-ES:
                              url: https://tienda.ejemplo.com/mochila-montana-b37/
                              name: Mochila de Montaña
                              description: >-
                                La mochila perfecta para aventuras en la
                                montaña.
                              body_html: >-
                                <p>La mochila perfecta para <b>aventuras en la
                                montaña</b>. Espaciosa, duradera y cómoda.</p>
                              long_name: Mochila de Montaña - Modelo 2026
                              meta_title: Compra la Mochila de Montaña Online
                              meta_description: >-
                                Consigue la Mochila de Montaña, la mochila
                                perfecta para aventuras en la montaña.
                                Espaciosa, duradera y cómoda. Disponible ahora.
                              slug_base: mochila-montana
                              slug: mochila-montana-b37
                        - id: 56
                          internal_id: city-bike
                          created_at: '2026-02-20T11:30:00Z'
                          updated_at: '2026-05-02T14:00:00Z'
                          product_structure: simple
                          status: published
                          product_kind: physical
                          stock_management: deny-without-own-stock
                          effective_stock_management: deny-without-own-stock
                          online_availability: pickup-only
                          model_code: ctybk_2026
                          tax_category: standard
                          supplier:
                            id: 8
                            name: Urban Supplies Ltd.
                          brand:
                            id: 6
                            name: CITYGEAR
                            internal_id: ctygr
                            translations:
                              en-GB:
                                url: https://shop.example.com/brands/citygear/
                              es-ES:
                                url: https://tienda.ejemplo.com/marcas/citygear/
                          categories:
                            - id: 22
                              internal_id: bikes
                              translations:
                                en-GB:
                                  url: https://shop.example.com/bikes/
                                  name: Bikes
                                es-ES:
                                  url: https://tienda.ejemplo.com/bicicletas/
                                  name: Bicicletas
                            - id: 23
                              internal_id: urban-mobility
                              translations:
                                en-GB:
                                  url: https://shop.example.com/urban-mobility/
                                  name: Urban Mobility
                                es-ES:
                                  url: https://tienda.ejemplo.com/movilidad-urbana/
                                  name: Movilidad Urbana
                            - id: 74
                              internal_id: spring-collection-2026
                              translations:
                                en-GB:
                                  url: >-
                                    https://shop.example.com/spring-collection-2026/
                                  name: Spring Collection 2026
                                es-ES:
                                  url: >-
                                    https://tienda.ejemplo.com/coleccion-primavera-2026/
                                  name: Colección Primavera 2026
                          images:
                            - id: 301
                              fullsize: >-
                                https://media.example.com/product/city-bike-1.jpg?width=1200
                              position: 0
                          variants_count: 1
                          variants:
                            - id: 401
                              internal_id: null
                              sku: ctybk-2026
                              ean: '9876543210124'
                              status: published
                              available_stock: 10
                              prices:
                                market_en:
                                  list_price:
                                    amount: '499.99'
                                    currency: EUR
                                  offer_price:
                                    amount: '429.99'
                                    currency: EUR
                                  flash_offer: null
                                  selling_price:
                                    amount: '429.99'
                                    currency: EUR
                                market_es:
                                  list_price:
                                    amount: '499.99'
                                    currency: EUR
                                  offer_price:
                                    amount: '399.99'
                                    currency: EUR
                                  flash_offer: null
                                  selling_price:
                                    amount: '399.99'
                                    currency: EUR
                              translations:
                                en-GB:
                                  name: null
                                es-ES:
                                  name: null
                          translations:
                            en-GB:
                              url: https://shop.example.com/city-bike-b38/
                              name: City Bike
                              description: >-
                                The ideal bike for urban commuting. Stylish,
                                efficient, and eco-friendly.
                              body_html: >-
                                <p>The ideal bike for <b>urban commuting</b>.
                                Stylish, efficient, and eco-friendly.</p>
                              long_name: City Bike - Model 2026
                              meta_title: Buy City Bike Online - CITYGEAR
                              meta_description: >-
                                Get the City Bike, the ideal bike for urban
                                commuting. Stylish, efficient, and eco-friendly.
                                Available now at CITYGEAR.
                              slug_base: city-bike
                              slug: city-bike-b38
                            es-ES:
                              url: https://tienda.ejemplo.com/bicicleta-urbana-b38/
                              name: Bicicleta Urbana
                              description: >-
                                La bicicleta ideal para desplazarse por la
                                ciudad. Elegante, eficiente y ecológica.
                              body_html: >-
                                <p>La bicicleta ideal para <b>desplazarse por la
                                ciudad</b>. Elegante, eficiente y ecológica.</p>
                              long_name: Bicicleta Urbana - Modelo 2026
                              meta_title: Compra la Bicicleta Urbana Online - CITYGEAR
                              meta_description: >-
                                Consigue la Bicicleta Urbana, la bicicleta ideal
                                para desplazarse por la ciudad. Elegante,
                                eficiente y ecológica. Disponible ahora en
                                CITYGEAR.
                              slug_base: bicicleta-urbana
                              slug: bicicleta-urbana-b38
                  summary: >-
                    All fields (e.g.
                    ?fields=product_structure,status,...&includes=variants,...)
          description: OK
  /api/v1/products/{id}/:
    get:
      operationId: Get Product Detail
      description: Retrieve detailed information about a specific product by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Products
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
              examples:
                DefaultFields:
                  value:
                    id: 42
                    internal_id: urban-shoe
                    product_structure: with-variants
                    status: published
                    product_kind: physical
                    model_code: urbn_2026
                    tax_category: standard
                    images:
                      - id: 101
                        fullsize: >-
                          https://media.example.com/product/urban-shoe-1.jpg?width=1200
                        position: 0
                      - id: 102
                        fullsize: >-
                          https://media.example.com/product/urban-shoe-2.jpg?width=1200
                        position: 1
                    variants_count: 3
                    translations:
                      en-GB:
                        url: https://shop.example.com/urban-shoe/
                        name: Urban Shoe
                        slug_base: urban-shoe
                        slug: urban-shoe-2026
                      es-ES:
                        url: https://tienda.ejemplo.com/urban-shoe/
                        name: Zapato Urbano
                        slug_base: zapato-urbano
                        slug: zapato-urbano-2026
                  summary: Default fields
                AllFields(e.g.?fields=productStructure,status,...&includes=variants,...):
                  value:
                    id: 42
                    internal_id: urban-shoe
                    created_at: '2026-03-10T09:00:00Z'
                    updated_at: '2026-05-01T12:00:00Z'
                    product_structure: with-variants
                    status: published
                    product_kind: physical
                    stock_management: default
                    effective_stock_management: deny-without-own-or-supplier-stock
                    online_availability: shipping-and-pickup
                    model_code: urbn_2026
                    tax_category: standard
                    supplier:
                      id: 7
                      name: Urban Supplies Ltd.
                    brand:
                      id: 5
                      name: URBANO
                      internal_id: urbn
                      translations:
                        en-GB:
                          url: https://shop.example.com/brands/urbano/
                        es-ES:
                          url: https://tienda.ejemplo.com/marcas/urbano/
                    categories:
                      - id: 21
                        internal_id: shoes
                        translations:
                          en-GB:
                            url: https://shop.example.com/shoes/
                            name: Shoes
                          es-ES:
                            url: https://tienda.ejemplo.com/zapatos/
                            name: Zapatos
                    images:
                      - id: 101
                        fullsize: >-
                          https://media.example.com/product/urban-shoe-1.jpg?width=1200
                        position: 0
                      - id: 102
                        fullsize: >-
                          https://media.example.com/product/urban-shoe-2.jpg?width=1200
                        position: 1
                    variants_count: 3
                    variants:
                      - id: 201
                        internal_id: null
                        sku: urbn-41
                        ean: '1234567890123'
                        status: published
                        available_stock: 12
                        prices:
                          market_en:
                            list_price:
                              amount: '100.00'
                              currency: GBP
                            offer_price:
                              amount: '89.99'
                              currency: GBP
                            flash_offer: null
                            selling_price:
                              amount: '89.99'
                              currency: GBP
                          market_es:
                            list_price:
                              amount: '120.00'
                              currency: EUR
                            offer_price:
                              amount: '99.99'
                              currency: EUR
                            flash_offer: null
                            selling_price:
                              amount: '99.99'
                              currency: EUR
                        translations:
                          en-GB:
                            name: '41'
                          es-ES:
                            name: '41'
                      - id: 202
                        internal_id: null
                        sku: urbn-42
                        ean: '1234567890124'
                        status: published
                        available_stock: 0
                        prices:
                          market_en:
                            list_price:
                              amount: '100.00'
                              currency: GBP
                            offer_price:
                              amount: '89.99'
                              currency: GBP
                            flash_offer: null
                            selling_price:
                              amount: '89.99'
                              currency: GBP
                          market_es:
                            list_price:
                              amount: '120.00'
                              currency: EUR
                            offer_price:
                              amount: '99.99'
                              currency: EUR
                            flash_offer:
                              valid_from: '2026-05-01'
                              valid_until: '2026-05-07'
                              price:
                                amount: '79.99'
                                currency: EUR
                            selling_price:
                              amount: '79.99'
                              currency: EUR
                        translations:
                          en-GB:
                            name: '42'
                          es-ES:
                            name: '42'
                      - id: 203
                        internal_id: null
                        sku: urbn-43
                        ean: '1234567890125'
                        status: published
                        available_stock: 5
                        prices:
                          market_en:
                            list_price:
                              amount: '100.00'
                              currency: GBP
                            offer_price:
                              amount: '84.50'
                              currency: GBP
                            flash_offer: null
                            selling_price:
                              amount: '84.50'
                              currency: GBP
                          market_es:
                            list_price:
                              amount: '94.50'
                              currency: EUR
                            offer_price: null
                            flash_offer: null
                            selling_price:
                              amount: '94.50'
                              currency: EUR
                        translations:
                          en-GB:
                            name: '43'
                          es-ES:
                            name: '43'
                    translations:
                      en-GB:
                        url: https://shop.example.com/urban-shoe/
                        name: Urban Shoe
                        description: >-
                          The perfect shoe for city life. Stylish, comfortable,
                          and durable.
                        body_html: >-
                          <p>The perfect shoe for <b>city life</b>. Stylish,
                          comfortable, and durable.</p>
                        long_name: Urban Shoe - Model 2026
                        meta_title: Buy Urban Shoe Online - URBANO
                        meta_description: >-
                          Get the Urban Shoe, the perfect shoe for city life.
                          Stylish, comfortable, and durable. Available now at
                          URBANO.
                        slug_base: urban-shoe
                        slug: urban-shoe-2026
                      es-ES:
                        url: https://tienda.ejemplo.com/urban-shoe/
                        name: Zapato Urbano
                        description: >-
                          El zapato perfecto para la vida urbana. Elegante,
                          cómodo y duradero.
                        body_html: >-
                          <p>El zapato perfecto para la <b>vida urbana</b>.
                          Elegante, cómodo y duradero.</p>
                        long_name: Zapato Urbano - Modelo 2026
                        meta_title: Compra el Zapato Urbano Online - URBANO
                        meta_description: >-
                          Consigue el Zapato Urbano, el zapato perfecto para la
                          vida urbana. Elegante, cómodo y duradero. Disponible
                          ahora en URBANO.
                        slug_base: zapato-urbano
                        slug: zapato-urbano-2026
                  summary: >-
                    All fields (e.g.
                    ?fields=product_structure,status,...&includes=variants,...)
          description: OK
  /api/v1/products/{product_id}/variants/:
    get:
      operationId: List Variants of a Product
      description: Retrieve a paginated list of variants of a product.
      parameters:
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
        - in: path
          name: product_id
          schema:
            type: integer
          required: true
      tags:
        - Variants
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedVariantList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - id: 201
                          internal_id: PIM-V-987
                          sku: sneaker-41
                          ean: '8431234567890'
                          status: published
                          available_stock: 270
                          prices:
                            market_es:
                              selling_price:
                                amount: '89.99'
                                currency: EUR
                              list_price:
                                amount: '109.00'
                                currency: EUR
                              offer_price:
                                amount: '89.99'
                                currency: EUR
                              flash_offer: null
                          translations:
                            es-ES:
                              name: Zapatilla Deportiva Talla 41
                            en-GB:
                              name: Sports Sneaker Size 41
                        - id: 201
                          internal_id: PIM-V-988
                          sku: sneaker-42
                          ean: '8431234567890'
                          status: published
                          available_stock: 265
                          prices:
                            market_es:
                              selling_price:
                                amount: '89.99'
                                currency: EUR
                              list_price:
                                amount: '109.00'
                                currency: EUR
                              offer_price:
                                amount: '89.99'
                                currency: EUR
                              flash_offer: null
                          translations:
                            es-ES:
                              name: Zapatilla Deportiva Talla 42
                            en-GB:
                              name: Sports Sneaker Size 42
                  summary: Default fields
                AllFields(e.g.?fields=minQuantity,supplierStock,costPrice,...):
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - id: 201
                          internal_id: PIM-V-987
                          sku: sneaker-41
                          ean: '8431234567890'
                          status: published
                          min_quantity: 1
                          quantity_factor: 1
                          warehouse_stock: 20
                          supplier_stock: 250
                          available_stock: 270
                          weight: '0.85'
                          volume: '0.003'
                          cost_price:
                            amount: '50.00'
                            currency: EUR
                          prices:
                            market_es:
                              selling_price:
                                amount: '89.99'
                                currency: EUR
                              list_price:
                                amount: '109.00'
                                currency: EUR
                              offer_price:
                                amount: '89.99'
                                currency: EUR
                              flash_offer: null
                          translations:
                            es-ES:
                              name: Zapatilla Deportiva Talla 41
                              description: >-
                                Zapatilla deportiva cómoda y ligera, ideal para
                                correr.
                              body_html: >-
                                <p>Zapatilla deportiva <b>cómoda y ligera</b>,
                                ideal para correr.</p>
                            en-GB:
                              name: Sports Sneaker Size 41
                              description: >-
                                Comfortable and lightweight sports sneaker,
                                ideal for running.
                              body_html: >-
                                <p>Comfortable and <b>lightweight sports
                                sneaker</b>, ideal for running.</p>
                        - id: 201
                          internal_id: PIM-V-988
                          sku: sneaker-42
                          ean: '8431234567890'
                          status: published
                          min_quantity: 1
                          quantity_factor: 1
                          warehouse_stock: 15
                          supplier_stock: 250
                          available_stock: 265
                          weight: '0.85'
                          volume: '0.003'
                          cost_price:
                            amount: '50.00'
                            currency: EUR
                          prices:
                            market_es:
                              selling_price:
                                amount: '89.99'
                                currency: EUR
                              list_price:
                                amount: '109.00'
                                currency: EUR
                              offer_price:
                                amount: '89.99'
                                currency: EUR
                              flash_offer: null
                          translations:
                            es-ES:
                              name: Zapatilla Deportiva Talla 42
                              description: >-
                                Zapatilla deportiva cómoda y ligera, ideal para
                                correr.
                              body_html: >-
                                <p>Zapatilla deportiva <b>cómoda y ligera</b>,
                                ideal para correr.</p>
                            en-GB:
                              name: Sports Sneaker Size 42
                              description: >-
                                Comfortable and lightweight sports sneaker,
                                ideal for running.
                              body_html: >-
                                <p>Comfortable and <b>lightweight sports
                                sneaker</b>, ideal for running.</p>
                  summary: >-
                    All fields (e.g.
                    ?fields=min_quantity,supplier_stock,cost_price,...)
          description: OK
  /api/v1/products/bulk-upsert/:
    post:
      operationId: Bulk Upsert Products
      description: >-
        <p>Creates an asynchronous bulk upsert job to create or updateproducts
        and their related data from the provided payload.</p><h3>Asynchronous
        processing</h3><p>This endpoint does not process the update within the
        request cycle. Before creating the job, OpenTiendas performs an initial
        validation of the request, including JSON format, payload structure,
        payload size and required top-level fields.</p><p>If the request fails
        this initial validation, no job is created and an error response is
        returned. The response may be <code>413 Request Entity Too Large</code>
        if the payload exceeds the maximum allowed size, or <code>400 Bad
        Request</code> for other validation errors.</p><p>If the request passes
        this initial validation, the endpoint creates and queues a job, then
        returns <code>202 Accepted</code> with the corresponding
        <code>job_id</code>. This confirms that the request has been accepted
        for asynchronous processing, but does not mean that all variants have
        already been updated successfully.</p><p>Record-level validations and
        update operations are performed later, during job processing.</p><h3>Job
        result</h3><p>The progress and result of the operation can be reviewed
        using the returned <code>job_id</code>.</p><p>The job log includes
        processing information, validation errors, affected variant identifiers
        when available, and a final summary with the total processed and failed
        records.</p><h3>Updating existing variants</h3><p>When updating existing
        variants, it is not necessary to send the full variant data. The request
        only needs to include the identifier required by <code>match_by</code>
        and the fields that should be modified.</p><p>Supported
        <code>match_by</code> values are <code>id</code> and
        <code>internal_id</code>. <code>id</code> matches records using the
        OpenTiendas platform identifier. <code>internal_id</code> matches
        records using the custom internal identifier provided in the
        payload.</p><h3>Limits</h3><p>Maximum request payload: 10 MB. Requests
        exceeding this limit are rejected.</p>
      tags:
        - Products
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductBulkUpsert'
            examples:
              POSTExample:
                value:
                  products:
                    - internal_id: mountain-backpack
                      product_structure: simple
                      status: unpublished
                      product_kind: physical
                      stock_management: default
                      online_availability: shipping-only
                      model_code: mtbpk_2026
                      tax_category: standard
                      supplier_id: 7
                      brand_id: 5
                      category_ids:
                        - 21
                      images:
                        - url: https://external.server.com/mountain-backpack-1.jpg
                          position: 0
                        - url: https://external.server.com/mountain-backpack-2.jpg
                          position: 1
                      variants:
                        - internal_id: mountain-backpack-variant
                          sku: mtbpk-2026
                          ean: '9876543210123'
                          status: unpublished
                          min_quantity: 1
                          quantity_factor: 1
                          warehouse_stock: 50
                          supplier_stock: 100
                          prices:
                            market_en:
                              list_price:
                                amount: '230.00'
                                currency: EUR
                              offer_price:
                                amount: '179.99'
                                currency: EUR
                            market_es:
                              list_price:
                                amount: '230.00'
                                currency: EUR
                              offer_price:
                                amount: '149.99'
                                currency: EUR
                      translations:
                        en-GB:
                          name: Mountain Backpack
                          description: The perfect backpack for mountain adventures.
                          body_html: >-
                            <p>The perfect backpack for <b>mountain
                            adventures</b>. Spacious, durable, and
                            comfortable.</p>
                          long_name: Mountain Backpack - Model 2026
                          meta_title: Buy Mountain Backpack Online
                          meta_description: >-
                            Get the Mountain Backpack, the perfect backpack for
                            mountain adventures. Spacious, durable, and
                            comfortable. Available now.
                        es-ES:
                          name: Mochila de Montaña
                          description: La mochila perfecta para aventuras en la montaña.
                          body_html: >-
                            <p>La mochila perfecta para <b>aventuras en la
                            montaña</b>. Espaciosa, duradera y cómoda.</p>
                          long_name: Mochila de Montaña - Modelo 2026
                          meta_title: Compra la Mochila de Montaña Online
                          meta_description: >-
                            Consigue la Mochila de Montaña, la mochila perfecta
                            para aventuras en la montaña. Espaciosa, duradera y
                            cómoda. Disponible ahora.
                    - internal_id: city-bike
                      product_structure: with-variants
                      status: published
                      product_kind: physical
                      stock_management: deny-without-own-stock
                      online_availability: pickup-only
                      model_code: ctybk_2026
                      tax_category: standard
                      supplier_id: 8
                      brand_id: 6
                      category_ids:
                        - 22
                        - 23
                        - 74
                      images:
                        - url: https://external.server.com/city-bike-1.jpg
                          position: 0
                      variants:
                        - internal_id: city-bike-m-red-2026
                          sku: ctybk-m-red-2026
                          ean: '9876543210124'
                          status: published
                          warehouse_stock: 10
                          prices:
                            market_en:
                              list_price:
                                amount: '499.99'
                                currency: EUR
                              offer_price:
                                amount: '429.99'
                                currency: EUR
                            market_es:
                              list_price:
                                amount: '549.99'
                                currency: EUR
                              offer_price:
                                amount: '479.99'
                                currency: EUR
                              flash_offer:
                                price:
                                  amount: '399.99'
                                  currency: EUR
                                valid_from: '2026-04-01'
                                valid_until: '2026-04-07'
                          translations:
                            en-GB:
                              name: Red / M
                            es-ES:
                              name: Talla M / Rojo
                        - internal_id: city-bike-m-blue-2026
                          sku: ctybk-m-blue-2026
                          ean: '9876543210125'
                          status: published
                          warehouse_stock: 5
                          prices:
                            market_en:
                              list_price:
                                amount: '499.99'
                                currency: EUR
                            market_es:
                              list_price:
                                amount: '549.99'
                                currency: EUR
                          translations:
                            en-GB:
                              name: Blue / M
                            es-ES:
                              name: Talla M / Azul
                      translations:
                        en-GB:
                          name: City Bike
                          description: The ideal bike for urban commuting.
                          body_html: >-
                            <p>The ideal bike for <b>urban commuting</b>.
                            Stylish, comfortable, and efficient.</p>
                          long_name: City Bike - Model 2026
                          meta_title: Buy City Bike Online
                          meta_description: >-
                            Get the City Bike, the ideal bike for urban
                            commuting. Stylish, comfortable, and efficient.
                            Available now.
                        es-ES:
                          name: Bicicleta Urbana
                          description: La bicicleta ideal para desplazarse por la ciudad.
                          body_html: >-
                            <p>La bicicleta ideal para <b>desplazarse por la
                            ciudad</b>. Elegante, cómoda y eficiente.</p>
                          long_name: Bicicleta Urbana - Modelo 2026
                          meta_title: Compra la Bicicleta Urbana Online
                          meta_description: >-
                            Consigue la Bicicleta Urbana, la bicicleta ideal
                            para desplazarse por la ciudad. Elegante, cómoda y
                            eficiente. Disponible ahora.
                  options:
                    match_by: internal_id
                summary: POST Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ProductBulkUpsert'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ProductBulkUpsert'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkJobCreationResponse'
              examples:
                POST202Example:
                  value:
                    - job_id: 123e4567-e89b-12d3-a456-426614174000
                      status: pending
                  summary: POST 202 Example
          description: Accepted. The bulk upsert job has been created.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductBulkUpsertErrorResponse'
              examples:
                POST400Example-Missing'products':
                  value:
                    detail: The 'products' field must be an array.
                  summary: POST 400 Example - Missing 'products'
          description: >-
            Bad Request. The request payload is invalid or missing required
            fields.
        '413':
          description: >-
            Payload Too Large. The request payload exceeds the maximum allowed
            size.
  /api/v1/reviews/:
    get:
      operationId: List Reviews
      description: >-
        Retrieve a paginated list of reviews with optional filtering and
        ordering.
      parameters:
        - in: query
          name: created_at_from
          schema:
            type: string
            format: date-time
          description: >-
            Filter reviews created from this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T00:00:00Z). If the time component is
            omitted, 00:00:00 is assumed.
        - in: query
          name: created_at_to
          schema:
            type: string
            format: date-time
          description: >-
            Filter reviews created up to this date/time (inclusive) in ISO 8601
            format (e.g. 2023-01-01T23:59:59Z). If the time component is
            omitted, 23:59:59 is assumed.
        - in: query
          name: locale
          schema:
            type: string
            enum:
              - ca-ES
              - da-DK
              - de-DE
              - el-GR
              - en-GB
              - es-ES
              - fr-FR
              - hr-HR
              - it-IT
              - nl-NL
              - pl-PL
              - pt-PT
              - ru-RU
              - sv-SE
          description: |-
            Filter by locale.

            * `es-ES` - Spanish (Spain)
            * `ca-ES` - Catalan (Spain)
            * `en-GB` - English (United Kingdom)
            * `fr-FR` - French (France)
            * `it-IT` - Italian (Italy)
            * `pt-PT` - Portuguese (Portugal)
            * `de-DE` - German (Germany)
            * `ru-RU` - Russian (Russia)
            * `nl-NL` - Dutch (Netherlands)
            * `sv-SE` - Swedish (Sweden)
            * `da-DK` - Danish (Denmark)
            * `pl-PL` - Polish (Poland)
            * `el-GR` - Greek (Greece)
            * `hr-HR` - Croatian (Croatia)
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
        - in: query
          name: product_id
          schema:
            type: number
          description: Filter reviews by product ID.
        - in: query
          name: rating
          schema:
            type: array
            items:
              type: integer
          description: >-
            Filter reviews by a rating or a list of ratings (comma-separated).
            Valid rating values are 1 to 5.
          explode: false
          style: form
        - name: sort
          required: false
          in: query
          description: >-
            Which field to use when ordering the results. Use '_asc' or '_desc'
            suffix to specify ascending or descending order. Valid values are:
            `created_at_asc`, `created_at_desc`, `rating_asc`,
            `rating_desc`.<p>Default value: ``created_at_desc``
          schema:
            type: string
        - in: query
          name: status
          schema:
            type: string
            enum:
              - published
              - unpublished
          description: |-
            Filter reviews by publication status.

            * `published` - published
            * `unpublished` - unpublished
        - in: query
          name: type
          schema:
            type: string
            nullable: true
            enum:
              - null
              - product
              - store
          description: Filter reviews by type.
      tags:
        - Reviews
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedReviewList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 2
                        locale: en-GB
                        status: published
                        rating: 5
                        created_at: '2019-08-24T14:15:22Z'
                        type: product
                  summary: Default fields
                AllFields(e.g.?fields=locale,status,rating,content,...):
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - id: 2
                        locale: en-GB
                        status: published
                        rating: 5
                        content: >-
                          The product matches the description perfectly. Highly
                          recommended.
                        created_at: '2019-08-24T14:15:22Z'
                        reviewer_name: Emily Smith
                        reviewer_email: emily.smith@example.com
                        order_id: 123456
                        customer:
                          id: 789
                          is_active: true
                          email: emily.smith@example.com
                          first_name: Emily
                          last_name: Smith
                          phone: '+1234567890'
                          preferred_locale: en-GB
                          created_at: '2023-01-01T10:00:00Z'
                          is_b2b: false
                        type: product
                        product_id: 2532
                        product_name: Example Product
                        variant_id: 1234
                        variant_name: Example Variant
                  summary: All fields (e.g. ?fields=locale,status,rating,content,...)
          description: OK
    post:
      operationId: Create Review
      description: Create a new review with the provided details.
      tags:
        - Reviews
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Review'
            examples:
              POSTExample:
                value:
                  locale: en-GB
                  status: published
                  rating: 5
                  content: >-
                    The product matches the description perfectly. Highly
                    recommended.
                  created_at: '2024-01-15T09:22:10Z'
                  reviewer_name: Emily Smith
                  reviewer_email: emily.smith@example.com
                  order_id: 123456
                  customer_id: 789
                  type: product
                  product_id: 2532
                  variant_id: null
                summary: POST Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Review'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/Review'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Review'
              examples:
                POST201Example:
                  value:
                    - id: 3
                      locale: en-GB
                      status: published
                      rating: 5
                      created_at: '2024-01-15T09:22:10Z'
                      type: product
                  summary: POST 201 Example
          description: Created
  /api/v1/reviews/{id}/:
    get:
      operationId: Get Review Detail
      description: Retrieve detailed information about a specific review by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Reviews
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Review'
              examples:
                StoreReviewWithDefaultFields:
                  value:
                    id: 3
                    locale: en-GB
                    status: published
                    rating: 5
                    created_at: '2024-01-15T09:22:10Z'
                    type: store
                  summary: Store review with default fields
                StoreReviewWithAllFields(e.g.?fields=locale,status,rating,content,...):
                  value:
                    id: 3
                    locale: en-GB
                    status: published
                    rating: 5
                    content: The shopping experience was excellent. Highly recommended.
                    created_at: '2024-01-15T09:22:10Z'
                    reviewer_name: Emily Smith
                    reviewer_email: emily.smith@example.com
                    order_id: 123456
                    customer:
                      id: 789
                      is_active: true
                      email: emily.smith@example.com
                      first_name: Emily
                      last_name: Smith
                      phone: '+1234567890'
                      preferred_locale: en-GB
                      created_at: '2023-01-01T10:00:00Z'
                      is_b2b: false
                    type: store
                  summary: >-
                    Store review with all fields (e.g.
                    ?fields=locale,status,rating,content,...)
                ProductReviewWithDefaultFields:
                  value:
                    id: 4
                    locale: en-GB
                    status: published
                    rating: 4
                    created_at: '2024-01-16T10:15:30Z'
                    type: product
                  summary: Product review with default fields
                ProductReviewWithAllFields(e.g.?fields=locale,status,rating,content,...):
                  value:
                    id: 4
                    locale: en-GB
                    status: published
                    rating: 4
                    content: The product quality is good, but delivery was slow.
                    created_at: '2024-01-16T10:15:30Z'
                    reviewer_name: John Doe
                    reviewer_email: john.doe@example.com
                    order_id: 123457
                    customer:
                      id: 790
                      is_active: true
                      email: john.doe@example.com
                      first_name: John
                      last_name: Doe
                      phone: '+1234567891'
                      preferred_locale: en-GB
                      created_at: '2023-01-02T11:00:00Z'
                      is_b2b: false
                    type: product
                    product_id: 2533
                    product_name: Example Product 2
                    variant_id: 1235
                    variant_name: Size M - Blue
                  summary: >-
                    Product review with all fields (e.g.
                    ?fields=locale,status,rating,content,...)
          description: OK
    patch:
      operationId: Update Review
      description: Update an existing review's details.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Reviews
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedReview'
            examples:
              PATCHExample:
                value:
                  content: The shopping experience was good.
                  rating: 4
                summary: PATCH Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedReview'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedReview'
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Review'
              examples:
                PATCH200Example:
                  value:
                    id: 3
                    locale: en-GB
                    status: published
                    rating: 4
                    created_at: '2024-01-15T09:22:10Z'
                    type: store
                  summary: PATCH 200 Example
          description: OK
    delete:
      operationId: Delete Review
      description: Delete a specific review by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Reviews
      security:
        - ApiKeyAuth: []
      responses:
        '204':
          description: No Content
  /api/v1/store/:
    get:
      operationId: Get Store Information
      description: >-
        Retrieves the store's return policy, and the name, domain, logo URL, and
        configured email accounts for each supported locale.
      tags:
        - Store
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StoreInfo'
              examples:
                StoreInfoExample:
                  value:
                    return_policy:
                      applicable_countries:
                        - ES
                        - DE
                        - FR
                      return_policy_country: ES
                      return_days: 30
                      return_method: by_mail
                      return_fees: customer_pays
                      refund_type: full
                      return_label_source: download_and_print
                      item_condition: new
                    translations:
                      en-GB:
                        name: My OpenTiendas Store
                        domain: example.com
                        logo_url: https://example.com/static/logo.png
                        orders_email_account: orders@example.com
                        contact_email_account: contact@example.com
                        promotions_email_account: promotions@example.com
                      fr-FR:
                        name: Ma boutique OpenTiendas
                        domain: example.fr
                        logo_url: https://example.fr/static/logo.png
                        orders_email_account: orders@example.fr
                        contact_email_account: contact@example.fr
                        promotions_email_account: promotions@example.fr
                      es-ES:
                        name: Mi tienda OpenTiendas
                        domain: example.es
                        logo_url: https://example.es/static/logo.png
                        orders_email_account: orders@example.es
                        contact_email_account: contact@example.es
                        promotions_email_account: promotions@example.es
                  summary: Store Info Example
          description: OK
  /api/v1/suppliers/:
    get:
      operationId: List Suppliers
      description: Retrieve a paginated list of suppliers.
      parameters:
        - name: page
          required: false
          in: query
          description: A page number within the paginated result set.
          schema:
            type: integer
        - name: per_page
          required: false
          in: query
          description: Number of results to return per page.
          schema:
            type: integer
            default: 50
            maximum: 100
      tags:
        - Suppliers
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedSupplierList'
              examples:
                DefaultFields:
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - id: 1
                          name: Example Supplier
                  summary: Default fields
                AllFields(e.g.?fields=name,internalId,description):
                  value:
                    pagination:
                      current_page: 3
                      per_page: 50
                      total: 223
                      total_pages: 5
                      next_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
                      previous_page_url: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
                    data:
                      - - id: 1
                          name: Example Supplier
                          internal_id: SUP-001
                          description: Supplier for testing
                  summary: All fields (e.g. ?fields=name,internal_id,description)
          description: OK
    post:
      operationId: Create Supplier
      description: Create a new supplier with the provided details.
      tags:
        - Suppliers
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Supplier'
            examples:
              POSTExample:
                value:
                  name: New Supplier
                  internal_id: SUP-002
                  description: A newly created supplier
                summary: POST Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Supplier'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/Supplier'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Supplier'
              examples:
                POST201Example:
                  value:
                    id: 2
                    name: New Supplier
                  summary: POST 201 Example
          description: Created
  /api/v1/suppliers/{id}/:
    get:
      operationId: Get Supplier Detail
      description: Retrieve detailed information about a specific supplier by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Suppliers
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Supplier'
              examples:
                DefaultFields:
                  value:
                    id: 1
                    name: Supplier A
                  summary: Default fields
                AllFields(e.g.?fields=name,internalId,description):
                  value:
                    id: 1
                    name: Supplier A
                    internal_id: SUP-A-001
                    description: Main supplier for electronics.
                  summary: All fields (e.g. ?fields=name,internal_id,description)
          description: OK
    patch:
      operationId: Update Supplier
      description: Update an existing supplier's details.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Suppliers
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedSupplier'
            examples:
              PATCHExample:
                value:
                  description: Updated description for Supplier A.
                summary: PATCH Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedSupplier'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedSupplier'
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Supplier'
              examples:
                PATCH200Example:
                  value:
                    id: 1
                    name: Supplier A
                  summary: PATCH 200 Example
          description: OK
    delete:
      operationId: Delete Supplier
      description: Delete a specific supplier by its ID.
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      tags:
        - Suppliers
      security:
        - ApiKeyAuth: []
      responses:
        '204':
          description: No Content
  /api/v1/variants/bulk-update/:
    post:
      operationId: Bulk Update Variants
      description: >-
        <p>Creates an asynchronous bulk update job to update variants and their
        related data from the provided payload.</p><h3>Asynchronous
        processing</h3><p>This endpoint does not process the update within the
        request cycle. Before creating the job, OpenTiendas performs an initial
        validation of the request, including JSON format, payload structure,
        payload size and required top-level fields.</p><p>If the request fails
        this initial validation, no job is created and an error response is
        returned. The response may be <code>413 Request Entity Too Large</code>
        if the payload exceeds the maximum allowed size, or <code>400 Bad
        Request</code> for other validation errors.</p><p>If the request passes
        this initial validation, the endpoint creates and queues a job, then
        returns <code>202 Accepted</code> with the corresponding
        <code>job_id</code>. This confirms that the request has been accepted
        for asynchronous processing, but does not mean that all variants have
        already been updated successfully.</p><p>Record-level validations and
        update operations are performed later, during job processing.</p><h3>Job
        result</h3><p>The progress and result of the operation can be reviewed
        using the returned <code>job_id</code>.</p><p>The job log includes
        processing information, validation errors, affected variant identifiers
        when available, and a final summary with the total processed and failed
        records.</p><p>After the job is completed/finished, changes may take a
        short time to propagate across all parts of the shop.</p><h3>Updating
        existing variants</h3><p>When updating existing variants, it is not
        necessary to send the full variant data. The request only needs to
        include the identifier required by <code>match_by</code> and the fields
        that should be modified.</p><p>Supported <code>match_by</code> values
        are <code>id</code>, <code>internal_id</code>, <code>ean</code>, and
        <code>sku_supplier</code>. When using <code>sku_supplier</code>, the
        request must include both the SKU and the supplier internal
        ID.</p><p>Fields marked as required in this schema apply to variant
        creation.</p><h3>Limits</h3><p>Maximum request payload: 10 MB. Requests
        exceeding this limit are rejected.</p>
      tags:
        - Variants
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SellableProductBulkUpdate'
            examples:
              POSTExample:
                value:
                  variants:
                    - id: 201
                      internal_id: PIM-V-987
                      sku: urbn-41
                      ean: '1234567890123'
                      status: published
                      min_quantity: 1
                      quantity_factor: 1
                      supplier_stock: 250
                      warehouse_stock: 20
                      cost_price:
                        amount: '50.00'
                        currency: EUR
                      prices:
                        market_en:
                          list_price:
                            amount: '95.00'
                            currency: EUR
                          offer_price:
                            amount: '89.99'
                            currency: EUR
                        market_es:
                          list_price:
                            amount: '109.00'
                            currency: EUR
                          offer_price:
                            amount: '99.99'
                            currency: EUR
                          flash_offer:
                            price:
                              amount: '94.99'
                              currency: EUR
                            valid_from: '2025-06-25'
                            valid_until: '2025-06-30'
                      translations:
                        en-GB:
                          name: '41'
                        es-ES:
                          name: '41'
                    - id: 202
                      internal_id: PIM-V-988
                      sku: urbn-42
                      ean: '1234567890124'
                      status: published
                      min_quantity: 1
                      quantity_factor: 1
                      supplier_stock: 300
                      warehouse_stock: 50
                      cost_price:
                        amount: '55.00'
                        currency: EUR
                      prices:
                        market_en:
                          list_price:
                            amount: '100.00'
                            currency: EUR
                          offer_price:
                            amount: '94.99'
                            currency: EUR
                        market_es:
                          list_price:
                            amount: '115.00'
                            currency: EUR
                          offer_price:
                            amount: '104.99'
                            currency: EUR
                      translations:
                        en-GB:
                          name: '42'
                        es-ES:
                          name: '42'
                  options:
                    match_by: id
                summary: POST Example
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SellableProductBulkUpdate'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SellableProductBulkUpdate'
        required: true
      security:
        - ApiKeyAuth: []
      responses:
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkJobCreationResponse'
              examples:
                POST202Example:
                  value:
                    - job_id: 6582ffe3-9c4b-4d2a-8f1e-123456789abc
                      status: pending
                  summary: POST 202 Example
          description: Accepted. The bulk update job has been created.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SellableProductBulkUpdateErrorResponse'
              examples:
                POST400Example-Missing'variants':
                  value:
                    detail: The 'variants' field must be an array.
                  summary: POST 400 Example - Missing 'variants'
          description: >-
            Bad Request. The request payload is invalid or missing required
            fields.
        '413':
          description: >-
            Payload Too Large. The request payload exceeds the maximum allowed
            size.
components:
  schemas:
    Address:
      type: object
      properties:
        first_name:
          type: string
          description: First name associated with the address.
        last_name:
          type: string
          description: Last name associated with the address.
        phone:
          type: string
          title: Phone number
          description: Phone number associated with the address.
        address:
          type: string
          description: Street address associated with the customer.
        postal_code:
          type: string
          title: Postcode / ZIP code
          description: Postal or ZIP code associated with the address.
        country_code:
          type: string
          title: Country
          description: >-
            Two-letter country code in ISO 3166-1 alpha-2 format (e.g.
            <code>ES</code>, <code>FR</code>).
          maxLength: 2
        region:
          type: string
          description: Region, province or state associated with the address.
        city:
          type: string
          title: City / Town
          description: City or locality associated with the address.
        company:
          type: string
          description: Company name associated with the address, if any.
        tax_id:
          type: string
          description: Tax identification number associated with the address, if any.
        notes:
          type: string
          description: Additional delivery or address notes associated with the address.
      required:
        - address
        - city
        - first_name
        - last_name
        - phone
        - postal_code
        - region
    AddressData:
      type: object
      description: >-
        Serializer for the billing and shipping address data included in the
        Order serializer.
      properties:
        first_name:
          type: string
          description: First name of the recipient.
        last_name:
          type: string
          description: Last name of the recipient.
        phone:
          type: string
          description: Phone number of the recipient.
        company:
          type: string
          description: Company name of the recipient (if applicable).
        street_address:
          type: string
          description: First line of the street address.
        postal_code:
          type: string
          description: Postal code of the address.
        country_code:
          type: string
          description: ISO 3166-1 alpha-2 country code of the address.
        region:
          type: string
          description: Region or state of the address.
        city:
          type: string
          description: City of the address.
        tax_id:
          type: string
          description: >-
            Tax identification number of the recipient (e.g. VAT, national ID,
            passport).
      required:
        - city
        - company
        - country_code
        - first_name
        - last_name
        - phone
        - postal_code
        - region
        - street_address
        - tax_id
    Brand:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the brand.
        name:
          type: string
          description: Name of the brand.
        internal_id:
          type: string
          nullable: true
          description: >-
            Internal ID for the brand. This alternative identifier is intended
            for linking it with external systems and managing it through imports
            or API integrations.
        slug:
          type: string
          description: >-
            URL-friendly slug for the brand. If not provided, it will be
            automatically generated from the name. Updating it changes the URL
            and may impact SEO (links and indexed pages). Cache invalidation or
            page refresh may be required for the change to take effect
            immediately.
          pattern: ^[-a-zA-Z0-9_]+$
        delivery_time_in_stock:
          type: integer
          minimum: 0
          description: Estimated delivery time in days when the product is in stock.
        delivery_time_out_of_stock:
          type: integer
          minimum: 0
          description: Estimated delivery time in days when the product is out of stock.
        image_url:
          type: string
          format: uri
          nullable: true
          description: >-
            URL of the brand logo image. If provided, the image will be
            downloaded and saved. The timeout for downloading the image is set
            to 5 seconds.
        translations:
          type: array
          items:
            $ref: '#/components/schemas/BrandTranslation'
      required:
        - id
        - name
        - translations
    BrandTranslation:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        locale:
          allOf:
            - $ref: '#/components/schemas/LocaleEnum'
          description: >-
            Locale code in ISO format (e.g., es-ES, en-GB).Format follows ISO
            639-1 (language) and ISO 3166-1 alpha-2 (country) standards.


            * `es-ES` - Spanish (Spain)

            * `ca-ES` - Catalan (Spain)

            * `en-GB` - English (United Kingdom)

            * `fr-FR` - French (France)

            * `it-IT` - Italian (Italy)

            * `pt-PT` - Portuguese (Portugal)

            * `de-DE` - German (Germany)

            * `ru-RU` - Russian (Russia)

            * `nl-NL` - Dutch (Netherlands)

            * `sv-SE` - Swedish (Sweden)

            * `da-DK` - Danish (Denmark)

            * `pl-PL` - Polish (Poland)

            * `el-GR` - Greek (Greece)

            * `hr-HR` - Croatian (Croatia)
        url:
          type: string
          nullable: true
          readOnly: true
          description: URL of the brand in the frontstore for the specified locale.
        description:
          type: string
          description: Short description of the brand in the specified locale.
        body_html:
          type: string
          description: HTML body content of the brand in the specified locale.
        long_name:
          type: string
          description: Long name of the brand in the specified locale.
        meta_title:
          type: string
          description: Meta title for the brand in the specified locale.
        meta_description:
          type: string
          description: Meta description for the brand in the specified locale.
        size_guide_file:
          $ref: '#/components/schemas/SizesGuideFile'
      required:
        - body_html
        - locale
        - url
    BrandsPriceList:
      type: object
      properties:
        brands:
          type: array
          items:
            $ref: '#/components/schemas/Brand'
          readOnly: true
          description: List of brands to which the discount applies.
        brand_ids:
          type: array
          items:
            type: integer
            writeOnly: true
          writeOnly: true
          description: >-
            List of brand IDs to which the discount applies. Use this field to
            assign brands to the price list when creating or updating it.
        discount:
          type: string
          format: decimal
          pattern: ^-?\d{0,3}(?:\.\d{0,2})?$
          description: >-
            Discount percentage applied to products of the specified brands when
            applicable. Expressed as a percentage value.
      required:
        - brand_ids
        - brands
        - discount
    BulkJobCreationResponse:
      type: object
      description: |-
        Serializer for the response of bulk job creation endpoints,
        returning the job ID and initial status.
      properties:
        job_id:
          type: string
          format: uuid
          description: The unique identifier of the created job.
        status:
          type: string
          description: The initial status of the created job.
      required:
        - job_id
        - status
    CategoriesPriceList:
      type: object
      properties:
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
          readOnly: true
          description: List of categories to which the discount applies.
        category_ids:
          type: array
          items:
            type: integer
            writeOnly: true
          writeOnly: true
          description: >-
            List of category IDs to which the discount applies. Use this field
            to assign categories to the price list when creating or updating it.
        discount:
          type: string
          format: decimal
          pattern: ^-?\d{0,3}(?:\.\d{0,2})?$
          description: >-
            Discount percentage applied to products in the specified categories
            when applicable. Expressed as a percentage value.
      required:
        - categories
        - category_ids
        - discount
    Category:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the category.
        internal_id:
          type: string
          nullable: true
          description: >-
            Internal ID for the category. This alternative identifier is
            intended for linking it with external systems and managing it
            through imports or API integrations.
        image_url:
          type: string
          format: uri
          nullable: true
          description: >-
            URL of the category image. If provided, the image will be downloaded
            and saved. The timeout for downloading the image is set to 5
            seconds.
        parent_id:
          type: integer
          nullable: true
          description: >-
            ID of the parent category, if any. Null if this is a top-level
            category.
        status:
          allOf:
            - $ref: '#/components/schemas/Status062Enum'
          description: |-
            Status of the object: 'published' or 'unpublished'.

            * `published` - published
            * `unpublished` - unpublished
        merchant_categories:
          allOf:
            - $ref: '#/components/schemas/MerchantCategories'
          description: Merchant category mappings (e.g., Google taxonomy).
        translations:
          type: array
          items:
            $ref: '#/components/schemas/CategoryTranslation'
      required:
        - id
        - status
        - translations
    CategoryTranslation:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        locale:
          allOf:
            - $ref: '#/components/schemas/LocaleEnum'
          description: >-
            Locale code in ISO format (e.g., es-ES, en-GB).Format follows ISO
            639-1 (language) and ISO 3166-1 alpha-2 (country) standards.


            * `es-ES` - Spanish (Spain)

            * `ca-ES` - Catalan (Spain)

            * `en-GB` - English (United Kingdom)

            * `fr-FR` - French (France)

            * `it-IT` - Italian (Italy)

            * `pt-PT` - Portuguese (Portugal)

            * `de-DE` - German (Germany)

            * `ru-RU` - Russian (Russia)

            * `nl-NL` - Dutch (Netherlands)

            * `sv-SE` - Swedish (Sweden)

            * `da-DK` - Danish (Denmark)

            * `pl-PL` - Polish (Poland)

            * `el-GR` - Greek (Greece)

            * `hr-HR` - Croatian (Croatia)
        url:
          type: string
          nullable: true
          readOnly: true
          description: URL of the category in the frontstore for the specified locale.
        name:
          type: string
          description: Name of the category in the specified locale.
        description:
          type: string
          description: Description of the category in the specified locale.
        body_html:
          type: string
          description: HTML body content of the category in the specified locale.
        long_name:
          type: string
          description: Long name of the category in the specified locale.
        meta_title:
          type: string
          description: Meta title for the category in the specified locale.
        meta_description:
          type: string
          description: Meta description for the category in the specified locale.
        slug_base:
          type: string
          description: >-
            Editable part of the slug. Combined with the immutable suffix, it
            forms the complete slug.<p>Updating it changes the URL and may
            impact SEO (links and indexed pages). Cache invalidation or page
            refresh may be required for the change to take effect
            immediately.</p>
          pattern: ^[-a-zA-Z0-9_]+$
        slug:
          type: string
          readOnly: true
          description: >-
            Slug for the category, used in URLs. This value includes an
            immutable suffix.
          pattern: ^[-a-zA-Z0-9_]+$
      required:
        - locale
        - name
        - slug
        - url
    DeliveryMethodEnum:
      enum:
        - shipment
        - store_pick_up
      type: string
      description: |-
        * `shipment` - Shipment
        * `store_pick_up` - Store pick-up
    EffectiveStockManagementEnum:
      enum:
        - ignore-stock
        - deny-without-own-stock
        - deny-without-own-or-supplier-stock
        - allow-backorder
      type: string
      description: >-
        * `ignore-stock` - Ignores stock when determining whether the product
        can be purchased.

        * `deny-without-own-stock` - The product can only be purchased if it has
        available own stock.

        * `deny-without-own-or-supplier-stock` - The product can only be
        purchased if it has available own stock or supplier stock.

        * `allow-backorder` - The product can be purchased even when no stock is
        available.
    FlashOffer:
      type: object
      properties:
        valid_from:
          type: string
          format: date
          description: Start date of the flash offer in ISO 8601 format.
        valid_until:
          type: string
          format: date
          description: End date of the flash offer in ISO 8601 format.
        price:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: >-
            Special flash offer price for the variant, valid during the
            specified period.
      required:
        - price
        - valid_from
        - valid_until
    FulfillmentStatusEnum:
      enum:
        - unfulfilled
        - partially_fulfilled
        - fulfilled
      type: string
      description: |-
        * `unfulfilled` - unfulfilled
        * `partially_fulfilled` - partially_fulfilled
        * `fulfilled` - fulfilled
    GenderEnum:
      enum:
        - male
        - female
        - other
      type: string
      description: |-
        * `male` - male
        * `female` - female
        * `other` - other
    GrossAmount:
      type: object
      properties:
        gross:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Gross amount (including taxes).
      required:
        - gross
    ItemConditionEnum:
      enum:
        - new
      type: string
      description: '* `new` - The item is in new condition.'
    Job:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: string
          format: uuid
          description: >-
            Unique job identifier. Use this value to retrieve the job status or
            its logs.
        type:
          type: string
          nullable: true
          description: >-
            Type of asynchronous operation, such as
            <code>products_bulk_upsert</code> or
            <code>variants_bulk_update</code>.
          maxLength: 100
        status:
          allOf:
            - $ref: '#/components/schemas/JobStatusEnum'
          description: >-
            Current job status.


            * `pending` - Job is waiting to be processed.

            * `running` - Job is currently being processed.

            * `done` - Job has been completed and all records were processed
            successfully.

            * `done_with_errors` - Job has been completed but some records could
            not be processed successfully.

            * `failed` - Job has failed and no records were processed
            successfully.
        created_at:
          type: string
          format: date-time
          description: Timestamp when the job was created. ISO 8601 format.
        started_at:
          type: string
          format: date-time
          description: >-
            Timestamp when the job started processing. ISO 8601 format. May be
            null if the job has not started yet. 
        finished_at:
          type: string
          format: date-time
          description: >-
            Timestamp when the job finished processing. ISO 8601 format. May be
            null if the job has not finished yet. 
        summary:
          allOf:
            - $ref: '#/components/schemas/JobSummary'
          description: 'Processing summary for the job. '
      required:
        - created_at
        - finished_at
        - started_at
        - summary
    JobLogEntry:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier of the log entry.
        created_at:
          type: string
          format: date-time
          description: Timestamp when the log entry was created. ISO 8601 format.
        severity:
          type: string
          description: >-
            Log entry severity level. <a href='#severity-values'>See values and
            descriptions.</a>
        code:
          type: string
          description: >-
            Stable log code. Intended for filtering and programmatic handling.
            <a href='#log-codes'>See values and descriptions.</a>
        message:
          type: string
          description: Human-readable log message.
        identifiers:
          type: object
          additionalProperties:
            type: string
          nullable: true
          description: Identifiers related to the affected resource, when available.
        affected_fields:
          type: array
          items:
            type: string
          nullable: true
          description: >-
            Fields related to the log entry, when available. <code>null</code>
            when the log is not linked to specific fields.
      required:
        - created_at
        - id
        - message
        - severity
    JobStatusEnum:
      enum:
        - pending
        - running
        - done
        - done_with_errors
        - failed
      type: string
      description: >-
        * `pending` - Job is waiting to be processed.

        * `running` - Job is currently being processed.

        * `done` - Job has been completed and all records were processed
        successfully.

        * `done_with_errors` - Job has been completed but some records could not
        be processed successfully.

        * `failed` - Job has failed and no records were processed successfully.
    JobSummary:
      type: object
      properties:
        total_records:
          type: integer
          description: Total number of records included in the job, when available.
        processed_records:
          type: integer
          description: Number of records processed by the job.
        succeeded_records:
          type: integer
          description: Number of records processed successfully.
        failed_records:
          type: integer
          description: Number of records that failed during processing.
        log_info_count:
          type: integer
          description: Number of log entries with <code>INFO</code> severity.
        log_warning_count:
          type: integer
          description: Number of log entries with <code>WARNING</code> severity.
        log_error_count:
          type: integer
          description: Number of log entries with <code>ERROR</code> severity.
      required:
        - failed_records
        - log_error_count
        - log_info_count
        - log_warning_count
        - processed_records
        - succeeded_records
        - total_records
    LinkIDs:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/LinkIDsItem'
          writeOnly: true
          description: >-
            <p>List of items to link identifiers for.</p><p>For each item, the
            provided internal IDs will be linked to the corresponding variant
            and its parent product based on the available identifiers (EAN, SKU
            + supplier).</p><p>Each item must include exactly one of the
            following identifier options to match the
            variant:</p><ul><li><code>ean</code></li><li><code>sku</code> and
            <code>supplier_internal_id</code></li></ul><p>Additionally, each
            item must include at least one of the following internal ID fields
            to be
            linked:</p><ul><li><code>product_internal_id</code></li><li><code>variant_internal_id</code></li></ul>
      required:
        - items
    LinkIDsErrorResponse:
      type: object
      properties:
        detail:
          type: string
          description: Error details explaining why the request is invalid.
      required:
        - detail
    LinkIDsItem:
      type: object
      properties:
        ean:
          type: string
          description: EAN of the variant, used for identification.
          maxLength: 14
        sku:
          type: string
          description: >-
            SKU of the variant, used for identification in combination with
            supplier internal ID.
          maxLength: 40
        supplier_internal_id:
          type: string
          description: >-
            Internal ID of the supplier of the variant's parent product, used
            for identification in combination with SKU.
        product_internal_id:
          type: string
          description: >-
            Internal ID to be set for the product linked to the variant. Must be
            unique among products.
        variant_internal_id:
          type: string
          description: >-
            Internal ID to be set for the variant. Must be unique among variants
            (including across products). 
    LocaleEnum:
      enum:
        - es-ES
        - ca-ES
        - en-GB
        - fr-FR
        - it-IT
        - pt-PT
        - de-DE
        - ru-RU
        - nl-NL
        - sv-SE
        - da-DK
        - pl-PL
        - el-GR
        - hr-HR
      type: string
      description: |-
        * `es-ES` - Spanish (Spain)
        * `ca-ES` - Catalan (Spain)
        * `en-GB` - English (United Kingdom)
        * `fr-FR` - French (France)
        * `it-IT` - Italian (Italy)
        * `pt-PT` - Portuguese (Portugal)
        * `de-DE` - German (Germany)
        * `ru-RU` - Russian (Russia)
        * `nl-NL` - Dutch (Netherlands)
        * `sv-SE` - Swedish (Sweden)
        * `da-DK` - Danish (Denmark)
        * `pl-PL` - Polish (Poland)
        * `el-GR` - Greek (Greece)
        * `hr-HR` - Croatian (Croatia)
    MarketEnum:
      enum:
        - market_ru
        - market_it
        - market_de
        - market_en
        - market_pt
        - market_es
        - market_fr
      type: string
      description: |-
        * `market_ru` - market_ru
        * `market_it` - market_it
        * `market_de` - market_de
        * `market_en` - market_en
        * `market_pt` - market_pt
        * `market_es` - market_es
        * `market_fr` - market_fr
    MerchantCategories:
      type: object
      properties:
        google:
          allOf:
            - $ref: '#/components/schemas/MerchantCategory'
          description: >-
            Google Merchant product category assigned to this category. You can
            view and download the complete list of Google Merchant product
            categories in <a
            href="https://www.opentiendas.com/google-merchant/taxonomy-with-ids.en-US.xls">english</a>
            or in <a
            href="https://www.opentiendas.com/google-merchant/taxonomy-with-ids.es-ES.xls">spanish</a>
    MerchantCategory:
      type: object
      properties:
        id:
          type: string
          description: ID of the merchant category.
        path:
          type: string
          description: Textual representation of the merchant category hierarchy.
      required:
        - id
    MktStateEnum:
      enum:
        - not_subscribed
        - subscribed
        - unsubscribed
      type: string
      description: |-
        * `not_subscribed` - not_subscribed
        * `subscribed` - subscribed
        * `unsubscribed` - unsubscribed
    ModeEnum:
      enum:
        - upsert
        - delete
      type: string
      description: >-
        * `upsert` - Creates new reference prices and updates existing
        ones.<br>Existing reference prices not included in the payload remain
        unchanged.

        * `delete` - Deletes the provided reference prices from the price list.
    NetGrossAmount:
      type: object
      properties:
        gross:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Gross amount (including taxes).
        net:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Net amount (without taxes).
      required:
        - gross
        - net
    NetGrossTaxAmount:
      type: object
      properties:
        gross:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Gross amount (including taxes).
        net:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Net amount (without taxes).
        tax:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Tax amount included in the gross amount.
      required:
        - gross
        - net
        - tax
    OnlineAvailabilityEnum:
      enum:
        - shipping-and-pickup
        - pickup-only
        - shipping-only
        - offline-only
      type: string
      description: >-
        * `shipping-and-pickup` - The product can be purchased online with home
        delivery or in-store pickup.

        * `pickup-only` - The product can be purchased online only for in-store
        pickup.

        * `shipping-only` - The product can be purchased online only with home
        delivery.

        * `offline-only` - The product cannot be purchased online.
    Order:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          description: Unique identifier of the order.
        payment_status:
          allOf:
            - $ref: '#/components/schemas/PaymentStatusEnum'
          description: |-
            Payment status of the order.

            * `paid` - Paid
            * `unpaid` - Unpaid
        warehouse_release_status:
          allOf:
            - $ref: '#/components/schemas/WarehouseReleaseStatusEnum'
          description: >-
            Indicates whether the order has been released to the warehouse for
            picking/preparation.


            * `not_released` - not_released

            * `partially_released` - partially_released

            * `released` - released
        fulfillment_status:
          allOf:
            - $ref: '#/components/schemas/FulfillmentStatusEnum'
          description: >-
            Indicates whether the merchant has completed the fulfillment process
            for the order items (e.g., shipped them or made them available for
            pickup).<p>Its meaning depends on the delivery method of the
            order:</p><table><tr><th>Fulfillment status</th><th>Shipment
            orders</th><th>Store pickup
            orders</th></tr><tr><td><code>unfulfilled</code></td><td>Nothing
            shipped</td><td>Not ready for
            pickup</td></tr><tr><td><code>partially_fulfilled</code></td><td>Some
            items shipped</td><td>Some items ready for
            pickup</td></tr><tr><td><code>fulfilled</code></td><td>All items
            shipped</td><td>All items ready for pickup</td></tr></table>


            * `unfulfilled` - unfulfilled

            * `partially_fulfilled` - partially_fulfilled

            * `fulfilled` - fulfilled
        created_at:
          type: string
          format: date-time
          description: >-
            Date and time when the order was created in ISO 8601 format (e.g.,
            2023-10-01T12:00:00Z).
        paid_at:
          type: string
          format: date-time
          description: >-
            Date and time when the order was paid in ISO 8601 format (e.g.,
            2023-10-01T12:00:00Z).
        fulfilled_at:
          type: string
          format: date-time
          description: >-
            Date and time in ISO 8601 format (e.g., 2023-10-01T12:00:00Z).
            <p>Its meaning depends on the delivery method of the
            order:</p><ul><li>For shipments, this is the moment when the last
            item was shipped.</li><li>For store pickups, this is the moment when
            the order became ready for pickup.</li></ul>
        canceled_at:
          type: string
          format: date-time
          description: >-
            Date and time in ISO 8601 format (e.g., 2023-10-01T12:00:00Z) when
            the order was canceled. Null if the order has not been canceled.
        cancel_reason:
          type: string
          description: Reason for order cancellation (if applicable).
        estimated_delivery_at:
          type: string
          format: date
          description: >-
            Current estimated moment when the customer is expected to receive
            the order.<ul><li>For shipments, this is the estimated carrier
            delivery date.</li><li>For store pickups, this is the estimated date
            when the order will be ready for pickup.</li></ul>
        initial_estimated_delivery_at:
          type: string
          format: date
          description: >-
            Original estimated delivery moment calculated when the order was
            created. This value does not change even if the delivery estimate is
            later updated.
        delivery_method:
          allOf:
            - $ref: '#/components/schemas/DeliveryMethodEnum'
          description: |-
            Delivery method chosen for the order.

            * `shipment` - Shipment
            * `store_pick_up` - Store pick-up
        locale:
          allOf:
            - $ref: '#/components/schemas/LocaleEnum'
          description: >-
            Locale code in ISO format (e.g., es-ES, en-GB).Format follows ISO
            639-1 (language) and ISO 3166-1 alpha-2 (country) standards.


            * `es-ES` - Spanish (Spain)

            * `ca-ES` - Catalan (Spain)

            * `en-GB` - English (United Kingdom)

            * `fr-FR` - French (France)

            * `it-IT` - Italian (Italy)

            * `pt-PT` - Portuguese (Portugal)

            * `de-DE` - German (Germany)

            * `ru-RU` - Russian (Russia)

            * `nl-NL` - Dutch (Netherlands)

            * `sv-SE` - Swedish (Sweden)

            * `da-DK` - Danish (Denmark)

            * `pl-PL` - Polish (Poland)

            * `el-GR` - Greek (Greece)

            * `hr-HR` - Croatian (Croatia)
        payment_method:
          allOf:
            - $ref: '#/components/schemas/PaymentMethodEnum'
          description: >-
            Payment method used for the order (e.g., 'card', 'paypal',
            'bank_transfer').<p>Payment methods available in OpenTiendas
            dashboard are mapped to API <code>payment_method</code> and
            <code>payment_gateway</code> as
            follows:</p><table><tr><th>OpenTiendas dashboard</th><th>Payment
            method</th><th>Payment gateway</th></tr><tr><td><i>Pago
            negociado</i></td><td><code>agreed_payment</code></td><td><code>manual</code></td></tr><tr><td><i>Pago
            con tarjeta en euros (€) -
            Redsys</i></td><td><code>card</code></td><td><code>redsys</code></td></tr><tr><td><i>Pago
            con tarjeta en libras (£) -
            Redsys</i></td><td><code>card</code></td><td><code>redsys</code></td></tr><tr><td><i>Bizum</i></td><td><code>bizum</code></td><td><code>redsys</code></td></tr><tr><td><i>PayPal</i></td><td><code>paypal</code></td><td><code>paypal</code></td></tr><tr><td><i>Transferencia
            bancaria</i></td><td><code>bank_transfer</code></td><td><code>manual</code></td></tr><tr><td><i>Contrareembolso</i></td><td><code>cash_on_delivery</code></td><td><code>manual</code></td></tr><tr><td><i>Google
            Pay</i></td><td><code>google_pay</code></td><td><code>redsys</code></td></tr><tr><td><i>Apple
            Pay</i></td><td><code>apple_pay</code></td><td><code>redsys</code></td></tr><tr><td><i>SeQura</i></td><td><code>installments</code>
            /
            <code>pay_later</code></td><td><code>sequra</code></td></tr><tr><td><i>Stripe</i></td><td><code>card</code>
            / <code>alipay</code> / <code>amazon_pay</code> /
            <code>apple_pay</code> / <code>cashapp</code> /
            <code>google_pay</code> / <code>apple_pay</code> /
            <code>grabpay</code> / <code>link</code> / <code>paypal</code> /
            <code>revolut_pay</code> / <code>wechat_pay</code> /
            <code>bank_transfer</code> /
            <code>pay_later</code></td><td><code>stripe</code></td></tr><tr><td><i>Adyen</i></td><td><code>card</code></td><td><code>adyen</code></td></tr><tr><td><i>Pago
            en
            tienda</i></td><td><code>in_store</code></td><td><code>manual</code></td></tr></table>


            * `unknown` - Unknown

            * `bank_transfer` - Bank transfer

            * `cash_on_delivery` - Cash on delivery

            * `agreed_payment` - Agreed payment

            * `in_store` - Pay in store

            * `card` - Card

            * `bizum` - Bizum

            * `paypal` - PayPal

            * `installments` - Installments

            * `pay_later` - Pay later

            * `google_pay` - Google Pay

            * `apple_pay` - Apple Pay

            * `alipay` - Alipay

            * `amazon_pay` - Amazon Pay

            * `cashapp` - Cash App

            * `grabpay` - GrabPay

            * `link` - Link

            * `revolut_pay` - Revolut Pay

            * `wechat_pay` - WeChat Pay
        payment_gateway:
          allOf:
            - $ref: '#/components/schemas/PaymentGatewayEnum'
          description: >-
            Payment gateway used for the order (e.g., 'manual', 'redsys',
            'paypal', 'stripe'). <p>For details about payment methods related to
            each payment gateway, see the documentation for the
            <code>payment_method</code> field.</p>


            * `manual` - Manual

            * `redsys` - Redsys

            * `paypal` - PayPal

            * `sequra` - SeQura

            * `adyen` - Adyen

            * `stripe` - Stripe
        total:
          allOf:
            - $ref: '#/components/schemas/NetGrossTaxAmount'
          description: Total amount of the order, including taxes.
        shipping:
          allOf:
            - $ref: '#/components/schemas/NetGrossTaxAmount'
          description: Shipping cost of the order, including taxes.
        fees:
          allOf:
            - $ref: '#/components/schemas/NetGrossTaxAmount'
          description: >-
            Total fees applied to the order (e.g., COD commissions, etc.),
            including taxes.
        line_items:
          type: array
          items:
            $ref: '#/components/schemas/OrderLine'
          description: List of items included in the order.
        bundles:
          type: array
          items:
            $ref: '#/components/schemas/OrderBundle'
          description: >-
            List of bundles in the order. Each bundle describes how multiple
            line_items are grouped together as a bundle. This field is metadata
            only; it does not add new lines or affect totals. All quantities and
            prices are defined in line_items.
        email:
          type: string
          format: email
          readOnly: true
          description: >-
            The customer's email address. This value is unique across the
            platform and can be used as a unique key for identifying customers.
        customer:
          allOf:
            - $ref: '#/components/schemas/User'
          description: >-
            Current customer (contact) resource linked to the order. Its values
            are not immutable and may differ from the customer information
            stored on the order when the purchase was made. Use order-level
            customer and address data for the purchase-time snapshot.
        billing_address:
          allOf:
            - $ref: '#/components/schemas/AddressData'
          description: Billing address of the order.
        shipping_address:
          allOf:
            - $ref: '#/components/schemas/AddressData'
          description: Shipping address of the order.
        is_intra_community_vat_requested:
          type: boolean
          readOnly: true
          description: Whether the customer has requested intra-community VAT exemption.
        is_intra_community_vat_validated:
          type: boolean
          readOnly: true
          description: >-
            Whether the customer's intra-community VAT exemption request has
            been validated.
        customer_note:
          type: string
          description: Customer note or comment included in the order.
        is_b2b:
          type: boolean
          readOnly: true
          description: Indicates whether the order was placed under B2B conditions.
        is_tax_exempt:
          type: boolean
          readOnly: true
          description: Whether the order is exempt from taxes.
        source:
          type: array
          items:
            $ref: '#/components/schemas/SourceEnum'
          description: >-
            List of attributed sources associated with the order, ordered
            chronologically.<br>Each item represents a source through which the
            customer reached the store before the order was created, based on
            the available attribution data.<br>When a customer reaches the store
            through multiple sources over time, more than one source may be
            associated with the order. Values are returned from earliest to most
            recent.<ul><li><code>not_defined</code> - The source is not
            available.</li><li><code>sem</code> - The customer arrived through a
            paid search campaign.</li><li><code>promotion</code> - The order
            comes from a manually created promotional campaign sent by the
            merchant through OpenTiendas.</li><li><code>social</code> - The
            customer arrived through a supported social media
            source.</li><li><code>backoffice</code> - The order was created
            manually by store staff in the
            backoffice.</li><li><code>seestocks</code> - The customer reached
            the store through SeeStocks CSS.</li><li><code>automarketing</code>
            - The order comes from an automated marketing flow in OpenTiendas,
            such as abandoned cart or repurchase reminders, triggered without
            manual intervention.</li></ul>
      required:
        - billing_address
        - cancel_reason
        - canceled_at
        - created_at
        - customer
        - customer_note
        - delivery_method
        - email
        - estimated_delivery_at
        - fees
        - fulfilled_at
        - fulfillment_status
        - id
        - initial_estimated_delivery_at
        - is_b2b
        - is_intra_community_vat_requested
        - is_intra_community_vat_validated
        - is_tax_exempt
        - line_items
        - locale
        - paid_at
        - payment_gateway
        - payment_method
        - payment_status
        - shipping
        - shipping_address
        - source
        - total
        - warehouse_release_status
    OrderBundle:
      type: object
      properties:
        bundle_group_id:
          type: integer
          description: >-
            Identifier of the bundle grouping within the order. Links the bundle
            to its related line_items via line_items.bundle_group_id.
        bundle_id:
          type: integer
          description: >-
            Unique identifier of the bundle product in the store. This
            identifies the bundle definition, unlike bundle_group_id, which
            identifies a specific bundle group within the order.
        display_name:
          type: string
          description: Commercial name of the bundle as shown to the customer.
        quantity:
          type: integer
          description: >-
            Number of bundles purchased. If quantity = N, it means the customer
            purchased N complete bundles. All corresponding units are already
            included in line_items (no additional multiplication required).
        line_item_ids:
          type: array
          items:
            type: integer
          description: >-
            List of line_items.id that belong to the bundle. Can be used to
            group items without relying only on bundle_group_id.
      required:
        - bundle_group_id
        - bundle_id
        - display_name
        - line_item_ids
        - quantity
    OrderLine:
      type: object
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier of the order line.
        product_id:
          type: integer
          description: Unique identifier of the product.
        variant_id:
          type: integer
          description: Unique identifier of the product variant.
        sku:
          type: string
          description: SKU of the product variant.
        ean:
          type: string
          description: EAN of the product variant.
        display_name:
          type: string
          description: Name of the product in the order line.
        tax_rate:
          type: string
          format: decimal
          pattern: ^-?\d{0,3}(?:\.\d{0,2})?$
          description: Tax rate applied to the product in percentage (e.g., 0.21 for 21%).
        quantity:
          type: integer
          description: Quantity of the product in the order line.
        bundle_group_id:
          type: integer
          nullable: true
          description: >-
            Identifier of the bundle grouping this line item belongs to. All
            line items with the same bundle_group_id are part of the same
            bundle. The field is only present for line items included in a
            bundle. This field is metadata only; it does not represent an
            additional order line.
        unit_price:
          allOf:
            - $ref: '#/components/schemas/OrderLineUnitPrice'
          description: Unit price details of the product in the order line.
        discounts_applied:
          type: array
          items:
            $ref: '#/components/schemas/OrderLineAppliedDiscount'
          description: List of discounts applied to the order line.
        additional_services:
          type: array
          items:
            $ref: '#/components/schemas/OrderLineAdditionalService'
          description: >-
            List of additional services purchased for the order line (e.g., gift
            wrapping, extended warranty).
        total:
          allOf:
            - $ref: '#/components/schemas/NetGrossTaxAmount'
          description: >-
            Total price for the order line (quantity multiplied by unit price
            after discounts).
      required:
        - additional_services
        - discounts_applied
        - display_name
        - ean
        - id
        - product_id
        - quantity
        - sku
        - tax_rate
        - total
        - unit_price
        - variant_id
    OrderLineAdditionalService:
      type: object
      properties:
        display_name:
          type: string
          description: Name of the additional service (e.g., 'gift wrapping').
        internal_id:
          type: string
          description: Internal identifier of the additional service.
        quantity:
          type: integer
          description: Quantity of the additional service.
        unit_price:
          allOf:
            - $ref: '#/components/schemas/NetGrossAmount'
          description: Unit price of the additional service.
        tax_rate:
          type: string
          format: decimal
          pattern: ^-?\d{0,3}(?:\.\d{0,2})?$
          description: >-
            Tax rate applied to the additional service in percentage (e.g., 0.21
            for 21%).
      required:
        - display_name
        - internal_id
        - quantity
        - tax_rate
        - unit_price
    OrderLineAppliedDiscount:
      type: object
      properties:
        type:
          allOf:
            - $ref: '#/components/schemas/OrderLineAppliedDiscountTypeEnum'
          description: |-
            Type of the discount.

            * `bundle` - bundle
            * `per_quantity` - per_quantity
            * `voucher` - voucher
            * `automatic` - automatic
        amount:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Amount of the discount.
        description:
          type: string
          description: Description of the discount.
      required:
        - amount
        - description
        - type
    OrderLineAppliedDiscountTypeEnum:
      enum:
        - bundle
        - per_quantity
        - voucher
        - automatic
      type: string
      description: |-
        * `bundle` - bundle
        * `per_quantity` - per_quantity
        * `voucher` - voucher
        * `automatic` - automatic
    OrderLineUnitPrice:
      type: object
      properties:
        list_price:
          allOf:
            - $ref: '#/components/schemas/GrossAmount'
          description: >-
            List price of the product in the order line (price before
            discounts).
        final_price:
          allOf:
            - $ref: '#/components/schemas/NetGrossAmount'
          description: >-
            Final price of the product in the order line (price after
            discounts).
      required:
        - final_price
        - list_price
    PaginatedBrandList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/Brand'
    PaginatedCategoryList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/Category'
    PaginatedJobLogEntryList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/JobLogEntry'
    PaginatedOrderList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/Order'
    PaginatedPriceListList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/PriceList'
    PaginatedPriceListVariantPriceList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/PriceListVariantPrice'
    PaginatedProductList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/Product'
    PaginatedReviewList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/Review'
    PaginatedSupplierList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/Supplier'
    PaginatedUserList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
    PaginatedVariantList:
      type: object
      required:
        - data
        - pagination
      properties:
        pagination:
          type: object
          required:
            - current_page
            - per_page
            - total
            - total_pages
          properties:
            current_page:
              type: integer
              example: 3
              description: The current page number in the paginated response.
            per_page:
              type: integer
              example: 50
              description: The number of items per page in the paginated response.
            total:
              type: integer
              example: 223
              description: The total number of items across all pages.
            total_pages:
              type: integer
              example: 5
              description: The total number of pages available in the paginated response.
            next_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=4
              description: The URL to the next page of results, if available.
            previous_page_url:
              type: string
              nullable: true
              format: uri
              example: https://my_store.opentiendas.app/api/v1/endpoint/?page=2
              description: The URL to the previous page of results, if available.
        data:
          type: array
          items:
            $ref: '#/components/schemas/Variant'
    PatchedBrand:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the brand.
        name:
          type: string
          description: Name of the brand.
        internal_id:
          type: string
          nullable: true
          description: >-
            Internal ID for the brand. This alternative identifier is intended
            for linking it with external systems and managing it through imports
            or API integrations.
        slug:
          type: string
          description: >-
            URL-friendly slug for the brand. If not provided, it will be
            automatically generated from the name. Updating it changes the URL
            and may impact SEO (links and indexed pages). Cache invalidation or
            page refresh may be required for the change to take effect
            immediately.
          pattern: ^[-a-zA-Z0-9_]+$
        delivery_time_in_stock:
          type: integer
          minimum: 0
          description: Estimated delivery time in days when the product is in stock.
        delivery_time_out_of_stock:
          type: integer
          minimum: 0
          description: Estimated delivery time in days when the product is out of stock.
        image_url:
          type: string
          format: uri
          nullable: true
          description: >-
            URL of the brand logo image. If provided, the image will be
            downloaded and saved. The timeout for downloading the image is set
            to 5 seconds.
        translations:
          type: array
          items:
            $ref: '#/components/schemas/BrandTranslation'
    PatchedCategory:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the category.
        internal_id:
          type: string
          nullable: true
          description: >-
            Internal ID for the category. This alternative identifier is
            intended for linking it with external systems and managing it
            through imports or API integrations.
        image_url:
          type: string
          format: uri
          nullable: true
          description: >-
            URL of the category image. If provided, the image will be downloaded
            and saved. The timeout for downloading the image is set to 5
            seconds.
        parent_id:
          type: integer
          nullable: true
          description: >-
            ID of the parent category, if any. Null if this is a top-level
            category.
        status:
          allOf:
            - $ref: '#/components/schemas/Status062Enum'
          description: |-
            Status of the object: 'published' or 'unpublished'.

            * `published` - published
            * `unpublished` - unpublished
        merchant_categories:
          allOf:
            - $ref: '#/components/schemas/MerchantCategories'
          description: Merchant category mappings (e.g., Google taxonomy).
        translations:
          type: array
          items:
            $ref: '#/components/schemas/CategoryTranslation'
    PatchedPriceList:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier of the price list.
        internal_id:
          type: string
          description: >-
            Merchant-defined identifier used to manage the price list through
            imports, exports and the API.
          maxLength: 100
        is_active:
          type: boolean
          description: Indicates whether the price list is active.
        minimum_order_amount:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: >-
            Minimum order amount required for customers using this custom price
            list.
        customers_count:
          type: integer
          readOnly: true
          description: Number of customers currently assigned to this price list.
        variant_prices_count:
          type: integer
          readOnly: true
          description: >-
            Number of product or variant reference prices configured in this
            custom price list.
        global_discount:
          type: string
          format: decimal
          pattern: ^-?\d{0,3}(?:\.\d{0,2})?$
          description: >-
            Global discount percentage applied by the custom price list when
            applicable. Expressed as a percentage value.
        category_discounts:
          type: array
          items:
            $ref: '#/components/schemas/CategoriesPriceList'
          description: >-
            List of category discount rules configured in this custom price
            list. Each rule applies the specified discount percentage to all
            included categories.
        brand_discounts:
          type: array
          items:
            $ref: '#/components/schemas/BrandsPriceList'
          description: >-
            List of brand discount rules configured in this custom price list.
            Each rule applies the specified discount percentage to all included
            brands.
    PatchedReview:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the review.
        locale:
          allOf:
            - $ref: '#/components/schemas/LocaleEnum'
          description: >-
            Locale code in ISO format (e.g., es-ES, en-GB).Format follows ISO
            639-1 (language) and ISO 3166-1 alpha-2 (country) standards.


            * `es-ES` - Spanish (Spain)

            * `ca-ES` - Catalan (Spain)

            * `en-GB` - English (United Kingdom)

            * `fr-FR` - French (France)

            * `it-IT` - Italian (Italy)

            * `pt-PT` - Portuguese (Portugal)

            * `de-DE` - German (Germany)

            * `ru-RU` - Russian (Russia)

            * `nl-NL` - Dutch (Netherlands)

            * `sv-SE` - Swedish (Sweden)

            * `da-DK` - Danish (Denmark)

            * `pl-PL` - Polish (Poland)

            * `el-GR` - Greek (Greece)

            * `hr-HR` - Croatian (Croatia)
        status:
          allOf:
            - $ref: '#/components/schemas/Status062Enum'
          description: |-
            Status of the object: 'published' or 'unpublished'.

            * `published` - published
            * `unpublished` - unpublished
        rating:
          type: integer
          maximum: 5
          minimum: 1
          description: Rating from 1 (minimum) to 5 (maximum).
        content:
          type: string
          description: Content of the review.
        created_at:
          type: string
          format: date-time
          description: >-
            Date and time in ISO 8601 format (e.g., 2023-10-01T12:00:00Z).
            Microseconds are not included.
        reviewer_name:
          type: string
          description: Name of the reviewer.
        reviewer_email:
          type: string
          format: email
          description: Email of the reviewer.
        order_id:
          type: integer
          title: Order number
          nullable: true
          description: >-
            ID of the order associated with the review, if applicable. If a
            review is associated with an order, it will be considered a verified
            review. This verification helps build trust and transparency for
            shoppers browsing your store.
        customer:
          allOf:
            - $ref: '#/components/schemas/User'
          readOnly: true
          description: Customer (contact) who wrote the review.
        customer_id:
          type: integer
          writeOnly: true
          nullable: true
          description: ID of the customer (contact) who wrote the review.
        type:
          allOf:
            - $ref: '#/components/schemas/ReviewTypeEnum'
          description: >-
            Type of review: 'product' for product reviews, 'store' for store
            reviews.


            * `product` - product

            * `store` - store
        product_id:
          type: integer
          nullable: true
          description: ID of the product being reviewed. Only for 'product' reviews.
        product_name:
          type: string
          nullable: true
          readOnly: true
          description: Name of the product being reviewed. Only for 'product' reviews.
        variant_id:
          type: integer
          nullable: true
          description: ID of the variant being reviewed. Only for 'product' reviews.
        variant_name:
          type: string
          nullable: true
          readOnly: true
          description: Name of the variant being reviewed. Only for 'product' reviews.
    PatchedSupplier:
      type: object
      description: Serializer for the Supplier model.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the supplier.
        name:
          type: string
          description: Name of the supplier.
        internal_id:
          type: string
          description: >-
            Internal ID for the supplier. This alternative identifier is
            intended for linking it with external systems and managing it
            through imports or API integrations.
        description:
          type: string
          description: Internal description of the supplier.
    PaymentGatewayEnum:
      enum:
        - manual
        - redsys
        - paypal
        - sequra
        - adyen
        - stripe
      type: string
      description: |-
        * `manual` - Manual
        * `redsys` - Redsys
        * `paypal` - PayPal
        * `sequra` - SeQura
        * `adyen` - Adyen
        * `stripe` - Stripe
    PaymentMethodEnum:
      enum:
        - unknown
        - bank_transfer
        - cash_on_delivery
        - agreed_payment
        - in_store
        - card
        - bizum
        - paypal
        - installments
        - pay_later
        - google_pay
        - apple_pay
        - alipay
        - amazon_pay
        - cashapp
        - grabpay
        - link
        - revolut_pay
        - wechat_pay
      type: string
      description: |-
        * `unknown` - Unknown
        * `bank_transfer` - Bank transfer
        * `cash_on_delivery` - Cash on delivery
        * `agreed_payment` - Agreed payment
        * `in_store` - Pay in store
        * `card` - Card
        * `bizum` - Bizum
        * `paypal` - PayPal
        * `installments` - Installments
        * `pay_later` - Pay later
        * `google_pay` - Google Pay
        * `apple_pay` - Apple Pay
        * `alipay` - Alipay
        * `amazon_pay` - Amazon Pay
        * `cashapp` - Cash App
        * `grabpay` - GrabPay
        * `link` - Link
        * `revolut_pay` - Revolut Pay
        * `wechat_pay` - WeChat Pay
    PaymentStatusEnum:
      enum:
        - paid
        - unpaid
      type: string
      description: |-
        * `paid` - Paid
        * `unpaid` - Unpaid
    PreferredLocaleEnum:
      enum:
        - es-ES
        - ca-ES
        - en-GB
        - fr-FR
        - it-IT
        - pt-PT
        - de-DE
        - ru-RU
        - nl-NL
        - sv-SE
        - da-DK
        - pl-PL
        - el-GR
        - hr-HR
      type: string
      description: |-
        * `es-ES` - Spanish (Spain)
        * `ca-ES` - Catalan (Spain)
        * `en-GB` - English (United Kingdom)
        * `fr-FR` - French (France)
        * `it-IT` - Italian (Italy)
        * `pt-PT` - Portuguese (Portugal)
        * `de-DE` - German (Germany)
        * `ru-RU` - Russian (Russia)
        * `nl-NL` - Dutch (Netherlands)
        * `sv-SE` - Swedish (Sweden)
        * `da-DK` - Danish (Denmark)
        * `pl-PL` - Polish (Poland)
        * `el-GR` - Greek (Greece)
        * `hr-HR` - Croatian (Croatia)
    PriceList:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier of the price list.
        internal_id:
          type: string
          description: >-
            Merchant-defined identifier used to manage the price list through
            imports, exports and the API.
          maxLength: 100
        is_active:
          type: boolean
          description: Indicates whether the price list is active.
        minimum_order_amount:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: >-
            Minimum order amount required for customers using this custom price
            list.
        customers_count:
          type: integer
          readOnly: true
          description: Number of customers currently assigned to this price list.
        variant_prices_count:
          type: integer
          readOnly: true
          description: >-
            Number of product or variant reference prices configured in this
            custom price list.
        global_discount:
          type: string
          format: decimal
          pattern: ^-?\d{0,3}(?:\.\d{0,2})?$
          description: >-
            Global discount percentage applied by the custom price list when
            applicable. Expressed as a percentage value.
        category_discounts:
          type: array
          items:
            $ref: '#/components/schemas/CategoriesPriceList'
          description: >-
            List of category discount rules configured in this custom price
            list. Each rule applies the specified discount percentage to all
            included categories.
        brand_discounts:
          type: array
          items:
            $ref: '#/components/schemas/BrandsPriceList'
          description: >-
            List of brand discount rules configured in this custom price list.
            Each rule applies the specified discount percentage to all included
            brands.
      required:
        - brand_discounts
        - category_discounts
        - customers_count
        - global_discount
        - id
        - internal_id
        - is_active
        - variant_prices_count
    PriceListVariantPrice:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        variant_id:
          type: integer
          description: ID of the variant to which this price list applies.
        variant_internal_id:
          type: string
          readOnly: true
          description: Internal ID of the variant to which this price list applies.
        product_id:
          type: integer
          readOnly: true
          description: >-
            ID of the product linked to the variant to which this price list
            applies.
        product_internal_id:
          type: string
          readOnly: true
          description: >-
            Internal ID of the product linked to the variant to which this price
            list applies.
        ean:
          type: string
          readOnly: true
          description: EAN of the variant to which this price list applies.
        sku:
          type: string
          readOnly: true
          description: SKU of the variant to which this price list applies.
        supplier_id:
          type: integer
          readOnly: true
          description: >-
            ID of the supplier linked to the product of the variant to which
            this price list applies.
        supplier_internal_id:
          type: string
          readOnly: true
          description: >-
            Internal ID of the supplier linked to the product of the variant to
            which this price list applies.
        display_name:
          type: string
          readOnly: true
          description: >-
            Display name of the variant in the the store's primary locale (e.g.
            es-ES). Informational field only.
        price:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Price of the variant when this price list is applied.
        min_quantity:
          type: integer
          maximum: 9999
          minimum: 1
          nullable: true
          description: >-
            Minimum quantity of the variant that must be purchased for this
            price list to apply. If not specified, the price list applies to any
            quantity.
        quantity_factor:
          type: integer
          maximum: 9999
          minimum: 1
          nullable: true
          description: >-
            Quantity must be bought in multiples of this value (step) when this
            price list is applied. If not specified, the quantity factor
            defaults to 1.
      required:
        - display_name
        - ean
        - price
        - product_id
        - product_internal_id
        - sku
        - supplier_id
        - supplier_internal_id
        - variant_id
        - variant_internal_id
    PriceListVariantPriceUpdate:
      type: object
      properties:
        variant_id:
          type: integer
          description: >-
            ID of the variant to which this price list applies. Used for
            matching when the <code>match_by</code> option is set to
            <code>variant_id</code>.
        variant_internal_id:
          type: string
          description: >-
            Internal ID of the variant to which this price list applies. Used
            for matching when the <code>match_by</code> option is set to
            <code>variant_internal_id</code>.
        ean:
          type: string
          description: >-
            EAN of the variant to which this price list applies. Used for
            matching when the <code>match_by</code> option is set to
            <code>ean</code>.
        sku:
          type: string
          description: >-
            Stock Keeping Unit (SKU) of the variant to which this price list
            applies. Used for matching when the <code>match_by</code> option is
            set to <code>sku_supplier</code>. It will not be stored in the
            database. Must be provided alongside
            <code>supplier_internal_id</code> for correct matching.
        supplier_internal_id:
          type: string
          description: >-
            Internal ID of the supplier for the variant to which this price list
            applies. Used for matching when the <code>match_by</code> option is
            set to <code>sku_supplier</code>. It will not be stored in the
            database. Must be provided alongside <code>sku</code> for correct
            matching.
        price:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: >-
            Price of the variant when this price list is
            applied.<ul><li>Required for <code>upsert</code>
            mode.</li><li>Ignored or not required for <code>delete</code>
            mode.</li><li>Only <code>EUR</code> is supported.</li></ul>
        min_quantity:
          type: integer
          maximum: 9999
          minimum: 1
          nullable: true
          description: >-
            Minimum quantity of the variant that must be purchased for this
            price list to apply. If not specified, the price list applies to any
            quantity.<ul><li>If omitted, the value is not modified in
            <code>upsert</code> mode.</li><li>If set to <code>null</code>, the
            price list override is cleared and the default variant value is
            used.</li></ul>
        quantity_factor:
          type: integer
          maximum: 9999
          minimum: 1
          nullable: true
          description: >-
            Quantity must be bought in multiples of this value (step) when this
            price list is applied. If not specified, the quantity factor
            defaults to 1.<ul><li>If omitted, the value is not modified in
            <code>upsert</code> mode.</li><li>If set to <code>null</code>, the
            price list override is cleared and the default variant value is
            used.</li></ul>
    Product:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the product.
        internal_id:
          type: string
          nullable: true
          description: >-
            Internal ID for the product. This alternative identifier is intended
            for linking it with external systems and managing it through imports
            or API integrations.
        created_at:
          type: string
          format: date-time
          readOnly: true
          description: >-
            Date and time when the product was created, in ISO 8601 format
            (e.g., 2023-10-01T12:00:00Z).
        updated_at:
          type: string
          format: date-time
          readOnly: true
          description: >-
            Date and time when the product was last updated, in ISO 8601 format
            (e.g., 2023-10-01T12:00:00Z). This value reflects product-level
            changes and also includes relevant variant-related changes, such as
            pricing or stock updates.
        product_structure:
          allOf:
            - $ref: '#/components/schemas/ProductStructureEnum'
          description: |-
            Product structure type: 'simple' or 'with-variants'.

            * `with-variants` - with-variants
            * `simple` - simple
        status:
          allOf:
            - $ref: '#/components/schemas/Status062Enum'
          description: |-
            Status of the object: 'published' or 'unpublished'.

            * `published` - published
            * `unpublished` - unpublished
        product_kind:
          allOf:
            - $ref: '#/components/schemas/ProductKindEnum'
          description: >-
            Defines whether the product is a tangible good ('physical') or a
            non-shippable service ('service').


            * `physical` - physical

            * `service` - service
        stock_management:
          allOf:
            - $ref: '#/components/schemas/StockManagementEnum'
          description: >-
            Stock management setting configured for the product. Determines how
            stock availability affects whether the product can be purchased.


            * `default` - Uses the store default stock management setting.

            * `ignore-stock` - Ignores stock when determining whether the
            product can be purchased.

            * `deny-without-own-stock` - The product can only be purchased if it
            has available own stock.

            * `deny-without-own-or-supplier-stock` - The product can only be
            purchased if it has available own stock or supplier stock.

            * `allow-backorder` - The product can be purchased even when no
            stock is available.
        effective_stock_management:
          allOf:
            - $ref: '#/components/schemas/EffectiveStockManagementEnum'
          readOnly: true
          description: >-
            Computed effective stock management setting for the product.
            Represents the resolved value after applying the store default
            configuration when applicable.


            * `ignore-stock` - Ignores stock when determining whether the
            product can be purchased.

            * `deny-without-own-stock` - The product can only be purchased if it
            has available own stock.

            * `deny-without-own-or-supplier-stock` - The product can only be
            purchased if it has available own stock or supplier stock.

            * `allow-backorder` - The product can be purchased even when no
            stock is available.
        online_availability:
          allOf:
            - $ref: '#/components/schemas/OnlineAvailabilityEnum'
          description: >-
            Online availability setting configured for the product. Determines
            if the product can be purchased online and whether it supports
            shipping, in-store pickup, or both.


            * `shipping-and-pickup` - The product can be purchased online with
            home delivery or in-store pickup.

            * `pickup-only` - The product can be purchased online only for
            in-store pickup.

            * `shipping-only` - The product can be purchased online only with
            home delivery.

            * `offline-only` - The product cannot be purchased online.
        model_code:
          type: string
          description: >-
            Code identifying the base model or family grouping all product
            variants (e.g., size, color).
        tax_category:
          allOf:
            - $ref: '#/components/schemas/TaxCategoryEnum'
          description: >-
            Tax category of the product: 'standard', 'reduced', 'super-reduced'
            or 'zero'.


            * `standard` - standard

            * `reduced` - reduced

            * `super-reduced` - super-reduced

            * `zero` - zero
        supplier:
          allOf:
            - $ref: '#/components/schemas/Supplier'
          readOnly: true
        supplier_id:
          type: integer
          writeOnly: true
          description: >-
            ID of the supplier associated with the product. Must reference an
            existing supplier.
        brand:
          allOf:
            - $ref: '#/components/schemas/Brand'
          readOnly: true
        brand_id:
          type: integer
          writeOnly: true
          description: >-
            ID of the brand associated with the product. Must reference an
            existing brand.
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
          readOnly: true
        category_ids:
          type: array
          items:
            type: integer
            writeOnly: true
          writeOnly: true
          description: >-
            List of category IDs assigned to the product. Each ID must reference
            an existing category. The order of the IDs is significant. The first
            category is treated as the primary category and is used for site
            navigation and product ordering. The remaining categories act as
            secondary classifications to improve product discovery from
            different sections of the catalog. When updating a product, the
            provided list replaces the product's existing category assignments.
        images:
          type: array
          items:
            $ref: '#/components/schemas/ProductImage'
        variants_count:
          type: integer
          readOnly: true
          description: Number of variants available for the product.
        variants:
          type: array
          items:
            $ref: '#/components/schemas/Variant'
          readOnly: true
          description: >-
            List of sellable variants of the product. Only included if
            explicitly requested via the 'includes' parameter. Use
            /products/{id}/variants/ to retrieve the full paginated list with
            specific fields and includes.
        translations:
          type: array
          items:
            $ref: '#/components/schemas/ProductTranslation'
          description: >-
            List of translations for the product. Each translation includes
            locale-specific information such as name, description, and URL.
      required:
        - brand
        - brand_id
        - categories
        - category_ids
        - created_at
        - effective_stock_management
        - id
        - product_kind
        - product_structure
        - status
        - supplier
        - tax_category
        - translations
        - updated_at
        - variants
        - variants_count
    ProductBulkUpsert:
      type: object
      properties:
        products:
          type: array
          items:
            $ref: '#/components/schemas/ProductWrite'
          writeOnly: true
          description: >-
            <p>List of products to create or update. Each product must include
            the field used for matching, as defined by
            <code>options.match_by</code>:</p><ul><li>If match_by is id,
            existing products are matched by id.</li><li>If match_by is
            internal_id, existing products are matched by
            internal_id.</li><li>If no existing product is found, a new product
            is created.</li></ul>
        options:
          allOf:
            - $ref: '#/components/schemas/ProductBulkUpsertOptions'
          description: >-
            Options for bulk upsert operation. Must include the 'match_by' field
            to specify how products should be matched for updates.
      required:
        - options
        - products
    ProductBulkUpsertErrorResponse:
      type: object
      properties:
        detail:
          type: string
          description: Error details explaining why the request is invalid.
      required:
        - detail
    ProductBulkUpsertOptions:
      type: object
      properties:
        match_by:
          allOf:
            - $ref: '#/components/schemas/ProductBulkUpsertOptionsMatchByEnum'
          description: >-
            <p>Field used to match existing products and variants during the
            upsert operation. Must be one of <code>id</code>,
            <code>internal_id</code>.</p><p>If a matching record is found, it is
            updated. If no match is found, a new record is created.</p>


            * `id` - matches records using the platform identifier

            * `internal_id` - matches records using the custom internal_id
            provided in the payload
      required:
        - match_by
    ProductBulkUpsertOptionsMatchByEnum:
      enum:
        - id
        - internal_id
      type: string
      description: >-
        * `id` - matches records using the platform identifier

        * `internal_id` - matches records using the custom internal_id provided
        in the payload
    ProductImage:
      type: object
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the product image.
        fullsize:
          type: string
          format: uri
          readOnly: true
          description: URL of the product image.
        url:
          type: string
          format: uri
          writeOnly: true
          description: >-
            Public URL of the product image. If the URL is new for the product,
            the image will be downloaded and stored. The download request has a
            timeout of 5 seconds.
        position:
          type: integer
          description: Position of the image within the product's image gallery.
      required:
        - fullsize
        - id
        - position
        - url
    ProductKindEnum:
      enum:
        - physical
        - service
      type: string
      description: |-
        * `physical` - physical
        * `service` - service
    ProductStructureEnum:
      enum:
        - with-variants
        - simple
      type: string
      description: |-
        * `with-variants` - with-variants
        * `simple` - simple
    ProductTranslation:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        locale:
          allOf:
            - $ref: '#/components/schemas/LocaleEnum'
          description: >-
            Locale code in ISO format (e.g., es-ES, en-GB).Format follows ISO
            639-1 (language) and ISO 3166-1 alpha-2 (country) standards.


            * `es-ES` - Spanish (Spain)

            * `ca-ES` - Catalan (Spain)

            * `en-GB` - English (United Kingdom)

            * `fr-FR` - French (France)

            * `it-IT` - Italian (Italy)

            * `pt-PT` - Portuguese (Portugal)

            * `de-DE` - German (Germany)

            * `ru-RU` - Russian (Russia)

            * `nl-NL` - Dutch (Netherlands)

            * `sv-SE` - Swedish (Sweden)

            * `da-DK` - Danish (Denmark)

            * `pl-PL` - Polish (Poland)

            * `el-GR` - Greek (Greece)

            * `hr-HR` - Croatian (Croatia)
        url:
          type: string
          nullable: true
          readOnly: true
          description: URL of the product in the frontstore for the specified locale.
        name:
          type: string
          description: Name of the product in the specified locale.
        description:
          type: string
          description: Description of the product in the specified locale.
        body_html:
          type: string
          description: HTML body content of the product in the specified locale.
        long_name:
          type: string
          description: Long name of the product in the specified locale.
        meta_title:
          type: string
          description: Meta title for the product in the specified locale.
        meta_description:
          type: string
          description: Meta description for the product in the specified locale.
        slug_base:
          type: string
          description: >-
            Editable part of the slug. Combined with the immutable suffix, it
            forms the complete slug.<p>Updating it changes the URL and may
            impact SEO (links and indexed pages). Cache invalidation or page
            refresh may be required for the change to take effect
            immediately.</p>
          pattern: ^[-a-zA-Z0-9_]+$
        slug:
          type: string
          readOnly: true
          description: >-
            Slug for the product, used in URLs. This value includes an immutable
            suffix.
          pattern: ^[-a-zA-Z0-9_]+$
      required:
        - locale
        - name
        - slug
        - url
    ProductWrite:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        id:
          type: integer
          description: >-
            ID of the product. Required when <code>options.match_by</code> is
            'id' for updating an existing product.
        internal_id:
          type: string
          nullable: true
          description: >-
            Custom alternative identifier for the product, typically used to map
            the product to records in other systems such as ERPs or PIMs. Must
            be unique among products. Required when
            <code>options.match_by</code> is 'internal_id' to update an existing
            product.
        created_at:
          type: string
          format: date-time
          readOnly: true
          description: >-
            Date and time when the product was created, in ISO 8601 format
            (e.g., 2023-10-01T12:00:00Z).
        updated_at:
          type: string
          format: date-time
          readOnly: true
          description: >-
            Date and time when the product was last updated, in ISO 8601 format
            (e.g., 2023-10-01T12:00:00Z). This value reflects product-level
            changes and also includes relevant variant-related changes, such as
            pricing or stock updates.
        product_structure:
          allOf:
            - $ref: '#/components/schemas/ProductStructureEnum'
          description: >-
            Product structure type: 'simple' or 'with-variants'. For updates,
            this field will be ignored and the existing product structure will
            be kept.


            * `with-variants` - with-variants

            * `simple` - simple
        status:
          allOf:
            - $ref: '#/components/schemas/Status062Enum'
          description: >-
            Status of the product: 'published' or 'unpublished'. For
            <code>simple</code> products, product and variant status are kept in
            sync. If both values are provided and differ, the variant status
            takes precedence and is applied to the product.


            * `published` - published

            * `unpublished` - unpublished
        product_kind:
          allOf:
            - $ref: '#/components/schemas/ProductKindEnum'
          description: >-
            Defines whether the product is a tangible good ('physical') or a
            non-shippable service ('service').


            * `physical` - physical

            * `service` - service
        stock_management:
          allOf:
            - $ref: '#/components/schemas/StockManagementEnum'
          description: >-
            Stock management setting configured for the product. Determines how
            stock availability affects whether the product can be purchased.


            * `default` - Uses the store default stock management setting.

            * `ignore-stock` - Ignores stock when determining whether the
            product can be purchased.

            * `deny-without-own-stock` - The product can only be purchased if it
            has available own stock.

            * `deny-without-own-or-supplier-stock` - The product can only be
            purchased if it has available own stock or supplier stock.

            * `allow-backorder` - The product can be purchased even when no
            stock is available.
        effective_stock_management:
          allOf:
            - $ref: '#/components/schemas/EffectiveStockManagementEnum'
          readOnly: true
          description: >-
            Computed effective stock management setting for the product.
            Represents the resolved value after applying the store default
            configuration when applicable.


            * `ignore-stock` - Ignores stock when determining whether the
            product can be purchased.

            * `deny-without-own-stock` - The product can only be purchased if it
            has available own stock.

            * `deny-without-own-or-supplier-stock` - The product can only be
            purchased if it has available own stock or supplier stock.

            * `allow-backorder` - The product can be purchased even when no
            stock is available.
        online_availability:
          allOf:
            - $ref: '#/components/schemas/OnlineAvailabilityEnum'
          description: >-
            Online availability setting configured for the product. Determines
            if the product can be purchased online and whether it supports
            shipping, in-store pickup, or both.


            * `shipping-and-pickup` - The product can be purchased online with
            home delivery or in-store pickup.

            * `pickup-only` - The product can be purchased online only for
            in-store pickup.

            * `shipping-only` - The product can be purchased online only with
            home delivery.

            * `offline-only` - The product cannot be purchased online.
        model_code:
          type: string
          description: >-
            Code identifying the base model or family grouping all product
            variants (e.g., size, color).
        tax_category:
          allOf:
            - $ref: '#/components/schemas/TaxCategoryEnum'
          description: >-
            Tax category of the product: 'standard', 'reduced', 'super-reduced'
            or 'zero'.


            * `standard` - standard

            * `reduced` - reduced

            * `super-reduced` - super-reduced

            * `zero` - zero
        supplier:
          allOf:
            - $ref: '#/components/schemas/Supplier'
          readOnly: true
        supplier_id:
          type: integer
          writeOnly: true
          description: >-
            ID of the supplier associated with the product. Must reference an
            existing supplier.
        brand:
          allOf:
            - $ref: '#/components/schemas/Brand'
          readOnly: true
        brand_id:
          type: integer
          writeOnly: true
          description: >-
            ID of the brand associated with the product. Must reference an
            existing brand.
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
          readOnly: true
        category_ids:
          type: array
          items:
            type: integer
            writeOnly: true
          writeOnly: true
          description: >-
            List of category IDs assigned to the product. Each ID must reference
            an existing category. The order of the IDs is significant. The first
            category is treated as the primary category and is used for site
            navigation and product ordering. The remaining categories act as
            secondary classifications to improve product discovery from
            different sections of the catalog. When updating a product, the
            provided list replaces the product's existing category assignments.
        images:
          type: array
          items:
            $ref: '#/components/schemas/ProductImage'
          description: >-
            <p>List of images to import for the product.</p><p>When an image is
            imported, OpenTiendas stores the original source URL used for the
            import. During subsequent updates, the system checks whether an
            image with the same source URL has already been imported for that
            product. If the source URL is already known, the image is not
            imported again. If the source URL is new, the image is downloaded
            and added to the product.</p><p>This endpoint allows adding new
            images, but it does not remove existing images.</p>
        variants_count:
          type: integer
          readOnly: true
          description: Number of variants available for the product.
        variants:
          type: array
          items:
            $ref: '#/components/schemas/Variant'
          description: >-
            <p>Each variant in the payload is processed as an upsert: it may
            result in either the creation of a new variant or the update of an
            existing one, using the same matching rule defined by
            <code>options.match_by</code>.</p><p>This endpoint does not delete
            existing variants. Variants not included in the request remain
            unchanged.</p><p>For products with <code>product_structure</code>
            set to 'simple', only a single variant is allowed. Attempting to add
            additional variants will result in an error.</p>
        translations:
          type: array
          items:
            $ref: '#/components/schemas/ProductTranslation'
          description: >-
            List of locale-specific translations to create or update for the
            product. Each translation may include fields such as the name,
            description, long name, HTML body content, and SEO metadata.
      required:
        - brand
        - brand_id
        - categories
        - category_ids
        - created_at
        - effective_stock_management
        - product_kind
        - product_structure
        - status
        - supplier
        - tax_category
        - translations
        - updated_at
        - variants
        - variants_count
    RefundTypeEnum:
      enum:
        - full
      type: string
      description: '* `full` - The item can be refunded for the full monetary amount.'
    ReturnFeesEnum:
      enum:
        - free
        - customer_pays
      type: string
      description: |-
        * `free` - The merchant covers the return cost.
        * `customer_pays` - The customer pays for the return shipping.
    ReturnLabelSourceEnum:
      enum:
        - customer_responsibility
        - download_and_print
        - in_box
      type: string
      description: >-
        * `customer_responsibility` - The customer arranges the return label.

        * `download_and_print` - The customer downloads and prints the return
        label.

        * `in_box` - The return label is included inside the original package.
    ReturnMethodEnum:
      enum:
        - by_mail
        - in_store
      type: string
      description: |-
        * `by_mail` - Returns are handled via shipping or courier.
        * `in_store` - Returns are handled in a physical store.
    ReturnPolicy:
      type: object
      properties:
        applicable_countries:
          type: array
          items:
            type: string
          description: >-
            List of countries where this return policy applies. Each value must
            be a two-letter ISO 3166-1 alpha-2 country code (e.g.
            <code>ES</code>, <code>DE</code>).<p>These countries typically
            represent where products are sold and returned from.</p>
        return_policy_country:
          type: string
          description: >-
            Country (two-letter ISO 3166-1 alpha-2 country code) that defines
            the return policy context. This is usually the store's primary
            country and may be used by external services as the base reference
            for the policy.
        return_days:
          type: integer
          description: Number of days during which customers can request a return.
        return_method:
          allOf:
            - $ref: '#/components/schemas/ReturnMethodEnum'
          description: |-
            Method used by customers to return products.

            * `by_mail` - Returns are handled via shipping or courier.
            * `in_store` - Returns are handled in a physical store.
        return_fees:
          allOf:
            - $ref: '#/components/schemas/ReturnFeesEnum'
          description: |-
            Indicates who is responsible for the return shipping cost.

            * `free` - The merchant covers the return cost.
            * `customer_pays` - The customer pays for the return shipping.
        refund_type:
          allOf:
            - $ref: '#/components/schemas/RefundTypeEnum'
          description: >-
            Type of refund applied when a return is accepted.<p>Currently, only
            full refunds are supported (<code>full</code>).</p>


            * `full` - The item can be refunded for the full monetary amount.
        return_label_source:
          allOf:
            - $ref: '#/components/schemas/ReturnLabelSourceEnum'
          description: >-
            Specifies how the customer obtains the return shipping label.


            * `customer_responsibility` - The customer arranges the return
            label.

            * `download_and_print` - The customer downloads and prints the
            return label.

            * `in_box` - The return label is included inside the original
            package.
        item_condition:
          allOf:
            - $ref: '#/components/schemas/ItemConditionEnum'
          description: >-
            Condition of the product required for returns.<p>Currently, only
            <code>new</code> is supported, meaning products must be returned
            unused and in their original condition.</p>


            * `new` - The item is in new condition.
      required:
        - applicable_countries
        - item_condition
        - refund_type
        - return_days
        - return_fees
        - return_label_source
        - return_method
        - return_policy_country
    Review:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the review.
        locale:
          allOf:
            - $ref: '#/components/schemas/LocaleEnum'
          description: >-
            Locale code in ISO format (e.g., es-ES, en-GB).Format follows ISO
            639-1 (language) and ISO 3166-1 alpha-2 (country) standards.


            * `es-ES` - Spanish (Spain)

            * `ca-ES` - Catalan (Spain)

            * `en-GB` - English (United Kingdom)

            * `fr-FR` - French (France)

            * `it-IT` - Italian (Italy)

            * `pt-PT` - Portuguese (Portugal)

            * `de-DE` - German (Germany)

            * `ru-RU` - Russian (Russia)

            * `nl-NL` - Dutch (Netherlands)

            * `sv-SE` - Swedish (Sweden)

            * `da-DK` - Danish (Denmark)

            * `pl-PL` - Polish (Poland)

            * `el-GR` - Greek (Greece)

            * `hr-HR` - Croatian (Croatia)
        status:
          allOf:
            - $ref: '#/components/schemas/Status062Enum'
          description: |-
            Status of the object: 'published' or 'unpublished'.

            * `published` - published
            * `unpublished` - unpublished
        rating:
          type: integer
          maximum: 5
          minimum: 1
          description: Rating from 1 (minimum) to 5 (maximum).
        content:
          type: string
          description: Content of the review.
        created_at:
          type: string
          format: date-time
          description: >-
            Date and time in ISO 8601 format (e.g., 2023-10-01T12:00:00Z).
            Microseconds are not included.
        reviewer_name:
          type: string
          description: Name of the reviewer.
        reviewer_email:
          type: string
          format: email
          description: Email of the reviewer.
        order_id:
          type: integer
          title: Order number
          nullable: true
          description: >-
            ID of the order associated with the review, if applicable. If a
            review is associated with an order, it will be considered a verified
            review. This verification helps build trust and transparency for
            shoppers browsing your store.
        customer:
          allOf:
            - $ref: '#/components/schemas/User'
          readOnly: true
          description: Customer (contact) who wrote the review.
        customer_id:
          type: integer
          writeOnly: true
          nullable: true
          description: ID of the customer (contact) who wrote the review.
        type:
          allOf:
            - $ref: '#/components/schemas/ReviewTypeEnum'
          description: >-
            Type of review: 'product' for product reviews, 'store' for store
            reviews.


            * `product` - product

            * `store` - store
        product_id:
          type: integer
          nullable: true
          description: ID of the product being reviewed. Only for 'product' reviews.
        product_name:
          type: string
          nullable: true
          readOnly: true
          description: Name of the product being reviewed. Only for 'product' reviews.
        variant_id:
          type: integer
          nullable: true
          description: ID of the variant being reviewed. Only for 'product' reviews.
        variant_name:
          type: string
          nullable: true
          readOnly: true
          description: Name of the variant being reviewed. Only for 'product' reviews.
      required:
        - content
        - customer
        - id
        - locale
        - product_name
        - reviewer_email
        - type
        - variant_name
    ReviewTypeEnum:
      enum:
        - product
        - store
      type: string
      description: |-
        * `product` - product
        * `store` - store
    SellablePricingPlanBulkUpdate:
      type: object
      properties:
        prices:
          type: array
          items:
            $ref: '#/components/schemas/PriceListVariantPriceUpdate'
          writeOnly: true
          description: >-
            Array of reference prices to process. <b>The array cannot be
            empty.</b> Each object must include the field used for matching, as
            defined by <code>options.match_by</code>.
        options:
          allOf:
            - $ref: '#/components/schemas/SellablePricingPlanBulkUpdateOptions'
          description: Options for the bulk update operation.
      required:
        - options
        - prices
    SellablePricingPlanBulkUpdateErrorResponse:
      type: object
      properties:
        detail:
          type: string
          description: Error details explaining why the request is invalid.
      required:
        - detail
    SellablePricingPlanBulkUpdateOptions:
      type: object
      properties:
        match_by:
          allOf:
            - $ref: >-
                #/components/schemas/SellablePricingPlanBulkUpdateOptionsMatchByEnum
          description: >-
            <p>Field used to match existing variants.</p><p>Supported values:
            <code>variant_id</code>, <code>variant_internal_id</code>,
            <code>ean</code>, <code>sku_supplier</code>.</p><p>When using
            <code>sku_supplier</code>, each price must include both
            <code>sku</code> and <code>supplier_internal_id</code>.</p>


            * `variant_id` - matches variants using the OpenTiendas platform
            identifier.

            * `variant_internal_id` - matches variants using the custom internal
            identifier provided in the payload.

            * `ean` - matches variants using the EAN code provided in the
            payload.

            * `sku_supplier` - matches variants using the combination of SKU and
            supplier internal ID provided in the payload.
        mode:
          $ref: '#/components/schemas/ModeEnum'
      required:
        - match_by
        - mode
    SellablePricingPlanBulkUpdateOptionsMatchByEnum:
      enum:
        - variant_id
        - variant_internal_id
        - ean
        - sku_supplier
      type: string
      description: >-
        * `variant_id` - matches variants using the OpenTiendas platform
        identifier.

        * `variant_internal_id` - matches variants using the custom internal
        identifier provided in the payload.

        * `ean` - matches variants using the EAN code provided in the payload.

        * `sku_supplier` - matches variants using the combination of SKU and
        supplier internal ID provided in the payload.
    SellableProductBulkUpdate:
      type: object
      properties:
        variants:
          type: array
          items:
            $ref: '#/components/schemas/Variant'
          writeOnly: true
          description: >-
            <p>List of variants to update. Each variant must include the field
            used for matching, as defined by
            <code>options.match_by</code>:</p><ul><li>If match_by is id,
            existing variants are matched by id.</li><li>If match_by is
            internal_id, existing variants are matched by
            internal_id.</li><li>If match_by is ean, existing variants are
            matched by EAN.</li><li>If match_by is sku_supplier, existing
            variants are matched by the combination of SKU and supplier internal
            ID.</li><li>Only existing variants will be updated. New variants
            cannot be created through this endpoint.</li></ul>
        options:
          allOf:
            - $ref: '#/components/schemas/SellableProductBulkUpdateOptions'
          description: >-
            Options for bulk update operation. Must include the 'match_by' field
            to specify how variants should be matched for updates.
      required:
        - options
        - variants
    SellableProductBulkUpdateErrorResponse:
      type: object
      properties:
        detail:
          type: string
          description: Error details explaining why the request is invalid.
      required:
        - detail
    SellableProductBulkUpdateOptions:
      type: object
      properties:
        match_by:
          allOf:
            - $ref: '#/components/schemas/SellableProductBulkUpdateOptionsMatchByEnum'
          description: >-
            <p>Field used to match existing variants during the update
            operation. Must be one of <code>id</code>, <code>internal_id</code>,
            <code>ean</code>, <code>sku_supplier</code>.</p><p>If a matching
            record is found, it is updated.</p>


            * `id` - matches records using the platform identifier

            * `internal_id` - matches records using the custom internal_id
            provided in the payload

            * `ean` - matches records using the EAN code provided in the payload

            * `sku_supplier` - matches records using the combination of SKU and
            supplier internal ID provided in the payload
      required:
        - match_by
    SellableProductBulkUpdateOptionsMatchByEnum:
      enum:
        - id
        - internal_id
        - ean
        - sku_supplier
      type: string
      description: >-
        * `id` - matches records using the platform identifier

        * `internal_id` - matches records using the custom internal_id provided
        in the payload

        * `ean` - matches records using the EAN code provided in the payload

        * `sku_supplier` - matches records using the combination of SKU and
        supplier internal ID provided in the payload
    SizesGuideFile:
      type: object
      properties:
        name:
          type: string
          description: Name of the size guide file as displayed to users.
        url:
          type: string
          nullable: true
          readOnly: true
          description: URL of the size guide file for the brand and locale.
      required:
        - url
    SourceEnum:
      enum:
        - not_defined
        - organic
        - sem
        - promotion
        - social
        - backoffice
        - seestocks
        - automarketing
      type: string
      description: |-
        * `not_defined` - not_defined
        * `organic` - organic
        * `sem` - sem
        * `promotion` - promotion
        * `social` - social
        * `backoffice` - backoffice
        * `seestocks` - seestocks
        * `automarketing` - automarketing
    Status062Enum:
      enum:
        - published
        - unpublished
      type: string
      description: |-
        * `published` - published
        * `unpublished` - unpublished
    StockManagementEnum:
      enum:
        - default
        - ignore-stock
        - deny-without-own-stock
        - deny-without-own-or-supplier-stock
        - allow-backorder
      type: string
      description: >-
        * `default` - Uses the store default stock management setting.

        * `ignore-stock` - Ignores stock when determining whether the product
        can be purchased.

        * `deny-without-own-stock` - The product can only be purchased if it has
        available own stock.

        * `deny-without-own-or-supplier-stock` - The product can only be
        purchased if it has available own stock or supplier stock.

        * `allow-backorder` - The product can be purchased even when no stock is
        available.
    StoreInfo:
      type: object
      properties:
        return_policy:
          allOf:
            - $ref: '#/components/schemas/ReturnPolicy'
          description: >-
            Return policy configuration for the store. This information can be
            used by integrations (e.g. Google Merchant) to represent the store's
            return conditions in a structured format.<p>This object is only
            present when the return policy is enabled.</p>
        translations:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/StoreInfoTranslation'
          description: >-
            Dictionary of translatable fields, keyed by locale. See the <a
            href="/docs/api/i18n-content#supported-locales">Supported
            Locales</a> section for available locales.
      required:
        - translations
    StoreInfoTranslation:
      type: object
      properties:
        name:
          type: string
          description: Name of the store, as defined in site texts.
        domain:
          type: string
        logo_url:
          type: string
          description: URL of the store's logo image.
        orders_email_account:
          type: string
          format: email
          description: >-
            Email address used for all order-related notifications (e.g. sales,
            shipping, pickup, and order updates).
        contact_email_account:
          type: string
          format: email
          description: >-
            Email address used for all customer communications (e.g. contact
            forms, product questions, and replies to reviews).
        promotions_email_account:
          type: string
          format: email
          description: Email address used for sending promotional communications.
      required:
        - contact_email_account
        - domain
        - logo_url
        - name
        - orders_email_account
        - promotions_email_account
    Supplier:
      type: object
      description: Serializer for the Supplier model.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the supplier.
        name:
          type: string
          description: Name of the supplier.
        internal_id:
          type: string
          description: >-
            Internal ID for the supplier. This alternative identifier is
            intended for linking it with external systems and managing it
            through imports or API integrations.
        description:
          type: string
          description: Internal description of the supplier.
      required:
        - id
        - internal_id
        - name
    TaxCategoryEnum:
      enum:
        - standard
        - reduced
        - super-reduced
        - zero
      type: string
      description: |-
        * `standard` - standard
        * `reduced` - reduced
        * `super-reduced` - super-reduced
        * `zero` - zero
    User:
      type: object
      description: |-
        Mixin for DRF Serializers to automatically validate input fields.
        Raises ValidationError if any unknown field is provided.
      properties:
        id:
          type: integer
          readOnly: true
        internal_id:
          type: string
          nullable: true
          description: >-
            Custom alternative identifier for the contact, typically used to map
            the contact to records in other systems such as ERPs. Must be unique
            among contacts.
        is_active:
          type: boolean
          description: >-
            Indicates whether the customer (contact) is active, meaning the
            email has been validated, the registration process completed, and
            the contact is not deleted.
        is_customer:
          type: boolean
          readOnly: true
          description: >-
            Indicates whether the contact is a customer, meaning they have made
            a purchase or completed a registration.
        deleted_at:
          type: string
          format: date-time
          description: >-
            Date and time in ISO 8601 format (e.g., 2023-10-01T12:00:00Z).
            Microseconds are not included. Timestamp indicating when the
            customer (contact) was deleted. Null if the customer (contact) is
            active.
        email:
          type: string
          format: email
          readOnly: true
        first_name:
          type: string
          description: First name of the contact.
        last_name:
          type: string
          description: Last name of the contact.
        full_name:
          type: string
          description: Full name of the contact, combining first and last names.
        phone:
          type: string
          nullable: true
          description: Phone number of the contact.
        preferred_locale:
          allOf:
            - $ref: '#/components/schemas/PreferredLocaleEnum'
          description: >-
            Locale code in ISO format (e.g., es-ES, en-GB).Format follows ISO
            639-1 (language) and ISO 3166-1 alpha-2 (country) standards.


            * `es-ES` - Spanish (Spain)

            * `ca-ES` - Catalan (Spain)

            * `en-GB` - English (United Kingdom)

            * `fr-FR` - French (France)

            * `it-IT` - Italian (Italy)

            * `pt-PT` - Portuguese (Portugal)

            * `de-DE` - German (Germany)

            * `ru-RU` - Russian (Russia)

            * `nl-NL` - Dutch (Netherlands)

            * `sv-SE` - Swedish (Sweden)

            * `da-DK` - Danish (Denmark)

            * `pl-PL` - Polish (Poland)

            * `el-GR` - Greek (Greece)

            * `hr-HR` - Croatian (Croatia)
        created_at:
          type: string
          format: date-time
          description: >-
            Date and time in ISO 8601 format (e.g., 2023-10-01T12:00:00Z).
            Microseconds are not included.
        is_b2b:
          type: boolean
          description: Indicates if the contact is a B2B (business-to-business) customer.
        last_login_at:
          type: string
          format: date-time
          description: >-
            Date and time in ISO 8601 format (e.g., 2023-10-01T12:00:00Z).
            Microseconds are not included.
        birth_date:
          type: string
          format: date
          description: Date in ISO 8601 format (e.g., 2023-10-01).
        gender:
          allOf:
            - $ref: '#/components/schemas/GenderEnum'
          description: |-
            Gender of the customer.

            * `male` - male
            * `female` - female
            * `other` - other
        customer_type:
          type: string
          nullable: true
          title: Tipo cliente
          description: >-
            Merchant-defined customer (contact) classification (e.g.
            professional, individual, sector). Selected during registration and
            editable by the customer.
          maxLength: 300
        is_agreed_payment_enabled:
          type: boolean
          description: >-
            Indicates whether the customer (contact) can place orders using the
            agreed payment method. Agreed payment refers to payment handled
            externally under conditions agreed with the merchant and must be
            marked as paid manually. Usually used in B2B scenarios.
        orders_count:
          type: integer
          description: Total number of orders created by the customer (contact).
        mkt_state:
          allOf:
            - $ref: '#/components/schemas/MktStateEnum'
          description: |-
            Current marketing state of the contact.

            * `not_subscribed` - not_subscribed
            * `subscribed` - subscribed
            * `unsubscribed` - unsubscribed
        default_shipping_address:
          allOf:
            - $ref: '#/components/schemas/Address'
          description: >-
            Default shipping address of the customer (contact). Used to pre-fill
            the shipping address during checkout.
        default_billing_address:
          allOf:
            - $ref: '#/components/schemas/Address'
          description: >-
            Default billing address of the customer (contact). Used to pre-fill
            the billing address during checkout.
      required:
        - birth_date
        - created_at
        - default_billing_address
        - default_shipping_address
        - email
        - full_name
        - id
        - is_customer
        - last_login_at
        - orders_count
        - preferred_locale
    Variant:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        id:
          type: integer
          readOnly: true
          description: Unique identifier for the variant.
        internal_id:
          type: string
          nullable: true
          description: >-
            Internal ID for the variant. This alternative identifier is intended
            for linking it with external systems and managing it through imports
            or API integrations.
        sku:
          type: string
          description: >-
            Stock Keeping Unit (SKU) for the variant, used for inventory
            management.
          maxLength: 40
        ean:
          type: string
          nullable: true
          description: >-
            European Article Number (EAN) for the variant, used for
            identification.
          maxLength: 14
        status:
          allOf:
            - $ref: '#/components/schemas/Status062Enum'
          description: |-
            Status of the object: 'published' or 'unpublished'.

            * `published` - published
            * `unpublished` - unpublished
        min_quantity:
          type: integer
          maximum: 9999
          minimum: 1
          description: Minimum purchasable quantity for this variant.
        quantity_factor:
          type: integer
          maximum: 9999
          minimum: 1
          description: Quantity must be bought in multiples of this value (step).
        warehouse_stock:
          type: integer
          description: A positive integer value.
        supplier_stock:
          type: integer
          maximum: 2147483647
          minimum: 0
          description: Number of units available from the supplier for this variant.
        available_stock:
          type: string
          readOnly: true
          description: >-
            Number of units available in stock for this variant. This is a
            computed field based on inventory and pending orders.
        weight:
          type: string
          format: decimal
          pattern: ^-?\d{0,8}(?:\.\d{0,2})?$
          description: >-
            Weight of the variant in kilograms (kg), used for shipping
            calculations. Accepts positive values with up to 2 decimal places
            for precision.
        volume:
          type: string
          format: decimal
          pattern: ^-?\d{0,7}(?:\.\d{0,3})?$
          nullable: true
          description: >-
            Volume of the variant in cubic meters (m³), used for shipping
            calculations. Accepts positive values with up to 3 decimal places
            for precision.
        cost_price:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Cost price of the variant (internal).
        prices:
          type: array
          items:
            $ref: '#/components/schemas/VariantPricing'
          description: >-
            <p>List of pricing information for the variant, specific to each
            market. Pricing inputs are provided per market.</p><p>For details
            about how markets are defined and how locales resolve to pricing
            markets, see the <a
            href="/docs/api/i18n-content#locales-vs-markets">Markets
            specification and mapping</a> section.</p>
        translations:
          type: array
          items:
            $ref: '#/components/schemas/VariantTranslation'
          description: >-
            List of translations for the variant. Each translation includes
            locale-specific information such as name, description, and URL.
      required:
        - available_stock
        - id
        - prices
        - status
    VariantPricing:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        market:
          allOf:
            - $ref: '#/components/schemas/MarketEnum'
          description: |-
            Pricing context (currency and commercial price rules).

            * `market_ru` - market_ru
            * `market_it` - market_it
            * `market_de` - market_de
            * `market_en` - market_en
            * `market_pt` - market_pt
            * `market_es` - market_es
            * `market_fr` - market_fr
        selling_price:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          readOnly: true
          description: Calculated selling price for the market.
        list_price:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Base price for the market.
        offer_price:
          type: object
          title: Money
          properties:
            amount:
              type: string
            currency:
              type: string
          description: Standard offer price for the market.
        flash_offer:
          allOf:
            - $ref: '#/components/schemas/FlashOffer'
          description: Temporary promotional price valid during a specific period.
      required:
        - list_price
        - market
        - selling_price
    VariantTranslation:
      type: object
      description: Base serializer for OpenTiendas models, providing common configurations.
      properties:
        locale:
          allOf:
            - $ref: '#/components/schemas/LocaleEnum'
          description: >-
            Locale code in ISO format (e.g., es-ES, en-GB).Format follows ISO
            639-1 (language) and ISO 3166-1 alpha-2 (country) standards.


            * `es-ES` - Spanish (Spain)

            * `ca-ES` - Catalan (Spain)

            * `en-GB` - English (United Kingdom)

            * `fr-FR` - French (France)

            * `it-IT` - Italian (Italy)

            * `pt-PT` - Portuguese (Portugal)

            * `de-DE` - German (Germany)

            * `ru-RU` - Russian (Russia)

            * `nl-NL` - Dutch (Netherlands)

            * `sv-SE` - Swedish (Sweden)

            * `da-DK` - Danish (Denmark)

            * `pl-PL` - Polish (Poland)

            * `el-GR` - Greek (Greece)

            * `hr-HR` - Croatian (Croatia)
        name:
          type: string
          description: >-
            Name of the variant in the specified locale. For write operations,
            this field is ignored for <code>simple</code> products.
        description:
          type: string
          readOnly: true
          description: Description of the variant in the specified locale.
        body_html:
          type: string
          readOnly: true
          description: HTML body content of the variant in the specified locale.
      required:
        - body_html
        - description
        - locale
        - name
    WarehouseReleaseStatusEnum:
      enum:
        - not_released
        - partially_released
        - released
      type: string
      description: |-
        * `not_released` - not_released
        * `partially_released` - partially_released
        * `released` - released
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: API Key authentication using Bearer token in Authorization header.
tags:
  - name: Brands
    description: >-
      <p>A <b>Brand</b> represents the manufacturer or commercial brand
      associated with products in the catalog. Brands are used for catalog
      organization, filtering, and SEO presentation.</p><hr><p><b>Fixed
      fields</b>: <code>id</code></p><p><b>Default fields</b>:
      <code>name</code>, <code>internal_id</code>, <code>url</code></p><p>See
      the <a href="/docs/api/controlling-response-shape">Field selection and
      response shape</a> page for the global rules governing field selection and
      related resource inclusion.</p>
  - name: Categories
    description: >-
      <p>A <b>Category</b> represents a hierarchical grouping of products in the
      catalog. Categories are used for navigation (category pages), filtering,
      and SEO presentation.</p><hr><p><b>Fixed fields</b>:
      <code>id</code></p><p><b>Default fields</b>: <code>internal_id</code>,
      <code>name</code>, <code>url</code></p><p>See the <a
      href="/docs/api/controlling-response-shape">Field selection and response
      shape</a> page for the global rules governing field selection and related
      resource inclusion.</p>
  - name: Contacts (customers and subscribers)
    description: >-
      <p>A <b>Contact</b> is created when a person provides identifying
      information through any of the following actions:<ul><li>Creating an order
      (including guest checkout)</li><li>Completing the account registration
      process</li><li>Subscribing to communications (e.g.
      newsletter)</li><li>Being created through import or external integration
      processes</li></ul><p>A contact can be a <b>customer</b>, a
      <b>subscriber</b>, or both.</p><p>Other considerations:</p><ul><li>Like
      other resources, contacts are identified by their <code>id</code> field.
      Additionally, the <code>email</code> and <code>internal_id</code> fields
      are also unique and cannot be duplicated across contacts.</li><li>A
      customer is a contact that has made a purchase or completed a
      registration; therefore, it may be registered or not, and may or may not
      have completed a purchase.</li><li>If a non-registered customer later
      registers using the same email address, the existing contact record is
      reused and retains the same <code>id</code>.</li><li>A subscriber is a
      contact whose marketing state (<i>mkt_state</i> field) is either
      <code>subscribed</code> or <code>unsubscribed</code>, indicating their
      marketing preference. Only contacts with a marketing state of
      <code>subscribed</code> are eligible to receive marketing
      communications.</li></ul></p><hr><p><b>Fixed fields</b>:
      <code>id</code></p><p><b>Default fields</b>: <code>internal_id</code>,
      <code>is_active</code>, <code>email</code>, <code>first_name</code>,
      <code>last_name</code>, <code>full_name</code>, <code>phone</code>,
      <code>preferred_locale</code></p><p>See the <a
      href="/docs/api/controlling-response-shape">Field selection and response
      shape</a> page for the global rules governing field selection and related
      resource inclusion.</p>
  - name: Jobs
    description: >-
      <p>
        A Job represents an asynchronous background task created by OpenTiendas to
        process heavy API operations without blocking the original request or affecting
        store performance.
      </p>


      <p>
        Jobs are commonly created by bulk API operations, such as
        <code>products_bulk_upsert</code> or <code>variants_bulk_update</code>. When
        one of these operations is accepted, the API returns <code>202 Accepted</code>
        together with a <code>job_id</code>. This initial response confirms that the
        job has been created and queued for processing. The final result is determined
        later, when the job is processed.
      </p>


      <p>
        External integrations can use jobs to inspect the status, result, and
        processing logs of large operations. They can also subscribe to job webhooks to
        be notified automatically when a job reaches a final state, avoiding periodic
        polling.
      </p>


      <p>
        A completed job may still contain errors. Use
        <code>completed_with_errors</code> to detect jobs where the background task
        finished but some records could not be processed successfully. Use the Job Logs
        endpoint to inspect the affected records and validation details.
      </p>


      <p>Other considerations:</p>


      <ul>
        <li>
          Logs are not included in the job response. Use the Job Logs endpoint to
          retrieve the execution log for a specific job.
        </li>
        <li>
          Jobs and their logs are retained for 5 days from the creation date when
          completed successfully, and for 30 days when failed or completed with errors.
          After this period, they are automatically deleted.
        </li>
      </ul><hr><p><b>Fixed fields</b>: <code>id</code></p><p><b>Default
      fields</b>: <code>type</code>, <code>status</code>,
      <code>created_at</code>, <code>started_at</code>,
      <code>finished_at</code>, <code>summary</code></p><p>See the <a
      href="/docs/api/controlling-response-shape">Field selection and response
      shape</a> page for the global rules governing field selection and related
      resource inclusion.</p>
  - name: Orders
    description: >-
      <p><p>An <b>Order</b> represents a purchase attempt created when a
      customer proceeds to the payment step during checkout. It records the
      items the customer intends to buy together with the commercial and
      operational information associated with that transaction. Because an order
      is created at the payment stage while going through the entire checkout
      process, a customer may generate <b>multiple orders</b> if the checkout
      process is abandoned and started again.</p><p>An order is a
      <b>transactional snapshot</b> created at that moment. The items, prices,
      taxes, and totals stored in the order reflect the exact state of the
      transaction at the time it was created and are not affected by later
      changes to products, variants, or pricing. Each order contains one or more
      <b>order items</b> referencing the variants selected by the customer,
      together with the quantities and commercial conditions applied. It also
      includes customer information, billing and shipping addresses, payment
      data, shipping details, and order totals.</p><p>Totals are always
      expressed in the canonical shop currency (ie. EUR).</p></p><hr><p><b>Fixed
      fields</b>: <code>id</code></p><p><b>Default fields</b>:
      <code>created_at</code>, <code>payment_status</code>,
      <code>warehouse_release_status</code>, <code>fulfillment_status</code>,
      <code>delivery_method</code>, <code>locale</code>,
      <code>payment_method</code>, <code>payment_gateway</code>,
      <code>paid_at</code>, <code>fulfilled_at</code>, <code>canceled_at</code>,
      <code>total</code>, <code>shipping</code>, <code>fees</code>,
      <code>email</code></p><p><b>Nested objects</b>:
      <code>customer</code></p><p>No nested objects are included by default. Use
      the <i>includes</i> query parameter to include nested objects in the
      response.<br>See the <a href="/docs/api/controlling-response-shape">Field
      selection and response shape</a> page for the global rules governing field
      selection and related resource inclusion.</p>
  - name: Price Lists
    description: >-
      <p>A <b>Price List</b> defines customer-specific prices, discounts and
      purchase conditions for products. Price lists can include: fixed prices
      for variants, percentage discounts, quantity-based pricing rules and
      minimum order requirements.<p>Important considerations:</p><ul><li>Custom
      price lists are typically used in B2B scenarios.</li><li>Customers
      assigned to a price list see adjusted pricing across the storefront and
      checkout.</li><li>If multiple price lists apply to the same customer, the
      final pricing is resolved automatically using the most specific applicable
      rule. When multiple rules with the same specificity apply, the best price
      for the customer is used.<p>Pricing priority:</p><ul><li>Fixed prices
      (lowest price wins)</li><li>Brand discounts (highest discount
      wins)</li><li>Category discounts (most specific category, then highest
      discount)</li><li>Global discounts (highest discount wins)</li></ul><p
      style='margin-bottom:1em;'>If a product belongs to multiple categories,
      the main product category is used for category discount
      calculation.</p></li><li>Products without applicable price list rules
      continue using their default storefront pricing.</li><li>Customers with a
      custom price list assigned are not eligible for standard promotions,
      automatic discounts, promotional codes, flash offers or regular quantity
      discounts and cannot add additional services to the
      cart.</li></ul></p><hr><p><b>Fixed fields</b>:
      <code>id</code></p><p><b>Default fields</b>: <code>internal_id</code>,
      <code>is_active</code>, <code>minimum_order_amount</code>,
      <code>customers_count</code>, <code>variant_prices_count</code>,
      <code>global_discount</code></p><p>See the <a
      href="/docs/api/controlling-response-shape">Field selection and response
      shape</a> page for the global rules governing field selection and related
      resource inclusion.</p>
  - name: Products
    description: >-
      <p>A <b>Product</b> is a catalog container that groups one or more
      variants under a single listing (name, description, brand, categories,
      etc.). Products always have at least one variant. Pricing, inventory, and
      other operational data are managed at the variant level.<p>The
      <code>product_structure</code> field indicates whether the product
      supports multiple variants (<code>with_variants</code>) or is a
      single-variant product (<code>simple</code>).</p></p><hr><p><b>Fixed
      fields</b>: <code>id</code></p><p><b>Default fields</b>:
      <code>internal_id</code>, <code>product_structure</code>,
      <code>status</code>, <code>product_kind</code>, <code>model_code</code>,
      <code>tax_category</code>, <code>images</code>,
      <code>variants_count</code>, <code>url</code>, <code>name</code>,
      <code>slug</code>, <code>slug_base</code></p><p><b>Nested objects</b>:
      <code>supplier</code>, <code>brand</code>, <code>categories</code>,
      <code>variants</code></p><p>No nested objects are included by default. Use
      the <i>includes</i> query parameter to include nested objects in the
      response.<br>See the <a href="/docs/api/controlling-response-shape">Field
      selection and response shape</a> page for the global rules governing field
      selection and related resource inclusion.</p>
  - name: Reviews
    description: >-
      <p>A <b>Review</b> represents customer feedback about a product
      (optionally a specific variant) or about the store. Reviews can be
      published/unpublished and include rating, content, author and other
      information.</p><hr><p><b>Fixed fields</b>:
      <code>id</code></p><p><b>Default fields</b>: <code>locale</code>,
      <code>status</code>, <code>rating</code>, <code>created_at</code>,
      <code>type</code></p><p>See the <a
      href="/docs/api/controlling-response-shape">Field selection and response
      shape</a> page for the global rules governing field selection and related
      resource inclusion.</p>
  - name: Store
    description: >-
      <p>The <b>Store</b> resource represents the global configuration and
      public identity of the shop. It exposes high-level information such as the
      store name or domains.</p><hr>
  - name: Suppliers
    description: >-
      <p>A <b>Supplier</b> represents a company or entity that provides products
      to the store. Suppliers are used internally for stock sourcing, logistics,
      purchasing workflows, and reporting. Supplier data is not localized and is
      intended for back-office and integration use.</p><hr><p><b>Fixed
      fields</b>: <code>name</code></p><p><b>Default fields</b>:
      <code>id</code></p><p>See the <a
      href="/docs/api/controlling-response-shape">Field selection and response
      shape</a> page for the global rules governing field selection and related
      resource inclusion.</p>
  - name: Variants
    description: >-
      <p>A <b>Variant</b> represents a purchasable SKU of a product (the exact
      item a customer buys, e.g. "T-shirt / Black / M"). Every variant belongs
      to a parent product. Pricing, inventory, and other operational data are
      managed at the variant level.</p><hr><p><b>Fixed fields</b>:
      <code>id</code></p><p><b>Default fields</b>: <code>internal_id</code>,
      <code>sku</code>, <code>ean</code>, <code>status</code>,
      <code>available_stock</code>, <code>name</code>,
      <code>selling_price</code></p><p>See the <a
      href="/docs/api/controlling-response-shape">Field selection and response
      shape</a> page for the global rules governing field selection and related
      resource inclusion.</p>
