openapi: 3.1.0
info:
  title: Medipim Web API - OpenAPI 3.1
  description: |-
    Here, you will find all the necessary information to interact with our
    platform programmatically using the web API. Our API allows developers to access and manipulate various resources on our internal network, such as products, media and leaflets.
  version: 1.0.0
  license:
    name: Commercial
    url: https://www.medipim.com/world/sales-conditions
servers:
  - url: https://api.medipim.be/v4
    description: Production server
  - url: https://api.dev.medipim.be/v4
    description: Staging server
security:
  - basicAuth: []
tags:
  - name: Products
    description: Products describe the specific goods you offer to your customers.
  - name: Media Items
    description: Media items are images or documents that are associated with a product.
  - name: Leaflets
    description: Leaflets are texts that provide legal information about a drug and its use.
  - name: Public Categories
    description: Public categories are classifications that help organize products for easier navigation and discovery by end-users. They are hierarchical and can have parent-child relationships.
  - name: Organizations
    description: Organizations represent customers, suppliers, or other entities in the platform. Use these endpoints to query, find, create organizations and check their subscription status.
  - name: Brands
    description: Brands represent the manufacturers or labels associated with products in the Medipim platform.
  - name: Dietary Restrictions
    description: Dietary restrictions indicate whether a product is suitable for certain diets or contains specific allergens.
externalDocs:
  description: Find out more about Medipim
  url: https://www.medipim.com/docs/
paths:
  /products/query:
    post:
      tags:
        - Products
      summary: Query products with filters and pagination.
      description: |-
        Query products using filters, sorting, and pagination. This endpoint supports a maximum of 10,000 results.

        **Filter**: The `filter` object must have exactly one key. It can be a **property filter** (e.g. `id`, `search`, `brand`, `publicCategories`, `organization`, `deleted`, `status`, `productFamilies`, `media`, `attributes`, `dietaryRestrictions`, `colors`, `createdAt`, `touchedAt`, `hasContent`, `hasCorrections`, `publicPrice`, `gtin`, `ean`, `activeIngredient`, `atc`) or a **compound filter** (`and`, `or`, `not`). See the `ProductFilter` schema for details. Region-specific codes (e.g. `cnk`, `pzn`, `cip13`) may also be supported.

        **Pagination Limit**: This endpoint can only return up to 10,000 products. If your query matches more than 10,000 products:
        - The `total` field in the response will be capped at 10,000
        - The `totalExceedsLimit` field will be set to `true`
        - Use the `/products/stream` endpoint to retrieve all matching products
      operationId: queryProducts
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  $ref: '#/components/schemas/ProductFilter'
                  description: Filter criteria. Exactly one key; property filter or compound (and, or, not).
                sorting:
                  oneOf:
                    - $ref: '#/components/schemas/ProductSortOption'
                    - type: array
                      items:
                        $ref: '#/components/schemas/ProductSortOption'
                      minItems: 1
                  description: |-
                    Sort order. Either a single sort object or an array of sort objects.
                    Each object has exactly one key (see ProductSortOption): a field name with value `ASC` or `DESC`, or `name` with `{ direction, locale }`, or `auto` with `{}` or `{ locale }`.
                    Examples: `{"id": "ASC"}`, `{"name": {"direction": "ASC", "locale": "nl"}}`, `{"auto": {}}`.
                page:
                  type: object
                  properties:
                    'no':
                      type: integer
                      description: Page number (0-based)
                      example: 0
                    size:
                      type: integer
                      description: Number of results per page (max 250)
                      example: 250
              required:
                - filter
                - sorting
            examples:
              searchQuery:
                summary: Query by search term
                value:
                  filter:
                    search:
                      query: aspirin
                      locale: en
                  sorting:
                    - publicPrice: DESC
                    - name:
                        direction: ASC
                        locale: en
                  page:
                    'no': 0
                    size: 100
              minimumContent:
                summary: Products with image, description and public category
                value:
                  filter:
                    minimumContent: true
                  sorting:
                    - id: ASC
                  page:
                    'no': 0
                    size: 100
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedProductResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '422':
          description: Validation error (e.g., pagination limit exceeded)
  /products/stream:
    post:
      tags:
        - Products
      summary: Stream all products matching a filter.
      description: |-
        Stream products using filters and sorting. Unlike `/products/query`, this endpoint has no result limit and returns all matching products.

        **When to use**: Use this endpoint when:
        - Your query matches more than 10,000 products
        - The `/products/query` endpoint returns `totalExceedsLimit: true`
        - You need to retrieve all matching products regardless of count

        The response is streamed as newline-delimited JSON (NDJSON).
      operationId: streamProducts
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  $ref: '#/components/schemas/ProductFilter'
                  description: Filter criteria. Same structure as `/products/query`.
                sorting:
                  oneOf:
                    - $ref: '#/components/schemas/ProductSortOption'
                    - type: array
                      items:
                        $ref: '#/components/schemas/ProductSortOption'
                      minItems: 1
                  description: Sort order. Same structure as `/products/query` (single sort object or array of sort objects).
                  example:
                    id: ASC
      responses:
        '200':
          description: Successful operation - returns streamed NDJSON
          content:
            application/x-ndjson:
              schema:
                type: object
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
  /products/find:
    get:
      tags:
        - Products
      summary: Get a product by ID or unique identifier.
      description: Returns a single product. You can identify the product by `id` (Medipim product ID, format M + 9 alphanumeric characters) or by a unique identifier field (e.g. EAN, product code) supported by your configuration.
      operationId: findProduct
      parameters:
        - name: id
          in: query
          required: false
          schema:
            type: string
            pattern: ^M[0-9A-Z]{9}$
          description: Product ID in Medipim format (M followed by 9 alphanumeric characters). Alternatively, use a unique identifier field name as query parameter.
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                type: object
                properties:
                  product:
                    $ref: '#/components/schemas/Product'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          description: Validation error (e.g. missing identifier).
  /products/create:
    post:
      tags:
        - Products
      summary: Create a product.
      description: |-
        Create a new product. The request body must include a `product` object with field values.
        Optionally include `organizations` (array of organization IDs) to assign the product to organizations.
      operationId: createProduct
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - product
              properties:
                product:
                  type: object
                  description: Product field values (structure depends on product fields configuration).
                organizations:
                  type: array
                  items:
                    type: string
                  description: Optional array of organization IDs to assign the product to.
      responses:
        '200':
          description: Successful operation. Returns the created product.
          content:
            application/json:
              schema:
                type: object
                properties:
                  product:
                    $ref: '#/components/schemas/Product'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /products/update:
    post:
      tags:
        - Products
      summary: Update a product.
      description: |-
        Update an existing product. Identify the product by `id` (Medipim product ID) or `product` (unique identifier).
        The `data` object contains the field values to update.
        Optionally include `organizations` to update organization assignments.
      operationId: updateProduct
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - data
              properties:
                id:
                  type: string
                  pattern: ^M[0-9A-Z]{9}$
                  description: Product ID in Medipim format (M + 9 alphanumeric characters). Use this or `product` to identify the product.
                product:
                  type: object
                  description: Unique identifier key-value to find the product (e.g. ean, productCode). Use this or `id`.
                data:
                  type: object
                  description: Product field values to update (structure depends on product fields configuration).
                organizations:
                  type: array
                  items:
                    type: string
                  description: Optional array of organization IDs.
      responses:
        '200':
          description: Successful operation. Returns the updated product.
          content:
            application/json:
              schema:
                type: object
                properties:
                  product:
                    $ref: '#/components/schemas/Product'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /products/get-fields:
    get:
      tags:
        - Products
      summary: Get product field definitions.
      description: Returns the list of product data fields available for the authenticated user (create/update, etc.).
      operationId: getProductFields
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                type: object
                properties:
                  fields:
                    type: array
                    items:
                      type: object
                    description: List of product field definitions (code, type, labels, etc.).
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
  /products/add-media:
    post:
      tags:
        - Products
      summary: Add a media item to a product.
      description: Associate a media item with a product. Identify the product by `id` or `product` (unique identifier).
      operationId: addProductMedia
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - media
              properties:
                id:
                  type: string
                  pattern: ^M[0-9A-Z]{9}$
                  description: Product ID in Medipim format (M + 9 alphanumeric characters). Use this or `product` to identify the product.
                product:
                  type: object
                  description: Unique identifier key-value to find the product. Use this or `id`.
                media:
                  type: integer
                  description: Media item ID to add to the product.
      responses:
        '200':
          description: Successful operation. Returns the product with updated media.
          content:
            application/json:
              schema:
                type: object
                properties:
                  product:
                    $ref: '#/components/schemas/Product'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /products/remove-media:
    post:
      tags:
        - Products
      summary: Remove a media item from a product.
      description: Disassociate a media item from a product. Identify the product by `id` or `product` (unique identifier).
      operationId: removeProductMedia
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - media
              properties:
                id:
                  type: string
                  pattern: ^M[0-9A-Z]{9}$
                  description: Product ID in Medipim format (M + 9 alphanumeric characters). Use this or `product` to identify the product.
                product:
                  type: object
                  description: Unique identifier key-value to find the product. Use this or `id`.
                media:
                  type: integer
                  description: Media item ID to remove from the product.
      responses:
        '200':
          description: Successful operation. Returns the product with updated media.
          content:
            application/json:
              schema:
                type: object
                properties:
                  product:
                    $ref: '#/components/schemas/Product'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /product_descriptions:
    get:
      tags:
        - Products
      summary: List product descriptions.
      operationId: listProductDescriptions
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RelatedResource'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
  /media_items:
    get:
      tags:
        - Media Items
      summary: List media items.
      operationId: listMediaItems
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/MediaItem'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
  /media_items/{mediaItemId}:
    get:
      tags:
        - Media Items
      summary: Get a media item by ID.
      operationId: retrieveMediaItem
      parameters:
        - name: mediaItemId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MediaItem'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '404':
          description: Media item not found
  /media/find:
    get:
      tags:
        - Media Items
      summary: Get a media item by ID.
      operationId: findMediaItem
      parameters:
        - name: id
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: Media item ID (UUID).
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                type: object
                properties:
                  mediaItem:
                    $ref: '#/components/schemas/MediaItem'
        '400':
          description: Bad request (e.g. missing id).
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '404':
          description: Media item not found
  /media/query:
    post:
      tags:
        - Media Items
      summary: Query media items with filters and pagination.
      operationId: queryMediaItems
      parameters:
        - name: compact
          in: query
          required: false
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
            default: 'false'
          description: If true, return compact media item representation.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  type: object
                  description: Filter criteria for media items.
                sorting:
                  type: object
                  description: Sort order.
                page:
                  type: object
                  properties:
                    'no':
                      type: integer
                      description: Page number (0-based).
                    size:
                      type: integer
                      description: Page size.
      responses:
        '200':
          description: Successful operation. Returns a paginated list of media items.
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                      totalExceedsLimit:
                        type: boolean
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/MediaItem'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
  /media/update:
    post:
      tags:
        - Media Items
      summary: Update a media item.
      description: |-
        Update an existing media item. Identify by `id` or `mediaItem` (UUID).
        Optionally provide `products` (array of product IDs) to update product associations.
      operationId: updateMediaItem
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                  format: uuid
                  description: Media item ID. Use this or `mediaItem`.
                mediaItem:
                  type: string
                  format: uuid
                  description: Media item ID. Use this or `id`.
                products:
                  type: array
                  items:
                    type: string
                  description: Optional array of product IDs to associate.
      responses:
        '200':
          description: Successful operation. Returns the updated media item.
          content:
            application/json:
              schema:
                type: object
                properties:
                  mediaItem:
                    $ref: '#/components/schemas/MediaItem'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /media/create-link:
    post:
      tags:
        - Media Items
      summary: Create a link media item.
      description: |-
        Create a new link-type media item. Provide `data` with media field values.
        Optionally include `organizations` and `products` to assign.
      operationId: createLinkMediaItem
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - data
              properties:
                data:
                  type: object
                  description: Media field values (structure depends on media fields configuration).
                organizations:
                  type: array
                  items:
                    type: string
                  description: Optional organization IDs.
                products:
                  type: array
                  items:
                    type: string
                  description: Optional product IDs to associate.
      responses:
        '200':
          description: Successful operation. Returns the created media item.
          content:
            application/json:
              schema:
                type: object
                properties:
                  mediaItem:
                    $ref: '#/components/schemas/MediaItem'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /media/upload:
    post:
      tags:
        - Media Items
      summary: Upload a media file.
      description: |-
        Upload a file (image or PDF) to create a new media item. Send as multipart/form-data with `file`, or JSON with base64-encoded `file`.
        Optionally include `products` (array of product IDs) and `central` (boolean).
      operationId: uploadMediaItem
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: byte
                  description: Base64-encoded file content (alternative to multipart).
                products:
                  type: array
                  items:
                    type: string
                  description: Optional product IDs to associate.
                central:
                  type: boolean
                  description: Optional; store in central repository.
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                products:
                  type: array
                  items:
                    type: string
                central:
                  type: boolean
      responses:
        '200':
          description: Successful operation. Returns the created media item.
          content:
            application/json:
              schema:
                type: object
                properties:
                  mediaItem:
                    $ref: '#/components/schemas/MediaItem'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /media/get-fields:
    get:
      tags:
        - Media Items
      summary: Get media field definitions.
      description: Returns the list of media data fields available for the authenticated user.
      operationId: getMediaFields
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                type: object
                properties:
                  fields:
                    type: array
                    items:
                      type: object
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
  /media/stream:
    post:
      tags:
        - Media Items
      summary: Stream all media items matching a filter.
      description: Returns all matching media items as newline-delimited JSON (NDJSON). No pagination limit.
      operationId: streamMediaItems
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  type: object
                sorting:
                  type: object
      responses:
        '200':
          description: Successful operation. Stream of JSON objects (one per line).
          content:
            application/x-json-stream:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                      index:
                        type: integer
                  result:
                    $ref: '#/components/schemas/MediaItem'
        '204':
          description: No content (no matching media items).
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
  /media/publish:
    post:
      tags:
        - Media Items
      summary: Publish a media item.
      operationId: publishMediaItem
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                  format: uuid
                  description: Media item ID. Use this or `mediaItem`.
                mediaItem:
                  type: string
                  format: uuid
                  description: Media item ID. Use this or `id`.
      responses:
        '200':
          description: Successful operation. Returns the published media item.
          content:
            application/json:
              schema:
                type: object
                properties:
                  mediaItem:
                    $ref: '#/components/schemas/MediaItem'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /media/unpublish:
    post:
      tags:
        - Media Items
      summary: Unpublish a media item.
      operationId: unpublishMediaItem
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                  format: uuid
                  description: Media item ID. Use this or `mediaItem`.
                mediaItem:
                  type: string
                  format: uuid
                  description: Media item ID. Use this or `id`.
      responses:
        '200':
          description: Successful operation. Returns the unpublished media item.
          content:
            application/json:
              schema:
                type: object
                properties:
                  mediaItem:
                    $ref: '#/components/schemas/MediaItem'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /public-categories/query:
    post:
      tags:
        - Public Categories
      description: Query the public categories assigned to products.
      summary: Query Public Categories
      operationId: queryPublicCategories
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  type: object
              example:
                filter:
                  id: 1
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                        example: 100
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/PublicCategory'
                required:
                  - meta
                  - results
              example:
                meta:
                  total: 2
                results:
                  - id: 1
                    name:
                      nl: Geneesmiddelen
                      fr: Médicaments
                      en: Medicines
                      de: Arzneimittel
                    parent: null
                    order: 1
                    meta:
                      createdAt: 1625247600
                      updatedAt: 1625334000
                  - id: 2
                    name:
                      nl: Supplementen
                      fr: Suppléments
                      en: Supplements
                      de: Ergänzungen
                    parent: 1
                    order: 2
                    meta:
                      createdAt: 1625247600
                      updatedAt: 1625334000
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /public-categories/tree:
    get:
      tags:
        - Public Categories
      description: Get the hierarchical tree structure of public categories.
      summary: Get Public Categories Tree
      operationId: getPublicCategoriesTree
      parameters:
        - name: filter
          in: query
          description: 'Filter the results. This is a comma separated string of filters. Example: `root:1,depth:2`'
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PublicCategoryTreeCategory'
              examples:
                public-categories-tree:
                  summary: Example category tree
                  value:
                    - id: 1
                      name:
                        nl: Geneesmiddelen
                        fr: Médicaments
                        en: Medicines
                        de: Arzneimittel
                      parent: null
                      order: 1
                      meta:
                        createdAt: 1625247600
                        updatedAt: 1625334000
                      children:
                        - id: 2
                          name:
                            nl: Supplementen
                            fr: Suppléments
                            en: Supplements
                            de: Ergänzungen
                          parent: 1
                          order: 2
                          meta:
                            createdAt: 1625247600
                            updatedAt: 1625334000
                          children: []
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
  /organizations/query:
    post:
      tags:
        - Organizations
      summary: Query organizations.
      description: |-
        Query organizations using filters, sorting, and pagination.

        ## Filter
        The `filter` object must have exactly one key. It can be:
        - A **property filter** (e.g. `id`, `type`, `name`, `search`, `searchName`, `specializations`, `public`, `sysId`, `externalId`, `createdBy`, `resellerId`) with an appropriate value.
        - A **compound filter** with key `and` (value: array of filter objects; all must match) or `or` (value: array of filter objects; at least one must match). Each element in an `and`/`or` array is again a filter object with the same structure.

        ## Sort
        Sort the results by one of the following fields: `id`, `name`, `city`.

        ## Page
        Size must be one of: 10, 50, 100, 250.
      operationId: queryOrganizations
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  $ref: '#/components/schemas/OrganizationFilter'
                sorting:
                  oneOf:
                    - $ref: '#/components/schemas/OrganizationSortOption'
                    - type: array
                      items:
                        $ref: '#/components/schemas/OrganizationSortOption'
                      minItems: 1
                  description: |-
                    Sort order. Either a single sort object or an array of sort objects.
                    Each object has exactly one key (`id`, `name`, or `city`) with value `ASC` or `DESC`.
                    Examples: `{"name": "ASC"}`, `[{"id": "ASC"}, {"name": "DESC"}]`.
                  example:
                    name: ASC
                page:
                  type: object
                  properties:
                    'no':
                      type: integer
                      description: Page number (0-based)
                      example: 0
                    size:
                      type: integer
                      description: Number of results per page (10, 50, 100, or 250)
                      example: 100
      responses:
        '200':
          description: |-
            Successful operation.

            Returns a paginated list of organizations, sorted by id in ascending order by default.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedOrganizationResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /organizations/find:
    get:
      tags:
        - Organizations
      summary: Get an organization by ID.
      operationId: findOrganization
      parameters:
        - name: id
          in: query
          required: true
          schema:
            type: string
          description: Organization ID.
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  organization:
                    $ref: '#/components/schemas/Organization'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '404':
          description: Organization not found
  /organizations/create:
    post:
      tags:
        - Organizations
      summary: Create an organization.
      description: |-
        Create a new organization. Requires a `profile` object with at least the `name` key.
        Optional `resellerId` and `settings` (isPublic, displayLogoOnApi).
        Profile may include type, externalId, holdingName, address, zipCode, region, city, country, phone, url.
      operationId: createOrganization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - profile
              properties:
                resellerId:
                  type: string
                  description: Reseller organization ID.
                settings:
                  type: object
                  properties:
                    isPublic:
                      type: boolean
                      default: true
                    displayLogoOnApi:
                      type: boolean
                      default: false
                profile:
                  type: object
                  required:
                    - name
                  properties:
                    name:
                      type: string
                    type:
                      type: string
                    externalId:
                      type: string
                    holdingName:
                      type: string
                    address:
                      type: string
                    zipCode:
                      type: string
                    region:
                      type: string
                    city:
                      type: string
                    country:
                      type: string
                    phone:
                      type: string
                    url:
                      type: string
            example:
              profile:
                name: Example Organization
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  organization:
                    $ref: '#/components/schemas/Organization'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /organizations/check/subscription:
    post:
      tags:
        - Organizations
      summary: List active subscriptions for organizations.
      description: |-
        Returns subscriptions and API keys for organizations matching the given filter.
        The `filter` object has the same structure as for `/organizations/query`: exactly one key, either a property filter (id, type, name, etc.) or a compound filter (`and` or `or` with an array of filter objects).
        Response includes organization id, name, active subscriptions, and API keys.
      operationId: checkOrganizationsSubscription
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - filter
              properties:
                filter:
                  $ref: '#/components/schemas/OrganizationFilter'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrganizationSubscriptionData'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /brands/query:
    post:
      tags:
        - Brands
      summary: Query brands.
      description: |-
        Query brands using filters, sorting, and pagination. Brands represent manufacturers or labels associated with products.

        ## Filter
        The `filter` object must have exactly one key. It can be:
        - A **property filter**, such as `search` (a string, to search for in brand name), `id` or `in` (an integer or array of integers, that represent brand IDs), `assignable` (boolean, brands assignable to your organization), `deleted` (boolean, include/exclude soft-deleted brands).
        - A **compound filter** with key `and` (array of filter objects; all must match), `or` (array of filter objects; at least one must match), or `not` (single filter object to negate).

        ## Sort
        Sort by one of: `id`, `name`, `product_count`.

        ## Page
        Size must be one of: 10, 50, 100, 250.

        ## Query parameter
        Use `viewableOnly=true` to restrict results to brands the authenticated user is allowed to view (e.g. brands of their organization).
      operationId: queryBrands
      parameters:
        - name: viewableOnly
          in: query
          required: false
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
            default: 'false'
          description: If `true`, only return brands the user is allowed to view.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  $ref: '#/components/schemas/BrandFilter'
                sorting:
                  oneOf:
                    - $ref: '#/components/schemas/BrandSortOption'
                    - type: array
                      items:
                        $ref: '#/components/schemas/BrandSortOption'
                      minItems: 1
                  description: |-
                    Sort order. Either a single sort object or an array of sort objects.
                    Each object has exactly one key (`id`, `name`, or `product_count`) with value `ASC` or `DESC`.
                  example:
                    name: ASC
                page:
                  type: object
                  properties:
                    'no':
                      type: integer
                      description: Page number (0-based)
                      example: 0
                    size:
                      type: integer
                      description: Number of results per page (10, 50, 100, or 250)
                      example: 100
            example:
              filter:
                search: Pharma
              sorting:
                name: ASC
              page:
                'no': 0
                size: 100
      responses:
        '200':
          description: Successful operation. Returns a paginated list of brands.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedBrandResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /brands/find:
    get:
      tags:
        - Brands
      summary: Get a brand by ID.
      description: Returns a single brand by its ID.
      operationId: findBrand
      parameters:
        - name: id
          in: query
          required: true
          schema:
            type: integer
            description: Brand ID.
          description: Brand ID.
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                type: object
                properties:
                  brand:
                    $ref: '#/components/schemas/Brand'
        '400':
          description: Bad request (e.g. missing id).
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '404':
          description: Brand not found.
  /brands/create:
    post:
      tags:
        - Brands
      summary: Create a brand.
      description: Create a new brand with the given name.
      operationId: createBrand
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  description: Brand name.
            example:
              name: Example Brand
      responses:
        '200':
          description: Successful operation. Returns the created brand.
          content:
            application/json:
              schema:
                type: object
                properties:
                  brand:
                    $ref: '#/components/schemas/Brand'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          description: Unprocessable entity (e.g. missing name property).
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: missing name property
  /brands/update:
    post:
      tags:
        - Brands
      summary: Update a brand.
      description: Update an existing brand's name by ID.
      operationId: updateBrand
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - id
                - data
              properties:
                id:
                  type: integer
                  description: Brand ID to update.
                data:
                  type: object
                  required:
                    - name
                  properties:
                    name:
                      type: string
                      description: New brand name.
            example:
              id: 123
              data:
                name: Updated Brand Name
      responses:
        '200':
          description: Successful operation. Returns the updated brand.
          content:
            application/json:
              schema:
                type: object
                properties:
                  brand:
                    $ref: '#/components/schemas/Brand'
        '400':
          description: Bad request (e.g. missing id).
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntityResponse'
  /dietary-restrictions/query:
    post:
      tags:
        - Dietary Restrictions
      summary: Query dietary restrictions.
      description: |-
        Returns dietary restrictions, optionally filtered.
        Dietary restrictions indicate whether a product is suitable for certain diets or contains specific allergens.

        ## Filter
        The optional `filter` object must have exactly one key when present. It can be:
        - A **property filter** `id`: a single dietary restriction ID (string) or an array of IDs (match any). Allowed values are the restriction codes, e.g. `gluten_free`, `vegan`, `halal`, `dairy_free`, `sugar_free`, etc.
        - A **compound filter** with key `and` (array of filter objects; all must match), `or` (array of filter objects; at least one must match), or `not` (single filter object to negate).
      operationId: queryDietaryRestrictions
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  $ref: '#/components/schemas/DietaryRestrictionFilter'
                  description: Optional. Filter by dietary restriction ID(s) or combine with and/or/not.
            examples:
              singleId:
                summary: Single ID
                value:
                  filter:
                    id: vegan
              multipleIds:
                summary: Match any of several IDs
                value:
                  filter:
                    id:
                      - gluten_free
                      - dairy_free
                      - lactose_free
              compound:
                summary: Compound filter (or)
                value:
                  filter:
                    or:
                      - id: vegan
                      - id: vegetarian
      responses:
        '200':
          description: Successful operation. Returns a list of dietary restrictions.
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                        description: Total number of dietary restrictions.
                      totalExceedsLimit:
                        type: boolean
                        description: True if the total exceeds the pagination limit (when applicable).
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/DietaryRestriction'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ForbiddenResponse'
components:
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: |-
        We only support the HTTP Basic Authentication scheme for our web API. This means it is not safe to use directly in browser-based applications, as browsers may expose your credentials. If you need to access the API from a browser, we recommend using a proxy server or backend service to handle authentication securely.
        You can find your API credentials in your account settings on the Medipim platform. Use your API key as the user-id and your API secret as the password when using basic authentication.
  schemas:
    DietaryRestrictionId:
      type: string
      description: Identifier for a dietary restriction (e.g. allergen or diet suitability).
      enum:
        - alcohol_free
        - allergens_free
        - bio
        - dairy_free
        - fragrance_free
        - gluten_free
        - halal
        - kosher
        - lactose_free
        - latex_free
        - low_carbs
        - low_in_purine
        - no_nuts
        - protein_rich
        - salt_free_diet
        - soy_free
        - sugar_free
        - vegan
        - vegetarian
        - without_dyes
        - without_fructose
        - without_palm_oil
        - without_preservatives
        - yeast_free
    ColorId:
      type: string
      description: Identifier for a product color.
      enum:
        - beige
        - black
        - blue
        - bordeaux
        - brown
        - gold
        - gray
        - green
        - khaki
        - multicolor
        - ocher
        - orange
        - pink
        - purple
        - red
        - transparent
        - white
        - yellow
    ProductPropertyFilter:
      description: A single property filter for products. Exactly one key per object.
      anyOf:
        - title: ProductIdFilter
          type: object
          required:
            - id
          properties:
            id:
              oneOf:
                - type: string
                  pattern: ^M[0-9A-Z]{9}$
                  description: Single product ID in Medipim format (letter M followed by 9 alphanumeric characters). Max 1000 in array form.
                  example: M000000000
                - type: array
                  items:
                    type: string
                    pattern: ^M[0-9A-Z]{9}$
                    example: M000000000
                  maxItems: 1000
          additionalProperties: false
        - title: ProductStatusFilter
          type: object
          required:
            - status
          properties:
            status:
              oneOf:
                - type: string
                  enum:
                    - active
                    - replaced
                    - inactive
                  description: Single product status.
                - type: array
                  items:
                    type: string
                    enum:
                      - active
                      - replaced
                      - inactive
                    description: Product statuses (match any).
          additionalProperties: false
        - title: OrganizationIdFilter
          type: object
          required:
            - organization
          properties:
            organization:
              oneOf:
                - type: integer
                  description: Single organization ID.
                - type: array
                  items:
                    type: integer
                    description: Organization IDs (match any).
          additionalProperties: false
        - title: PublicCategoryIdFilter
          type: object
          properties:
            publicCategories:
              oneOf:
                - type: integer
                  description: Single public category ID.
                - type: array
                  items:
                    type: integer
                    description: Public category IDs (match any).
          additionalProperties: false
        - title: BrandIdFilter
          type: object
          required:
            - brand
          properties:
            brand:
              oneOf:
                - type: integer
                  description: Single brand ID.
                - type: array
                  items:
                    type: integer
                  description: Brand IDs (match any).
          additionalProperties: false
        - title: ProductFamilyIdFilter
          type: object
          properties:
            productFamilies:
              oneOf:
                - type: integer
                  description: Single product family ID.
                - type: array
                  items:
                    type: integer
                    description: Product family IDs (match any).
          additionalProperties: false
        - title: SearchFilter
          type: object
          required:
            - search
          properties:
            search:
              type: object
              required:
                - query
                - locale
              properties:
                query:
                  type: string
                locale:
                  type: string
                  description: Locale code (e.g. nl, fr).
                type:
                  type: string
                  enum:
                    - starts
                    - contains
                    - exact
                    - refcode
                    - symptoms
                  description: Optional search type. Defaults to 'starts' if omitted.
          additionalProperties: false
          example:
            search:
              query: aspirin
              locale: en
              type: starts
        - title: MinimumContentFilter
          type: object
          required:
            - minimumContent
          properties:
            minimumContent:
              description: |-
                Matches products that have an image AND a description AND a public category.
                When **true**, products must have all three; when **false**, products must lack at least one.
                Can be a boolean (simple form) or an object with **value** and **locale** for locale-scoped checks on media and descriptions.
              oneOf:
                - type: boolean
                  description: true = has media, description and public category; false = lacks at least one.
                - type: object
                  required:
                    - value
                    - locale
                  description: Locale-scoped check. Requires both value and locale.
                  properties:
                    value:
                      type: boolean
                      description: true = has all three (media, description, public category) in the given locale where applicable; false = lacks at least one.
                    locale:
                      type: string
                      description: Locale code for media and description checks (e.g. en, nl).
          additionalProperties: false
          example:
            minimumContent: true
        - title: HasContentFilter
          type: object
          required:
            - hasContent
          description: Filter by presence or absence of content in certain fields (e.g. media, descriptions, publicCategories).
          properties:
            hasContent:
              type: object
              required:
                - flag
              properties:
                flag:
                  type: string
                  description: Content flag (e.g. media, descriptions, publicCategories).
                condition:
                  type: boolean
                  default: true
                locale:
                  type: string
          additionalProperties: false
          example:
            hasContent:
              flag: media
              condition: false
              locale: en
        - title: EanFilter
          type: object
          required:
            - ean
          description: |-
            Matches products with specified EAN number.
            EAN codes must be provided as strings (with or without leading zeros). Arrays are limited to 1000 items.
          properties:
            ean:
              oneOf:
                - type: string
                  description: Single EAN code.
                  example: '3574660696318'
                - type: array
                  items:
                    type: string
                    description: EAN codes (match any) up to 1000 items.
                    example: '3574660696318'
                  maxItems: 1000
          additionalProperties: false
          example:
            ean: '3574660696318'
        - title: GTINFilter
          type: object
          required:
            - gtin
          deprecated: true
          properties:
            gtin:
              deprecated: true
              description: Deprecated. Use `eanGtin14` filter instead.
              oneOf:
                - type: string
                - type: array
                  items:
                    type: string
          additionalProperties: false
        - title: EAN/GTIN8Filter
          type: object
          required:
            - eanGtin8
          properties:
            eanGtin8:
              description: Filter by EAN/GTIN*. An 8 digit code that may be represented with or without leading zeros. To avoid confusion, EANs should be provided as strings. Arrays are limited to 1000 items.
              oneOf:
                - type: string
                - type: array
                  items:
                    type: string
          additionalProperties: false
          example:
            eanGtin8: '35746606'
        - title: EAN/GTIN12Filter
          type: object
          required:
            - eanGtin12
          properties:
            eanGtin12:
              description: Filter by EAN/GTIN*. An 12 digit code that may be represented with or without leading zeros. To avoid confusion, EANs should be provided as strings. Arrays are limited to 1000 items.
              oneOf:
                - type: string
                - type: array
                  items:
                    type: string
          additionalProperties: false
          example:
            eanGtin12: '357466069012'
        - title: EAN/GTIN13Filter
          type: object
          required:
            - eanGtin13
          properties:
            eanGtin13:
              description: Filter by EAN/GTIN*. An 13 digit code that may be represented with or without leading zeros. To avoid confusion, EANs should be provided as strings. Arrays are limited to 1000 items.
              oneOf:
                - type: string
                - type: array
                  items:
                    type: string
          additionalProperties: false
          example:
            eanGtin13: '357466069013'
        - title: EAN/GTIN14Filter
          type: object
          required:
            - eanGtin14
          properties:
            eanGtin14:
              description: Filter by EAN/GTIN. EANs are 14-digit codes that may be represented with or without leading zeros. To avoid confusion, EANs should be provided as strings. Arrays are limited to 1000 items.
              oneOf:
                - type: string
                - type: array
                  items:
                    type: string
          additionalProperties: false
          example:
            eanGtin14: '3574660696318'
        - title: HsCodeFilter
          type: object
          required:
            - hsCode
          description: Matches products with specified HS (Harmonised System) code.
          properties:
            hsCode:
              oneOf:
                - type: string
                  description: Single HS code.
                - type: array
                  items:
                    type: string
                  maxItems: 1000
                  description: HS codes (match any).
          additionalProperties: false
          example:
            hsCode: '010203'
        - title: CnkFilter
          type: object
          required:
            - cnk
          description: Matches products by CNK code.
          properties:
            cnk:
              oneOf:
                - type: string
                  description: |-
                    The national code number (CNK) is assigned to all medicines and parapharmaceutical products (medical devices,
                    biocides, food supplements, cosmetics, ...) dispensed in the pharmacy; both for human, veterinary and
                    phytopharmaceutical use.
                    This code is always 7 digits long.
                - type: array
                  items:
                    type: string
                  maxItems: 1000
                  description: CNK codes (match any).
          additionalProperties: false
          example:
            cnk: '4444444'
        - title: CtiFilter
          type: object
          required:
            - cti
          description: Matches products with specified CTI number.
          properties:
            cti:
              type: string
              description: CTI code.
          additionalProperties: false
          example:
            cti: '240904'
        - title: GalenicShapeFilter
          type: object
          required:
            - galenicShape
          description: Matches products by galenic shape
          properties:
            galenicShape:
              oneOf:
                - type: string
                  description: Single galenic shape code.
                - type: array
                  items:
                    type: string
                  maxItems: 1000
                  description: Galenic shape codes (match any).
          additionalProperties: false
          example:
            galenicShape: capsule
        - title: NameCtiFilter
          type: object
          required:
            - nameCti
          description: |-
            Matches products with specified nameCti or grouping by name number.
            An identical value (?) is assigned for products where the name is identical except for the quantity indication.
            This allows you to group identical products for which different packaging exists.
            Note: Medipim retrieves the name of a product from various sources. Poorly structured names can lead to discrepancies.
          properties:
            nameCti:
              type: string
              description: nameCti / grouping by name number.
          additionalProperties: false
          example:
            nameCti: '603722'
        - title: ActiveIngredientFilter
          type: object
          required:
            - activeIngredient
          properties:
            activeIngredient:
              oneOf:
                - type: string
                - type: array
                  items:
                    type: string
          additionalProperties: false
        - title: ATCFilter
          type: object
          required:
            - atc
          properties:
            atc:
              oneOf:
                - type: string
                - type: array
                  items:
                    type: string
              description: ATC category ID(s).
          additionalProperties: false
        - title: ProductAttributeFilter
          type: object
          required:
            - attributes
          deprecated: true
          properties:
            attributes:
              deprecated: true
              description: Deprecated. Use `colors`, `dietaryRestrictions` or `galenicShape` filter instead.
              oneOf:
                - type: integer
                - type: array
                  items:
                    type: integer
          additionalProperties: false
        - title: DietaryRestrictionsFilter
          type: object
          required:
            - dietaryRestrictions
          properties:
            dietaryRestrictions:
              oneOf:
                - $ref: '#/components/schemas/DietaryRestrictionId'
                - type: array
                  items:
                    $ref: '#/components/schemas/DietaryRestrictionId'
          additionalProperties: false
        - title: ColorsFilter
          type: object
          required:
            - colors
          properties:
            colors:
              oneOf:
                - $ref: '#/components/schemas/ColorId'
                - type: array
                  items:
                    $ref: '#/components/schemas/ColorId'
          additionalProperties: false
        - title: CreatedAtFilter
          type: object
          required:
            - createdAt
          description: Matches items created since the given time.
          properties:
            createdAt:
              oneOf:
                - type: integer
                  format: unix-time
                  description: Timestamp filter (e.g. from).
                - type: object
                  description: Timestamp filter (e.g. from).
                  properties:
                    from:
                      type: integer
                      format: unix-time
                    until:
                      type: integer
                      format: unix-time
          additionalProperties: false
          example:
            createdAt:
              from: 1712345678
              until: 1712345678
        - title: DeletedFilter
          type: object
          required:
            - deleted
          properties:
            deleted:
              type: boolean
              description: Include or exclude pre-deleted (soft-deleted) products.
          additionalProperties: false
        - title: MediaIdFilter
          type: object
          required:
            - media
          properties:
            media:
              oneOf:
                - type: integer
                  description: Single media item ID.
                - type: array
                  items:
                    type: integer
                    description: Media item IDs (match any).
              description: Media item ID(s).
          additionalProperties: false
    ProductFilter:
      description: Filter object with exactly one key. Either a **property filter** (e.g. id, search, brand, publicCategories, organization, deleted, status, productFamilies, media, attributes, dietaryRestrictions, colors, createdAt, touchedAt, minimumContent, hasContent, hasCorrections, publicPrice, gtin, ean, hsCode, cnk, cti, galenicShape, nameCti, activeIngredient, atc; region-specific codes like cnk, pzn, cip13, etc. may also be supported) or a **compound filter** with key `and` (array of filter objects, all must match), `or` (array of filter objects, at least one must match), or `not` (single filter object to negate). Arrays of IDs are limited to 1000 items where applicable.
      oneOf:
        - $ref: '#/components/schemas/ProductPropertyFilter'
        - title: AndFilterOperator
          type: object
          required:
            - and
          properties:
            and:
              type: array
              items:
                $ref: '#/components/schemas/ProductPropertyFilter'
              description: All of these filters must match.
          additionalProperties: false
        - title: OrFilterOperator
          type: object
          required:
            - or
          properties:
            or:
              type: array
              items:
                $ref: '#/components/schemas/ProductPropertyFilter'
              description: At least one of these filters must match.
          additionalProperties: false
        - title: NotFilterOperator
          type: object
          required:
            - not
          properties:
            not:
              $ref: '#/components/schemas/ProductPropertyFilter'
              description: Negate this filter.
          additionalProperties: false
    ProductSortOptionName:
      description: Sort by product name in a given locale.
      type: object
      required:
        - name
      properties:
        name:
          type: object
          required:
            - direction
            - locale
          properties:
            direction:
              type: string
              enum:
                - ASC
                - DESC
            locale:
              type: string
              enum:
                - en
                - nl
                - fr
                - de
                - es
                - it
                - pl
              description: Language code for the name sort.
      additionalProperties: false
    ProductSortOptionAuto:
      description: Sort by relevance (descending). Optional locale for localized relevance.
      type: object
      required:
        - auto
      properties:
        auto:
          type: object
          properties:
            locale:
              type: string
              enum:
                - ar
                - bg
                - cs
                - de
                - en
                - es
                - fr
                - hu
                - it
                - nl
                - pl
                - pt
                - ro
                - ru
      additionalProperties: false
    ProductSortOptionField:
      description: 'Sort by a single field (ASC or DESC). Allowed keys: id, publicPrice, createdAt, touchedAt, statusTouchedAt, status, pbs, pzn, pznAustria, cnk, sukl, pdk, cefip, nationalCode, cn, ndc, upc10, upc11, upc12, hamacherCode, hri, pin. Region-specific (e.g. pzn vs pznAustria) may apply.'
      type: object
      minProperties: 1
      maxProperties: 1
      additionalProperties:
        type: string
        enum:
          - ASC
          - DESC
    ProductSortOption:
      description: |-
        A single sort clause. Exactly one key per object.
        - **Simple fields** (value `ASC` or `DESC`): id, publicPrice, createdAt, touchedAt, statusTouchedAt, status, pbs, pzn, pznAustria, cnk, sukl, pdk, cefip, nationalCode, cn, ndc, upc10, upc11, upc12, hamacherCode, hri, pin
        - **name**: value is object with required `direction` (ASC|DESC) and `locale` (language code)
        - **auto**: value is object with optional `locale`; sorts by relevance (descending)
        Default when sorting is omitted is id ascending.
      oneOf:
        - $ref: '#/components/schemas/ProductSortOptionName'
        - $ref: '#/components/schemas/ProductSortOptionAuto'
        - $ref: '#/components/schemas/ProductSortOptionField'
      example:
        id: ASC
    RelatedResource:
      type: object
      properties:
        id:
          type: string
          format: uuid
          examples:
            - 123e4567-e89b-12d3-a456-426614174000
            - e2b1c7a2-4f3d-4e2a-9b1a-7c8e2f1d5a3b
        resource_url:
          type: string
          format: uri
          examples:
            - https://api.example.com/relatedresource/123e4567-e89b-12d3-a456-426614174000
            - https://api.example.com/relatedresource/e2b1c7a2-4f3d-4e2a-9b1a-7c8e2f1d5a3b
    Product:
      type: object
      properties:
        id:
          type: string
          pattern: ^M[0-9A-Z]{9}$
          description: Product ID in Medipim format (letter M followed by 9 alphanumeric characters).
          examples:
            - M00000001A
            - M1A2B3C4D5
        name:
          type: string
          examples:
            - Diphantoine 100mg Comp 100
        publicCategories:
          type: array
          items:
            type: string
            format: uuid
          examples:
            - - fa3a6c1c-9e8d-4bb8-9515-31221415f04a
              - 2ed61e20-ac19-4989-8c0d-c2b3a8287087
        descriptions:
          type: array
          items:
            $ref: '#/components/schemas/RelatedResource'
    PaginatedProductResponse:
      type: object
      properties:
        meta:
          type: object
          properties:
            total:
              type: integer
              description: |-
                The total number of products matching the query, capped at 10,000.
                If the actual total exceeds 10,000, this will show 10,000 and `totalExceedsLimit` will be `true`.
              example: 10000
            totalExceedsLimit:
              type: boolean
              description: |-
                Indicates that the total number of matching products exceeds the pagination limit of 10,000.
                When `true`, you cannot retrieve all matching products using this endpoint.
                **Use the `/products/stream` endpoint instead to get all results.**
              example: true
            page:
              type: object
              properties:
                'no':
                  type: integer
                  description: Current page number (0-based)
                  example: 0
                offset:
                  type: integer
                  description: Current offset in results
                  example: 0
                size:
                  type: integer
                  description: Page size
                  example: 250
        results:
          type: array
          items:
            $ref: '#/components/schemas/Product'
    MediaItem:
      type: object
      properties:
        id:
          type: string
          format: uuid
          examples:
            - 123e4567-e89b-12d3-a456-426614174000
        mediaType:
          type: string
          examples:
            - image
            - document
        locales:
          type: array
          items:
            type: string
          examples:
            - - nl_BE
              - fr_FR
        photoType:
          type: string
          examples:
            - packshot
        visibleSides:
          type: array
          items:
            type: string
          examples:
            - - front
              - back
        hasTransparency:
          type: boolean
          examples:
            - true
            - false
        original:
          type: string
          format: uri
          examples:
            - https://cdn.internal/media_items/123e4567-e89b-12d3-a456-426614174000/original.jpg
        isCentralised:
          type: boolean
          description: Indicates if the media item is stored in a central repository.
          examples:
            - true
            - false
        products:
          type: array
          items:
            $ref: '#/components/schemas/RelatedResource'
    LocalizedString:
      type: object
      properties:
        nl:
          type: string
          example: Een voorbeeldtekst in het Nederlands.
        fr:
          type: string
          example: Un texte d'exemple en français.
        en:
          type: string
          example: An example text in English.
        de:
          type: string
          example: Ein Beispieltext auf Deutsch.
    PublicCategory:
      type: object
      properties:
        id:
          type: integer
          example: 1
        name:
          $ref: '#/components/schemas/LocalizedString'
          description: The name of the category in multiple languages.
          example:
            nl: Geneesmiddelen
            fr: Médicaments
            en: Medicines
            de: Arzneimittel
        parent:
          type:
            - integer
            - 'null'
          description: The id of the parent category, or null if it has no parent.
          example: null
        order:
          type: integer
          description: This field is deprecated and will be removed in future versions.
          example: 1
        meta:
          type: object
          properties:
            createdAt:
              type: integer
              format: unix-time
              examples:
                - 1625247600
                - 1625334000
            updatedAt:
              type: integer
              format: unix-time
              examples:
                - 1625247600
                - 1625334000
    PublicCategoryTreeCategory:
      allOf:
        - $ref: '#/components/schemas/PublicCategory'
        - type: object
          properties:
            children:
              type: array
              items:
                $ref: '#/components/schemas/PublicCategoryTreeCategory'
    OrganizationPropertyFilter:
      description: A property filter. The object must contain exactly one key; that key must be one of the following. Multiple keys (e.g. id and public together) are invalid; use an `and` filter to combine conditions.
      oneOf:
        - title: organizationIdFilter
          type: object
          required:
            - id
          properties:
            id:
              oneOf:
                - type: integer
                  description: Organization ID.
                - type: array
                  items:
                    type: integer
                  description: Organization IDs (match any).
          additionalProperties: false
        - title: organizationTypeFilter
          type: object
          required:
            - type
          properties:
            type:
              type: string
              enum:
                - supplier
                - marketing
                - medical_professional
                - other
              description: Organization type.
          additionalProperties: false
        - title: organizationNameFilter
          type: object
          required:
            - name
          properties:
            name:
              type: string
              description: Organization name.
          additionalProperties: false
        - title: SearchFilter
          type: object
          required:
            - search
          properties:
            search:
              type: string
              description: Search in name and identifiers.
          additionalProperties: false
        - title: searchNameFilter
          type: object
          required:
            - searchName
          properties:
            searchName:
              type: string
              description: Search in name.
          additionalProperties: false
        - title: specializationsFilter
          type: object
          required:
            - specializations
          properties:
            specializations:
              type: array
              items:
                type: integer
              description: List of public category IDs to filter by specialization. The organization must have at least one of these specializations.
          additionalProperties: false
        - title: publicFilter
          type: object
          required:
            - public
          properties:
            public:
              type: boolean
              description: Whether the organization is public or non-public. Non-public organizations are only visible to users with the appropriate permissions.
          additionalProperties: false
        - title: sysId
          type: object
          required:
            - sysId
          properties:
            sysId:
              type: string
              description: Some organizations are 'system' organizations. Those have a special string identifier based on their name.
          additionalProperties: false
        - title: externalId
          type: object
          required:
            - externalId
          properties:
            externalId:
              type: string
              description: External identifier.
          additionalProperties: false
        - title: createdByFilter
          type: object
          required:
            - createdBy
          properties:
            createdBy:
              type: integer
              description: User ID of creator.
          additionalProperties: false
        - title: resellerId
          type: object
          required:
            - resellerId
          properties:
            resellerId:
              type: string
              description: Reseller organization ID.
          additionalProperties: false
      example:
        type: supplier
    OrganizationFilter:
      description: Filter object with exactly one key. Either a property filter (one of id, type, name, etc.) or a compound filter with key `and` (array of filter objects, all must match) or `or` (array of filter objects, at least one must match). Each element in an and/or array has the same structure.
      oneOf:
        - $ref: '#/components/schemas/OrganizationPropertyFilter'
        - title: and
          type: object
          required:
            - and
          properties:
            and:
              type: array
              items:
                $ref: '#/components/schemas/OrganizationPropertyFilter'
              description: All of these filters must match.
          additionalProperties: false
        - title: or
          type: object
          required:
            - or
          properties:
            or:
              type: array
              items:
                $ref: '#/components/schemas/OrganizationPropertyFilter'
              description: At least one of these filters must match.
          additionalProperties: false
    OrganizationSortOption:
      description: A single sort clause. Exactly one of id, name, or city with value ASC or DESC.
      oneOf:
        - type: object
          required:
            - id
          properties:
            id:
              type: string
              enum:
                - ASC
                - DESC
          additionalProperties: false
        - type: object
          required:
            - name
          properties:
            name:
              type: string
              enum:
                - ASC
                - DESC
          additionalProperties: false
        - type: object
          required:
            - city
          properties:
            city:
              type: string
              enum:
                - ASC
                - DESC
          additionalProperties: false
      example:
        name: ASC
    Organization:
      type: object
      description: Organization entity (customer, supplier, or other type).
      properties:
        id:
          type: string
          description: Organization ID.
          example: '12345'
        name:
          type: string
          description: Organization name.
          example: Example Pharma
        type:
          type: string
          description: Organization type (e.g. supplier, customer).
        brands:
          type: array
          items:
            type: integer
          description: Associated brand IDs.
        productFamilies:
          type: array
          items:
            type: integer
          description: Associated product family IDs.
        meta:
          type: object
          properties:
            createdAt:
              type: integer
              format: unix-time
            updatedAt:
              type: integer
              format: unix-time
        contactInformation:
          type: object
          description: Present for supplier-type organizations.
          properties:
            address:
              type: string
            city:
              type: string
            region:
              type: string
            zipcode:
              type: string
            country:
              type: string
            url:
              type: string
              format: uri
    PaginatedOrganizationResponse:
      type: object
      properties:
        meta:
          type: object
          properties:
            total:
              type: integer
              description: Total number of organizations matching the query.
            totalExceedsLimit:
              type: boolean
              description: True if the total exceeds the pagination limit.
            page:
              type: object
              properties:
                'no':
                  type: integer
                  description: Current page number (0-based)
                offset:
                  type: integer
                  description: Current offset in results
                size:
                  type: integer
                  description: Page size
        results:
          type: array
          items:
            $ref: '#/components/schemas/Organization'
    OrganizationSubscriptionData:
      type: object
      description: Subscription check result for organizations matching a filter.
      properties:
        organization:
          type: string
          description: Organization ID.
        name:
          type: string
          description: Organization name.
        activeSubscriptions:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
              name:
                type: string
              start:
                type: integer
                format: unix-time
              end:
                type: integer
                format: unix-time
        apiKeys:
          type: array
          description: API keys associated with the organization.
    BrandPropertyFilter:
      description: A single property filter. Exactly one key per object.
      oneOf:
        - type: object
          required:
            - search
          properties:
            search:
              type: string
              description: Search in brand name.
          additionalProperties: false
        - type: object
          required:
            - id
          properties:
            id:
              oneOf:
                - type: integer
                  description: Single brand ID.
                - type: array
                  items:
                    type: integer
                  description: Brand IDs (match any).
          additionalProperties: false
        - type: object
          required:
            - in
          properties:
            in:
              oneOf:
                - type: integer
                  description: Single brand ID.
                - type: array
                  items:
                    type: integer
                  description: Brand IDs (match any).
          additionalProperties: false
        - type: object
          required:
            - assignable
          properties:
            assignable:
              type: boolean
              description: Filter by brands assignable to the authenticated user's organization.
          additionalProperties: false
        - type: object
          required:
            - deleted
          properties:
            deleted:
              type: boolean
              description: Include or exclude pre-deleted (soft-deleted) brands.
          additionalProperties: false
    BrandFilter:
      description: Filter object with exactly one key. Either a property filter (search, id, in, assignable, deleted) or a compound filter with key `and` (array of filter objects, all must match) or `or` (array of filter objects, at least one must match) or `not` (single filter object to negate).
      oneOf:
        - $ref: '#/components/schemas/BrandPropertyFilter'
        - type: object
          required:
            - and
          properties:
            and:
              type: array
              items:
                $ref: '#/components/schemas/BrandFilter'
              description: All of these filters must match.
          additionalProperties: false
        - type: object
          required:
            - or
          properties:
            or:
              type: array
              items:
                $ref: '#/components/schemas/BrandFilter'
              description: At least one of these filters must match.
          additionalProperties: false
        - type: object
          required:
            - not
          properties:
            not:
              $ref: '#/components/schemas/BrandPropertyFilter'
              description: Negate this filter.
          additionalProperties: false
    BrandSortOption:
      description: A single sort clause. Exactly one of id, name, or product_count with value ASC or DESC.
      oneOf:
        - type: object
          required:
            - id
          properties:
            id:
              type: string
              enum:
                - ASC
                - DESC
          additionalProperties: false
        - type: object
          required:
            - name
          properties:
            name:
              type: string
              enum:
                - ASC
                - DESC
          additionalProperties: false
        - type: object
          required:
            - product_count
          properties:
            product_count:
              type: string
              enum:
                - ASC
                - DESC
          additionalProperties: false
    Brand:
      type: object
      description: A brand (manufacturer or label) associated with products.
      properties:
        id:
          type: integer
          description: Brand ID.
        name:
          type: string
          description: Brand name.
        meta:
          type: object
          properties:
            createdAt:
              type: integer
              format: unix-time
              description: Creation timestamp.
            updatedAt:
              type: integer
              format: unix-time
              description: Last update timestamp.
    PaginatedBrandResponse:
      type: object
      description: Paginated list of brands.
      properties:
        meta:
          type: object
          properties:
            total:
              type: integer
              description: Total number of brands matching the query.
            totalExceedsLimit:
              type: boolean
              description: True if the total exceeds the pagination limit (when applicable).
            page:
              type: object
              properties:
                'no':
                  type: integer
                  description: Current page number (0-based).
                offset:
                  type: integer
                  description: Current offset in results.
                size:
                  type: integer
                  description: Page size.
        results:
          type: array
          items:
            $ref: '#/components/schemas/Brand'
    DietaryRestrictionPropertyFilter:
      description: A single property filter for dietary restrictions. Exactly one key per object.
      oneOf:
        - type: object
          required:
            - id
          properties:
            id:
              oneOf:
                - $ref: '#/components/schemas/DietaryRestrictionId'
                - type: array
                  items:
                    $ref: '#/components/schemas/DietaryRestrictionId'
                  description: Dietary restriction IDs (match any).
          additionalProperties: false
    DietaryRestrictionFilter:
      description: Filter object with exactly one key. Either a property filter (`id` – single dietary restriction ID or array of IDs, match any) or a compound filter with key `and` (array of filter objects, all must match), `or` (array of filter objects, at least one must match), or `not` (single filter object to negate).
      oneOf:
        - $ref: '#/components/schemas/DietaryRestrictionPropertyFilter'
        - type: object
          required:
            - and
          properties:
            and:
              type: array
              items:
                $ref: '#/components/schemas/DietaryRestrictionPropertyFilter'
              description: All of these filters must match.
          additionalProperties: false
        - type: object
          required:
            - or
          properties:
            or:
              type: array
              description: At least one of these filters must match.
          additionalProperties: false
        - type: object
          required:
            - not
          properties:
            not:
              $ref: '#/components/schemas/DietaryRestrictionPropertyFilter'
              description: Negate this filter.
          additionalProperties: false
    DietaryRestriction:
      type: object
      description: A dietary restriction (e.g. allergen or diet suitability).
      properties:
        id:
          $ref: '#/components/schemas/DietaryRestrictionId'
        name:
          $ref: '#/components/schemas/LocalizedString'
          description: Name of the dietary restriction in multiple languages.
  responses:
    UnauthorizedResponse:
      description: Unauthorized
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: object
                properties:
                  status:
                    type: integer
                    const: 401
                  code:
                    type: string
                    const: authentication.not_authenticated
                  message:
                    type: string
                    const: Please provide your API key and secret
    ForbiddenResponse:
      description: Forbidden
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: object
                properties:
                  status:
                    type: integer
                    const: 403
                  code:
                    type: string
                    const: authentication.invalid_api_secret
                  message:
                    type: string
                    const: ''
    UnprocessableEntityResponse:
      description: Unprocessable Entity
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: object
                properties:
                  status:
                    type: integer
                    const: 422
                  code:
                    type: string
                    const: validation_failed
                  message:
                    type: string
                    example: 'Unknown filter: string (at `filter`)'
                  violations:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                          example: Invalid filter syntax (at `filter`)
                        path:
                          type: string
                          example: 'Unknown filter: string (at `filter`)'
                        value:
                          type: string
                      required:
                        - message
                        - path
