openapi: 3.1.0
info:
  title: Merchant Service
  version: 2026-08-09.2745644872
  description: Merchant-facing API. Endpoints for listing accessible merchants,
    reading/updating the merchant profile, and managing communication endpoints
    — the shared inboxes that receive merchant-level notifications.
servers:
  - url: https://api-1.test.logitrail.com
    description: Test / Development Server
  - url: https://api-1.logitrail.com
    description: Production Server
paths:
  /v1/me/merchants:
    get:
      summary: List merchants accessible to the current user
      description: Returns merchants the authenticated user can access based on their
        Keycloak token.
      operationId: GetCurrentUserMerchants
      security:
        - idp: []
      parameters: []
      responses:
        "200":
          description: Merchants accessible to the authenticated user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  merchants:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: Merchant identifier.
                        name:
                          type: string
                          description: Display name of the merchant.
                        status:
                          type: string
                          enum:
                            - active
                            - disabled
                          description: Merchant operational status — `active` or `disabled`.
                        vat_id:
                          anyOf:
                            - type: string
                            - type: "null"
                          description: Merchant VAT identifier. Null when unset.
                      required:
                        - id
                        - name
                        - status
                        - vat_id
                      additionalProperties: false
                    description: Merchants accessible to the authenticated user.
                required:
                  - merchants
                additionalProperties: false
        "400":
          description: Validation error, see response body for details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: A brief, human readable error message.
                  error_code:
                    type: string
                    const: VALIDATION_ERROR
                    description: Reason of the error.
                  validation_errors:
                    type: array
                    items: {}
                    description: An array of validation error details.
                required:
                  - message
                  - error_code
                  - validation_errors
                additionalProperties: false
  /v1/merchant-profile:
    get:
      summary: Get merchant profile
      description: Returns the full profile of the active merchant identified by the
        x-logitrail-merchant-id header.
      operationId: GetMerchantProfile
      security:
        - idp:
            - merchant-profile:manage
      parameters:
        - in: header
          name: x-logitrail-merchant-id
          schema:
            type: string
            minLength: 1
            description: Logitrail's Merchant ID.
          required: true
          description: Logitrail's Merchant ID.
      responses:
        "200":
          description: Merchant profile.
          content:
            application/json:
              schema:
                type: object
                properties:
                  merchant_profile:
                    type: object
                    properties:
                      id:
                        type: string
                        description: Merchant identifier.
                      status:
                        type: string
                        enum:
                          - active
                          - disabled
                        description: Merchant status — active or disabled.
                      official_name:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: Legal company name.
                      name:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: Brand/display name.
                      address:
                        anyOf:
                          - type: object
                            properties:
                              street:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Street address.
                              postal_code:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Postal code.
                              city:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: City.
                              country:
                                anyOf:
                                  - type: string
                                    minLength: 2
                                    maxLength: 2
                                  - type: "null"
                                description: ISO 3166-1 alpha-2 country code.
                            required:
                              - street
                              - postal_code
                              - city
                              - country
                            additionalProperties: false
                          - type: "null"
                        description: Merchant address.
                      vat_id:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: VAT identifier.
                      business_id:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: Business identity code (Y-tunnus).
                      eori:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: EORI number for EU customs.
                      voec:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: VOEC number (Norway).
                      hmrc:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: HMRC VAT number (UK).
                      ioss:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: IOSS number for EU imports.
                      ioss_issuer_country:
                        anyOf:
                          - type: string
                            minLength: 2
                            maxLength: 2
                          - type: "null"
                        description: ISO 3166-1 alpha-2 country code of the IOSS issuer.
                      gs1_company_id:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: GS1 Company Prefix.
                      customer_service:
                        anyOf:
                          - type: object
                            properties:
                              email:
                                anyOf:
                                  - type: string
                                    format: email
                                    pattern: ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
                                  - type: "null"
                                description: Customer service email address.
                              phone:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Customer service phone number.
                            required:
                              - email
                              - phone
                            additionalProperties: false
                          - type: "null"
                        description: Customer service contact.
                      invoicing:
                        anyOf:
                          - type: object
                            properties:
                              mode:
                                type: string
                                enum:
                                  - email
                                  - finvoice
                                description: Invoicing method.
                              email_recipient:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Email recipient for email invoicing.
                              finvoice_address:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Finvoice EDI address. Required when mode is finvoice.
                              finvoice_operator_id:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Finvoice operator ID. Required when mode is finvoice.
                              payment_term_days:
                                anyOf:
                                  - type: integer
                                    minimum: -9007199254740991
                                    maximum: 9007199254740991
                                  - type: "null"
                                description: Payment term in days. Read-only via public API.
                            required:
                              - mode
                              - email_recipient
                              - finvoice_address
                              - finvoice_operator_id
                              - payment_term_days
                            additionalProperties: false
                          - type: "null"
                        description: Invoicing details including payment terms.
                      logo_url:
                        anyOf:
                          - type: string
                            format: uri
                          - type: "null"
                        description: Logo image URL. Null until uploaded (see DEV-1372).
                      tracking:
                        type: object
                        properties:
                          requires_batch_number:
                            type: boolean
                            description: Merchant-level default requiring a batch/lot number at intake for
                              every product of this merchant, regardless of the
                              per-product setting.
                          requires_best_before_date:
                            type: boolean
                            description: Merchant-level default requiring a best-before date at intake for
                              every product of this merchant, regardless of the
                              per-product setting.
                        required:
                          - requires_batch_number
                          - requires_best_before_date
                        additionalProperties: false
                        description: Merchant-level intake requirement defaults. Always present; both
                          flags default to false. OR-combined with the
                          per-product setting, never overriding it.
                    required:
                      - id
                      - status
                      - official_name
                      - name
                      - address
                      - vat_id
                      - business_id
                      - eori
                      - voec
                      - hmrc
                      - ioss
                      - ioss_issuer_country
                      - gs1_company_id
                      - customer_service
                      - invoicing
                      - logo_url
                      - tracking
                    additionalProperties: false
                required:
                  - merchant_profile
                additionalProperties: false
        "400":
          description: Validation error, see response body for details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: A brief, human readable error message.
                  error_code:
                    type: string
                    const: VALIDATION_ERROR
                    description: Reason of the error.
                  validation_errors:
                    type: array
                    items: {}
                    description: An array of validation error details.
                required:
                  - message
                  - error_code
                  - validation_errors
                additionalProperties: false
    patch:
      summary: Update merchant profile
      description: Updates editable fields of the active merchant profile. PATCH
        semantics — only supplied fields are updated. Read-only fields (id,
        status, invoicing.payment_term_days, logo_url) are not accepted.
      operationId: PatchMerchantProfile
      security:
        - idp:
            - merchant-profile:manage
      parameters:
        - in: header
          name: x-logitrail-merchant-id
          schema:
            type: string
            minLength: 1
            description: Logitrail's Merchant ID.
          required: true
          description: Logitrail's Merchant ID.
      responses:
        "200":
          description: Updated merchant profile.
          content:
            application/json:
              schema:
                type: object
                properties:
                  merchant_profile:
                    type: object
                    properties:
                      id:
                        type: string
                        description: Merchant identifier.
                      status:
                        type: string
                        enum:
                          - active
                          - disabled
                        description: Merchant status — active or disabled.
                      official_name:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: Legal company name.
                      name:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: Brand/display name.
                      address:
                        anyOf:
                          - type: object
                            properties:
                              street:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Street address.
                              postal_code:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Postal code.
                              city:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: City.
                              country:
                                anyOf:
                                  - type: string
                                    minLength: 2
                                    maxLength: 2
                                  - type: "null"
                                description: ISO 3166-1 alpha-2 country code.
                            required:
                              - street
                              - postal_code
                              - city
                              - country
                            additionalProperties: false
                          - type: "null"
                        description: Merchant address.
                      vat_id:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: VAT identifier.
                      business_id:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: Business identity code (Y-tunnus).
                      eori:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: EORI number for EU customs.
                      voec:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: VOEC number (Norway).
                      hmrc:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: HMRC VAT number (UK).
                      ioss:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: IOSS number for EU imports.
                      ioss_issuer_country:
                        anyOf:
                          - type: string
                            minLength: 2
                            maxLength: 2
                          - type: "null"
                        description: ISO 3166-1 alpha-2 country code of the IOSS issuer.
                      gs1_company_id:
                        anyOf:
                          - type: string
                          - type: "null"
                        description: GS1 Company Prefix.
                      customer_service:
                        anyOf:
                          - type: object
                            properties:
                              email:
                                anyOf:
                                  - type: string
                                    format: email
                                    pattern: ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
                                  - type: "null"
                                description: Customer service email address.
                              phone:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Customer service phone number.
                            required:
                              - email
                              - phone
                            additionalProperties: false
                          - type: "null"
                        description: Customer service contact.
                      invoicing:
                        anyOf:
                          - type: object
                            properties:
                              mode:
                                type: string
                                enum:
                                  - email
                                  - finvoice
                                description: Invoicing method.
                              email_recipient:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Email recipient for email invoicing.
                              finvoice_address:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Finvoice EDI address. Required when mode is finvoice.
                              finvoice_operator_id:
                                anyOf:
                                  - type: string
                                  - type: "null"
                                description: Finvoice operator ID. Required when mode is finvoice.
                              payment_term_days:
                                anyOf:
                                  - type: integer
                                    minimum: -9007199254740991
                                    maximum: 9007199254740991
                                  - type: "null"
                                description: Payment term in days. Read-only via public API.
                            required:
                              - mode
                              - email_recipient
                              - finvoice_address
                              - finvoice_operator_id
                              - payment_term_days
                            additionalProperties: false
                          - type: "null"
                        description: Invoicing details including payment terms.
                      logo_url:
                        anyOf:
                          - type: string
                            format: uri
                          - type: "null"
                        description: Logo image URL. Null until uploaded (see DEV-1372).
                      tracking:
                        type: object
                        properties:
                          requires_batch_number:
                            type: boolean
                            description: Merchant-level default requiring a batch/lot number at intake for
                              every product of this merchant, regardless of the
                              per-product setting.
                          requires_best_before_date:
                            type: boolean
                            description: Merchant-level default requiring a best-before date at intake for
                              every product of this merchant, regardless of the
                              per-product setting.
                        required:
                          - requires_batch_number
                          - requires_best_before_date
                        additionalProperties: false
                        description: Merchant-level intake requirement defaults. Always present; both
                          flags default to false. OR-combined with the
                          per-product setting, never overriding it.
                    required:
                      - id
                      - status
                      - official_name
                      - name
                      - address
                      - vat_id
                      - business_id
                      - eori
                      - voec
                      - hmrc
                      - ioss
                      - ioss_issuer_country
                      - gs1_company_id
                      - customer_service
                      - invoicing
                      - logo_url
                      - tracking
                    additionalProperties: false
                required:
                  - merchant_profile
                additionalProperties: false
        "400":
          description: Validation error, see response body for details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: A brief, human readable error message.
                  error_code:
                    type: string
                    const: VALIDATION_ERROR
                    description: Reason of the error.
                  validation_errors:
                    type: array
                    items: {}
                    description: An array of validation error details.
                required:
                  - message
                  - error_code
                  - validation_errors
                additionalProperties: false
  /v1/merchant-communication-endpoints:
    get:
      summary: List merchant communication endpoints
      description: Returns the shared-inbox contact records (email/SMS) configured for
        the active merchant.
      operationId: ListMerchantCommunicationEndpoints
      security:
        - idp:
            - merchant-profile:manage
      parameters:
        - in: header
          name: x-logitrail-merchant-id
          schema:
            type: string
            minLength: 1
            description: Logitrail's Merchant ID.
          required: true
          description: Logitrail's Merchant ID.
      responses:
        "200":
          description: Communication endpoints for the merchant.
          content:
            application/json:
              schema:
                type: object
                properties:
                  endpoints:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          minLength: 24
                          maxLength: 24
                          description: MongoDB ObjectId hex string identifying the endpoint.
                        channel:
                          type: string
                          enum:
                            - email
                            - sms
                        address:
                          type: string
                          description: Delivery address for this channel — an email address or phone
                            number.
                        label:
                          description: Human-readable label, e.g. "Palautusilmoitukset".
                          type: string
                        locale:
                          description: Optional per-endpoint locale override. Falls back to the merchant
                            locale chain when absent.
                          type: string
                      required:
                        - id
                        - channel
                        - address
                      additionalProperties: false
                required:
                  - endpoints
                additionalProperties: false
        "400":
          description: Validation error, see response body for details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: A brief, human readable error message.
                  error_code:
                    type: string
                    const: VALIDATION_ERROR
                    description: Reason of the error.
                  validation_errors:
                    type: array
                    items: {}
                    description: An array of validation error details.
                required:
                  - message
                  - error_code
                  - validation_errors
                additionalProperties: false
    post:
      summary: Create a merchant communication endpoint
      description: Adds a shared-inbox contact record to the active merchant. Admin
        attestation only — no address verification.
      operationId: CreateMerchantCommunicationEndpoint
      security:
        - idp:
            - merchant-profile:manage
      parameters:
        - in: header
          name: x-logitrail-merchant-id
          schema:
            type: string
            minLength: 1
            description: Logitrail's Merchant ID.
          required: true
          description: Logitrail's Merchant ID.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channel:
                  type: string
                  enum:
                    - email
                    - sms
                address:
                  type: string
                  minLength: 1
                  description: Delivery address for this channel.
                label:
                  description: Human-readable label.
                  type: string
                  minLength: 1
                locale:
                  description: Optional per-endpoint locale override.
                  type: string
              required:
                - channel
                - address
      responses:
        "201":
          description: Created endpoint.
          content:
            application/json:
              schema:
                type: object
                properties:
                  endpoint:
                    type: object
                    properties:
                      id:
                        type: string
                        minLength: 24
                        maxLength: 24
                        description: MongoDB ObjectId hex string identifying the endpoint.
                      channel:
                        type: string
                        enum:
                          - email
                          - sms
                      address:
                        type: string
                        description: Delivery address for this channel — an email address or phone
                          number.
                      label:
                        description: Human-readable label, e.g. "Palautusilmoitukset".
                        type: string
                      locale:
                        description: Optional per-endpoint locale override. Falls back to the merchant
                          locale chain when absent.
                        type: string
                    required:
                      - id
                      - channel
                      - address
                    additionalProperties: false
                required:
                  - endpoint
                additionalProperties: false
        "400":
          description: Validation error, see response body for details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: A brief, human readable error message.
                  error_code:
                    type: string
                    const: VALIDATION_ERROR
                    description: Reason of the error.
                  validation_errors:
                    type: array
                    items: {}
                    description: An array of validation error details.
                required:
                  - message
                  - error_code
                  - validation_errors
                additionalProperties: false
  /v1/merchant-communication-endpoints/{id}:
    patch:
      summary: Update a merchant communication endpoint
      description: Partially updates address, label, or locale override for one
        endpoint. Channel is immutable after creation.
      operationId: PatchMerchantCommunicationEndpoint
      security:
        - idp:
            - merchant-profile:manage
      parameters:
        - in: header
          name: x-logitrail-merchant-id
          schema:
            type: string
            minLength: 1
            description: Logitrail's Merchant ID.
          required: true
          description: Logitrail's Merchant ID.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                address:
                  description: Updated delivery address.
                  type: string
                  minLength: 1
                label:
                  description: Updated label.
                  type: string
                  minLength: 1
                locale:
                  description: Updated locale override, or null to clear it.
                  anyOf:
                    - type: string
                    - type: "null"
      responses:
        "200":
          description: Updated endpoint.
          content:
            application/json:
              schema:
                type: object
                properties:
                  endpoint:
                    type: object
                    properties:
                      id:
                        type: string
                        minLength: 24
                        maxLength: 24
                        description: MongoDB ObjectId hex string identifying the endpoint.
                      channel:
                        type: string
                        enum:
                          - email
                          - sms
                      address:
                        type: string
                        description: Delivery address for this channel — an email address or phone
                          number.
                      label:
                        description: Human-readable label, e.g. "Palautusilmoitukset".
                        type: string
                      locale:
                        description: Optional per-endpoint locale override. Falls back to the merchant
                          locale chain when absent.
                        type: string
                    required:
                      - id
                      - channel
                      - address
                    additionalProperties: false
                required:
                  - endpoint
                additionalProperties: false
        "400":
          description: Validation error, see response body for details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: A brief, human readable error message.
                  error_code:
                    type: string
                    const: VALIDATION_ERROR
                    description: Reason of the error.
                  validation_errors:
                    type: array
                    items: {}
                    description: An array of validation error details.
                required:
                  - message
                  - error_code
                  - validation_errors
                additionalProperties: false
        "404":
          description: Endpoint not found
          content:
            application/json:
              schema: {}
    delete:
      summary: Delete a merchant communication endpoint
      description: Removes the contact record. Existing per-type subscription rows for
        this endpoint are not cleaned up.
      operationId: DeleteMerchantCommunicationEndpoint
      security:
        - idp:
            - merchant-profile:manage
      parameters:
        - in: header
          name: x-logitrail-merchant-id
          schema:
            type: string
            minLength: 1
            description: Logitrail's Merchant ID.
          required: true
          description: Logitrail's Merchant ID.
      responses:
        "204":
          description: Endpoint deleted
        "400":
          description: Validation error, see response body for details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: A brief, human readable error message.
                  error_code:
                    type: string
                    const: VALIDATION_ERROR
                    description: Reason of the error.
                  validation_errors:
                    type: array
                    items: {}
                    description: An array of validation error details.
                required:
                  - message
                  - error_code
                  - validation_errors
                additionalProperties: false
        "404":
          description: Endpoint not found
          content:
            application/json:
              schema: {}
  /v1/merchant-communication-endpoints/{id}/subscriptions/{typeKey}:
    put:
      summary: Subscribe a merchant communication endpoint to a type
      description: Sets enabled/channels/cadence for one communication type on one
        shared-inbox endpoint. Rejects channels or cadence outside the permitted
        set and opting out of a type where optOutAllowed is false.
      operationId: PutMerchantCommunicationEndpointSubscription
      security:
        - idp:
            - merchant-profile:manage
      parameters:
        - in: header
          name: x-logitrail-merchant-id
          schema:
            type: string
            minLength: 1
            description: Logitrail's Merchant ID.
          required: true
          description: Logitrail's Merchant ID.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                channels:
                  type: array
                  items:
                    type: string
                    enum:
                      - email
                      - sms
                cadence:
                  type: string
                  enum:
                    - instant
                    - daily
                    - weekly
              required:
                - enabled
                - channels
                - cadence
      responses:
        "200":
          description: Updated subscription.
          content:
            application/json:
              schema:
                type: object
                properties:
                  typeKey:
                    type: string
                  enabled:
                    type: boolean
                  channels:
                    type: array
                    items:
                      type: string
                  cadence:
                    type: string
                  updatedAt:
                    type: string
                required:
                  - typeKey
                  - enabled
                  - channels
                  - cadence
                  - updatedAt
                additionalProperties: false
        "400":
          description: Validation error, see response body for details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: A brief, human readable error message.
                  error_code:
                    type: string
                    const: VALIDATION_ERROR
                    description: Reason of the error.
                  validation_errors:
                    type: array
                    items: {}
                    description: An array of validation error details.
                required:
                  - message
                  - error_code
                  - validation_errors
                additionalProperties: false
        "404":
          description: Merchant, endpoint, or typeKey not found
          content:
            application/json:
              schema: {}
components:
  securitySchemes:
    idp:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://idp.logitrail.com/realms/logitrail/protocol/openid-connect/token
          scopes:
            merchant-profile:manage: Read and update the merchant profile, including
              communication endpoints (shared inboxes) and their notification
              subscriptions
