openapi: 3.0.3

info:
  version: v1
  title: API OpenDelivery DeliveryVip
  description: >-
    API compatível com o padrão Open Delivery (Abrasel), em que a DeliveryVip atua como
    Ordering Application para Software Services (PDVs e sistemas de gestão).
    A autenticação usa OAuth 2.0 `client_credentials` no endpoint `/oauth/token` deste mesmo
    host, com o escopo `od.all` (tokens sem esse escopo recebem 403). Os tokens são opacos e
    enviados no header `Authorization: Bearer <token>`. Datas são retornadas em UTC (ISO 8601).

servers:
  - url: https://od.deliveryvip.com.br
    description: Produção

security:
  - bearerAuth: []

tags:
  - name: OAuth
    description: Emissão de access tokens para a API OpenDelivery.

  - name: Versions
    description: Versões da API implementadas. Não exigem autenticação.

  - name: Events
    description: >-
      Mudanças de estado e outras notificações dos pedidos das lojas vinculadas ao aplicativo.

  - name: Orders
    description: Detalhes do pedido e ações sobre ele.

  - name: Merchants
    description: Onboarding da loja, abertura/fechamento e atualização de catálogo.

paths:
  /oauth/token:
    post:
      tags:
        - OAuth
      summary: Obter access token
      description: >-
        Emite um access token com `grant_type=client_credentials`. As credenciais podem ser
        enviadas no corpo (`client_id`/`client_secret`) ou via HTTP Basic. Quando o
        `client_secret` é a credencial de uma loja específica (aplicativos com a extensão
        OpenDelivery), o token fica vinculado apenas àquela loja; nesse caso, a loja precisa ter
        o aplicativo instalado. Tokens expiram em 24 horas e não têm `refresh_token`. Envie
        `Content-Type: application/x-www-form-urlencoded`.
      operationId: createToken
      security:
        - basicAuth: []
        - {}
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required:
                - grant_type
              properties:
                grant_type:
                  type: string
                  enum:
                    - client_credentials
                  description: Tipo de concessão OAuth.
                client_id:
                  type: string
                  description: Identificador do aplicativo.
                  example: seu-client-id
                client_secret:
                  type: string
                  description: Segredo do aplicativo ou credencial da loja.
                  example: seu-client-secret
                scope:
                  type: string
                  description: Escopos separados por espaço. Padrão `od.all`.
                  example: od.all
      responses:
        "200":
          description: Token emitido.
          content:
            application/json:
              schema:
                type: object
                properties:
                  access_token:
                    type: string
                    description: Access token opaco.
                    example: 2YotnFZFEjr1zCsicMWpAA
                  token_type:
                    type: string
                    description: Tipo do token, sempre `Bearer`.
                    example: Bearer
                  expires_in:
                    type: integer
                    description: Tempo restante de validade, em segundos.
                    example: 86400
                  scope:
                    type: string
                    description: Escopos concedidos.
                    example: od.all
                  created_at:
                    type: integer
                    description: Momento de emissão (Unix timestamp, em segundos).
                    example: 1639571898
        "400":
          description: Requisição inválida (parâmetro ausente, `grant_type` ou escopo não suportado).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/oauthError"
        "401":
          description: >-
            Credenciais inválidas ou loja sem o aplicativo instalado (`invalid_client`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/oauthError"

  /v1/versions/orderingApp:
    get:
      tags:
        - Versions
      summary: Consultar versão da Ordering Application
      description: >-
        Retorna as versões dos endpoints hospedados pela DeliveryVip como Ordering Application
        e os métodos de entrega de eventos suportados.
      operationId: getOrderingAppVersion
      security: []
      responses:
        "200":
          description: Versões da Ordering Application.
          content:
            application/json:
              schema:
                type: object
                properties:
                  merchant:
                    type: object
                    properties:
                      version:
                        type: string
                        description: Versão dos endpoints de merchant.
                        example: "1.0.0"
                  order:
                    type: object
                    properties:
                      version:
                        type: string
                        description: Versão dos endpoints de pedidos.
                        example: "1.3.0"
                      availableEventsMethods:
                        type: array
                        description: Métodos de entrega de eventos suportados.
                        items:
                          type: string
                          enum:
                            - POLLING
                            - WEBHOOK
                        example:
                          - POLLING
                          - WEBHOOK

  /v1/versions/merchant:
    get:
      tags:
        - Versions
      summary: Consultar versão da API de merchant
      description: >-
        Retorna a versão dos endpoints de merchant que a Ordering Application espera do
        Software Service.
      operationId: getMerchantVersion
      security: []
      responses:
        "200":
          description: Versão da API de merchant.
          content:
            application/json:
              schema:
                type: object
                properties:
                  merchantEndpoint:
                    type: string
                    description: Versão esperada dos endpoints de merchant.
                    example: "1.2.1"

  /v1/events:polling:
    get:
      tags:
        - Events
      summary: Listar eventos
      description: >-
        Retorna os eventos ainda não confirmados pelo aplicativo, das lojas vinculadas ao token,
        criados nas últimas 24 horas. Os eventos vêm em ordem cronológica, no máximo 100 por
        chamada. Cada evento recebido deve ser confirmado em `/v1/events/acknowledgment`; caso
        contrário, continuará sendo retornado nas próximas consultas.
      operationId: pollEvents
      parameters:
        - in: header
          name: x-polling-merchants
          description: >-
            Restringe a consulta a estas lojas. Aceita o `merchantId` informado no onboarding ou o
            identificador interno da loja, separados por vírgula. Todas precisam estar vinculadas
            ao token.
          required: false
          style: simple
          schema:
            type: array
            items:
              type: string
          example:
            - 313AE66A-5AE4-4FD7-A552-A089CD71F063
        - in: query
          name: eventType
          description: >-
            Filtra pelos tipos de evento. Pode ser repetido (`eventType=CREATED&eventType=CANCELLED`)
            ou separado por vírgula.
          required: false
          style: form
          explode: true
          schema:
            type: array
            items:
              $ref: "#/components/schemas/eventType"
        - in: query
          name: orderType
          description: >-
            Filtra pelo tipo do pedido. Pode ser repetido ou separado por vírgula.
          required: false
          style: form
          explode: true
          schema:
            type: array
            items:
              type: string
              enum:
                - DELIVERY
                - TAKEOUT
                - INDOOR
      responses:
        "200":
          description: Eventos pendentes de confirmação.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/event"
        "204":
          description: Nenhum evento disponível.
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: >-
            `eventType`, `orderType` ou `x-polling-merchants` inválido, ou loja não vinculada ao token.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                status: "403"
                title: Invalid eventType
        "406":
          $ref: "#/components/responses/NotAcceptable"

  /v1/events/acknowledgment:
    post:
      tags:
        - Events
      summary: Confirmar recebimento de eventos
      description: >-
        Confirma o recebimento de eventos. Eventos confirmados deixam de ser retornados no
        polling. Identificadores desconhecidos ou de lojas não vinculadas ao token são ignorados
        e não entram no total.
      operationId: acknowledgeEvents
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              minItems: 1
              items:
                type: object
                required:
                  - id
                properties:
                  id:
                    type: string
                    format: uuid
                    description: '`eventId` do evento recebido no polling.'
            example:
              - id: 8a6f6c1e-0d3b-4c1a-9a57-0b1c2d3e4f50
      responses:
        "202":
          description: Confirmação aceita.
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    description: Quantidade de eventos efetivamente confirmados.
                    example: 1
        "401":
          $ref: "#/components/responses/Unauthorized"
        "406":
          $ref: "#/components/responses/NotAcceptable"
        "422":
          description: Lista de eventos vazia.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /v1/orders/{orderId}:
    get:
      tags:
        - Orders
      summary: Consultar pedido
      description: >-
        Retorna os detalhes de um pedido de uma loja vinculada ao token. Pedidos aguardando
        pagamento ou não pagos não são retornados.
      operationId: getOrder
      parameters:
        - $ref: "#/components/parameters/orderId"
        - in: query
          name: views
          description: >-
            Formato dos complementos dos itens. Sem o parâmetro, cada item traz `options` (lista
            plana). `optionGroups` retorna `items[].optionGroups` e `groupOptions` retorna
            `items[].optionsGroup`, ambos agrupados por grupo de complemento.
          required: false
          schema:
            type: string
            enum:
              - optionGroups
              - groupOptions
      responses:
        "200":
          description: Detalhes do pedido.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/order"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /v1/orders/{orderId}/confirm:
    post:
      tags:
        - Orders
      summary: Confirmar pedido
      description: >-
        Confirma (aceita) o pedido. Consulte os detalhes do pedido antes de confirmá-lo.
        Um corpo, se enviado, é ignorado.
      operationId: confirmOrder
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "202":
          $ref: "#/components/responses/Action"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/orders/{orderId}/preparing:
    post:
      tags:
        - Orders
      summary: Iniciar preparo
      description: Sinaliza que a loja começou a preparar o pedido.
      operationId: startPreparation
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "202":
          $ref: "#/components/responses/Action"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/orders/{orderId}/readyForPickup:
    post:
      tags:
        - Orders
      summary: Marcar pedido como pronto
      description: Sinaliza que o pedido está pronto para ser retirado ou entregue.
      operationId: readyForPickup
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "202":
          $ref: "#/components/responses/Action"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/orders/{orderId}/pickedUp:
    post:
      tags:
        - Orders
      summary: Marcar pedido como retirado
      description: Sinaliza que o pedido foi retirado pelo cliente (pedidos para retirada).
      operationId: orderPickedUp
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "202":
          $ref: "#/components/responses/Action"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/orders/{orderId}/dispatch:
    post:
      tags:
        - Orders
      summary: Despachar pedido
      description: Sinaliza que o pedido saiu para entrega.
      operationId: dispatchOrder
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "202":
          $ref: "#/components/responses/Action"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/orders/{orderId}/delivered:
    post:
      tags:
        - Orders
      summary: Marcar pedido como entregue
      description: Sinaliza que o pedido foi entregue ao cliente.
      operationId: orderDelivered
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "202":
          $ref: "#/components/responses/Action"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/orders/{orderId}/requestCancellation:
    post:
      tags:
        - Orders
      summary: Cancelar pedido
      description: >-
        Cancela o pedido imediatamente. Um corpo (motivo, código, itens indisponíveis), se
        enviado, é ignorado.
      operationId: requestCancellation
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "200":
          $ref: "#/components/responses/ActionOk"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/orders/{orderId}/acceptCancellation:
    post:
      tags:
        - Orders
      summary: Aceitar cancelamento
      description: >-
        Aceita uma solicitação de cancelamento. Apenas confirma o recebimento: o estado do pedido
        não é alterado.
      operationId: acceptCancellation
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "200":
          $ref: "#/components/responses/ActionOk"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /v1/orders/{orderId}/denyCancellation:
    post:
      tags:
        - Orders
      summary: Recusar cancelamento
      description: >-
        Recusa uma solicitação de cancelamento. Apenas confirma o recebimento: o estado do pedido
        não é alterado.
      operationId: denyCancellation
      parameters:
        - $ref: "#/components/parameters/orderId"
      responses:
        "200":
          $ref: "#/components/responses/ActionOk"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /v1/orders/{orderId}/tracking:
    post:
      tags:
        - Orders
      summary: Enviar rastreamento da entrega
      description: >-
        Atualiza o rastreamento da entrega do pedido: um evento de entrega (`event`) ou uma
        ocorrência (`problem`), com dados opcionais de entregador, veículo, previsões e
        localização.
      operationId: updateTracking
      parameters:
        - $ref: "#/components/parameters/orderId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/deliveryTrackingInfo"
      responses:
        "202":
          $ref: "#/components/responses/Action"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/merchantOnboarding:
    put:
      tags:
        - Merchants
      summary: Fazer onboarding da loja
      description: >-
        Registra (ou atualiza) os dados do Software Service para a loja do token: o seu
        identificador da loja (`merchantId`), a URL e a chave para consulta do merchant
        (getMerchant) e a URL do webhook de pedidos. Responde 201 no primeiro registro e 204 nas
        atualizações.
      operationId: merchantOnboarding
      parameters:
        - in: query
          name: merchantId
          description: Identificador da loja no Software Service.
          required: true
          schema:
            type: string
          example: 313AE66A-5AE4-4FD7-A552-A089CD71F063
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                getMerchantURL:
                  type: object
                  description: Endpoint do Software Service que retorna os dados e o catálogo da loja.
                  properties:
                    baseURL:
                      type: string
                      format: uri
                      description: URL base do endpoint getMerchant.
                      example: https://pdv.exemplo.com.br/
                    apiKey:
                      type: string
                      description: Chave enviada nas chamadas ao getMerchant.
                      example: chave-secreta
                ordersWebhookURL:
                  type: string
                  format: uri
                  description: URL que receberá os eventos de pedido via webhook.
                  example: https://pdv.exemplo.com.br/newEvent
      responses:
        "201":
          description: Onboarding registrado.
        "204":
          description: Onboarding atualizado.
        "400":
          description: '`merchantId` ausente, corpo ausente ou URL inválida.'
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                status: "400"
                title: merchantId is required
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/MultipleMerchants"
        "422":
          description: >-
            O aplicativo não declarou a extensão OpenDelivery
            (`open_delivery_extension_not_declared`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /v1/merchantStatus:
    get:
      tags:
        - Merchants
      summary: Consultar processamento do merchant
      description: >-
        Retorna o resultado do último processamento de atualização da loja disparado por
        `/v1/merchantUpdate` (nova leitura do merchant e do catálogo via getMerchant).
      operationId: getMerchantStatus
      parameters:
        - in: query
          name: merchantId
          description: Identificador da loja no Software Service, informado no onboarding.
          required: true
          schema:
            type: string
          example: 313AE66A-5AE4-4FD7-A552-A089CD71F063
      responses:
        "200":
          description: Resultado do último processamento.
          content:
            application/json:
              schema:
                type: object
                required:
                  - lastRead
                  - status
                properties:
                  lastRead:
                    type: string
                    format: date-time
                    description: Momento da última tentativa de processamento (UTC).
                    example: "2026-09-23T12:00:00Z"
                  status:
                    type: string
                    description: Situação do processamento.
                    enum:
                      - PROCESSING
                      - SUCCESS
                      - FAIL
                    example: SUCCESS
                  moreInfo:
                    type: string
                    description: Motivo da falha. Presente apenas quando `status` é `FAIL`.
                    example: invalid_schema
        "400":
          description: Parâmetro `merchantId` ausente.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          description: >-
            Loja não encontrada para o token (`merchant not found`) ou ainda sem processamento
            (`no processing result`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /v1/merchantUpdate:
    post:
      tags:
        - Merchants
      summary: Atualizar merchant
      description: >-
        Notifica a DeliveryVip de mudanças na loja do token. Modos:


        - corpo vazio: agenda uma nova leitura completa do merchant e do catálogo via getMerchant;

        - apenas `merchantStatus`: abre (`AVAILABLE`) ou fecha (`UNAVAILABLE`) a loja, sem nova leitura;

        - `entityType` com `updatedObjects`: agenda uma nova leitura completa (as entidades
        informadas não são aplicadas individualmente);

        - `merchantStatus` com `entityType`: faz as duas coisas.


        A nova leitura exige onboarding com `getMerchantURL` e é processada de forma assíncrona;
        acompanhe o resultado em `/v1/merchantStatus`.
      operationId: merchantUpdate
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                merchantStatus:
                  type: string
                  description: Novo estado da loja.
                  enum:
                    - AVAILABLE
                    - UNAVAILABLE
                entityType:
                  type: string
                  description: Tipo da entidade alterada. Exige `updatedObjects`.
                  enum:
                    - MERCHANT
                    - BASIC_INFO
                    - SERVICE
                    - MENU
                    - CATEGORY
                    - ITEM
                    - ITEM_OFFER
                    - OPTION_GROUP
                    - OPTION
                    - AVAILABILITY
                updatedObjects:
                  type: array
                  description: Objetos alterados. Obrigatório quando `entityType` é enviado.
                  items:
                    type: object
                    additionalProperties: true
            examples:
              status:
                summary: Fechar a loja
                value:
                  merchantStatus: UNAVAILABLE
              entidades:
                summary: Notificar itens alterados
                value:
                  entityType: ITEM_OFFER
                  updatedObjects:
                    - id: a1b2c3
      responses:
        "204":
          description: Atualização aceita.
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/MultipleMerchants"
        "422":
          description: >-
            Valor inválido de `merchantStatus` ou `entityType`, `entityType` sem `updatedObjects`
            (`objects_empty`), ou nova leitura solicitada sem onboarding com getMerchant
            (`api_info_missing`).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

components:
  parameters:
    orderId:
      in: path
      name: orderId
      description: Identificador (UUID) do pedido.
      required: true
      schema:
        type: string
        format: uuid

  schemas:
    eventType:
      type: string
      enum:
        - CREATED
        - CONFIRMED
        - PREPARING
        - DISPATCHED
        - READY_FOR_PICKUP
        - PICKUP_AREA_ASSIGNED
        - PICKED_UP
        - DELIVERED
        - CONCLUDED
        - CANCELLATION_REQUESTED
        - CANCELLATION_REQUEST_DENIED
        - CANCELLED
        - ORDER_CANCELLATION_REQUEST
        - CALL_WAITER
        - CLOSE_ACCOUNT

    event:
      type: object
      description: >-
        Evento de pedido ou de atendimento em mesa. Eventos de pedido trazem `orderId`,
        `orderURL` e `orderType`; eventos de mesa (`CALL_WAITER`, `CLOSE_ACCOUNT`) trazem os
        campos de local e comanda.
      required:
        - eventId
        - eventType
        - merchantId
        - createdAt
      properties:
        eventId:
          type: string
          format: uuid
          description: Identificador do evento, usado na confirmação.
        eventType:
          $ref: "#/components/schemas/eventType"
        merchantId:
          type: string
          description: >-
            `merchantId` informado no onboarding da loja ou, na ausência dele, o identificador
            interno da loja.
        createdAt:
          type: string
          format: date-time
          description: Momento de criação do evento (UTC).
          example: "2026-10-29T15:04:05Z"
        metadata:
          type: object
          additionalProperties: true
          description: Dados adicionais do evento. Omitido quando vazio.
        orderId:
          type: string
          format: uuid
          description: Identificador do pedido.
        orderURL:
          type: string
          format: uri
          description: URL para consultar o pedido.
          example: https://od.deliveryvip.com.br/v1/orders/aa67c98c-d81f-5a9c-b0bc-26caa0051aea
        orderType:
          type: string
          description: Tipo do pedido.
          enum:
            - DELIVERY
            - TAKEOUT
            - INDOOR
        placeName:
          type: string
          description: Nome do local (mesa). Apenas em eventos de mesa.
        placeId:
          type: string
          description: Identificador do local (mesa). Apenas em eventos de mesa.
        tab:
          type: string
          description: Comanda. Apenas em eventos de mesa.
        tabId:
          type: string
          description: Identificador da comanda. Apenas em eventos de mesa.
        tabCode:
          type: string
          description: Código da comanda. Apenas em eventos de mesa.
        tabName:
          type: string
          description: Nome da comanda. Apenas em eventos de mesa.

    order:
      type: object
      description: Pedido no formato Open Delivery. Datas em UTC (ISO 8601).
      properties:
        id:
          type: string
          format: uuid
          description: Id do pedido.
        type:
          type: string
          description: Tipo do pedido. Pedidos de consumo no local são retornados como `INDOOR`.
          enum:
            - DELIVERY
            - TAKEOUT
            - INDOOR
        displayId:
          type: string
          description: Código curto do pedido, exibido para a loja e o cliente.
        salesChannel:
          type: string
          description: Canal de venda do pedido.
          enum:
            - STORE
            - MARKETPLACE
            - TABLET
            - QRCODE
            - TAB
        createdAt:
          type: string
          format: date-time
          description: Data e hora de criação do pedido.
        orderTiming:
          type: string
          description: Pedido imediato ou agendado.
          enum:
            - INSTANT
            - SCHEDULED
        preparationStartDateTime:
          type: string
          format: date-time
          description: Início previsto do preparo (atualmente igual a `createdAt`).
        lastEvent:
          type: string
          description: >-
            Último evento do pedido, derivado do seu estado atual. Omitido quando o estado não corresponde a
            nenhum destes valores.
          enum:
            - CREATED
            - CONFIRMED
            - READY_FOR_PICKUP
            - CONCLUDED
            - CANCELLED
        merchant:
          type: object
          properties:
            id:
              type: string
              description: >-
                Id da loja: o id que o aplicativo usa para a loja (`orderingAppMerchantId`), quando configurado;
                caso contrário, o UUID da loja na plataforma.
            name:
              type: string
        items:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              index:
                type: integer
                description: Posição do item no pedido.
              name:
                type: string
              externalCode:
                type: string
                description: Código externo do item. Omitido quando vazio.
              unit:
                type: string
                description: Unidade de medida. Sempre `UN`.
                enum:
                  - UN
              ean:
                type: string
                description: Código EAN. Omitido quando vazio.
              quantity:
                type: integer
              specialInstructions:
                type: string
                description: Observação do cliente para o item. Omitida quando vazia.
              unitPrice:
                $ref: "#/components/schemas/money"
              optionsPrice:
                $ref: "#/components/schemas/money"
              totalPrice:
                $ref: "#/components/schemas/money"
              options:
                type: array
                description: Complementos escolhidos (formato padrão). Omitido quando o item não tem complementos.
                items:
                  $ref: "#/components/schemas/orderOption"
              optionGroups:
                type: array
                description: Complementos agrupados (view `optionGroups`).
                items:
                  $ref: "#/components/schemas/orderOptionGroup"
              optionsGroup:
                type: array
                deprecated: true
                description: Complementos agrupados (view `groupOptions`, descontinuada).
                items:
                  $ref: "#/components/schemas/orderOptionGroup"
        otherFees:
          type: array
          description: Taxas do pedido. Presente apenas em pedidos de entrega.
          items:
            type: object
            properties:
              name:
                type: string
              type:
                type: string
                enum:
                  - DELIVERY_FEE
                  - SERVICE_FEE
                  - TIP
                  - MIN_ORDER_FEE
              receivedBy:
                type: string
                enum:
                  - MARKETPLACE
                  - MERCHANT
                  - LOGISTIC_SERVICES
              receiverDocument:
                type: string
              price:
                $ref: "#/components/schemas/money"
        discounts:
          type: array
          description: Descontos aplicados. Omitido quando o pedido não tem desconto.
          items:
            type: object
            properties:
              amount:
                $ref: "#/components/schemas/money"
              target:
                type: string
                description: Sobre o que o desconto incide.
                enum:
                  - CART
                  - DELIVERY_FEE
              sponsorshipValues:
                type: array
                description: Quem financia o desconto.
                items:
                  type: object
                  properties:
                    name:
                      type: string
                      enum:
                        - MARKETPLACE
                        - MERCHANT
                    amount:
                      $ref: "#/components/schemas/money"
                    discountCode:
                      type: string
                      description: Código ou título do desconto.
        total:
          type: object
          description: Totais do pedido.
          properties:
            itemsPrice:
              $ref: "#/components/schemas/money"
            otherFees:
              $ref: "#/components/schemas/money"
            discount:
              $ref: "#/components/schemas/money"
            orderAmount:
              $ref: "#/components/schemas/money"
        payments:
          type: object
          properties:
            prepaid:
              type: number
              description: Valor já pago online.
            pending:
              type: number
              description: Valor a receber na entrega ou retirada.
            methods:
              type: array
              items:
                type: object
                properties:
                  value:
                    type: number
                  currency:
                    type: string
                    enum:
                      - BRL
                  type:
                    type: string
                    description: Momento do pagamento.
                    enum:
                      - PREPAID
                      - PENDING
                      - ONLINE
                      - OFFLINE
                  method:
                    type: string
                    description: Forma de pagamento.
                    enum:
                      - CREDIT
                      - DEBIT
                      - MEAL_VOUCHER
                      - FOOD_VOUCHER
                      - DIGITAL_WALLET
                      - PIX
                      - CASH
                      - CREDIT_DEBIT
                      - COUPON
                      - REDEEM
                      - PREPAID_REDEEM
                      - OTHER
                  brand:
                    type: string
                    description: Bandeira. Omitida quando não se aplica.
                    example: VISA
                  methodInfo:
                    type: string
                    description: Informação adicional da forma de pagamento. Omitida quando vazia.
                  changeFor:
                    type: number
                    description: Valor para o qual levar troco. Presente apenas quando há troco.
        loyalty:
          $ref: "#/components/schemas/loyaltyBlock"
        customer:
          type: object
          description: Cliente. Omitido quando o pedido não tem nome de comprador.
          properties:
            id:
              type: string
              format: uuid
            name:
              type: string
            documentNumber:
              type: string
              description: CPF/CNPJ do cliente. Omitido quando não informado.
            phone:
              type: object
              properties:
                number:
                  type: string
                  description: Telefone no formato E.164, sem formatação.
                  example: "5511999999999"
            email:
              type: string
              description: E-mail. Omitido para clientes convidados (sem cadastro).
            ordersCountOnMerchant:
              type: integer
              description: Quantidade de pedidos do cliente na loja.
        schedule:
          type: object
          description: Janela do agendamento. Presente apenas em pedidos agendados.
          properties:
            scheduledDateTimeStart:
              type: string
              format: date-time
            scheduledDateTimeEnd:
              type: string
              format: date-time
        delivery:
          type: object
          description: Dados da entrega. Presente apenas em pedidos de entrega.
          properties:
            deliveredBy:
              type: string
              enum:
                - MERCHANT
            estimatedDeliveryDateTime:
              type: string
              format: date-time
            deliveryAddress:
              $ref: "#/components/schemas/address"
        takeout:
          type: object
          description: Dados da retirada. Presente apenas em pedidos para retirada.
          properties:
            mode:
              type: string
              enum:
                - DEFAULT
            takeoutDateTime:
              type: string
              format: date-time
        indoor:
          type: object
          description: Dados do consumo no local. Presente apenas em pedidos `INDOOR`.
          properties:
            mode:
              type: string
              description: >-
                `DEFAULT` para consumo no local sem mesa/comanda, `TAB` para pedidos em comanda e `PLACE` para
                pedidos em mesa.
              enum:
                - DEFAULT
                - PLACE
                - TAB
            indoorDateTime:
              type: string
              format: date-time
            place:
              type: string
            placeName:
              type: string
            placeId:
              type: string
            tab:
              type: string
            tabId:
              type: string
              format: uuid
            tabName:
              type: string
            tabCode:
              type: string
        sendDelivered:
          type: boolean
          description: A loja é responsável pelo evento DELIVERED (sem operador logístico externo).
        sendPreparing:
          type: boolean
          description: A loja deve enviar o evento PREPARING.
        sendPickedUp:
          type: boolean
          description: A loja é responsável pelo evento PICKED_UP (pedidos para retirada).
        sendTracking:
          type: boolean
          description: A loja deve enviar atualizações de rastreamento.
        extraInfo:
          type: string
          description: Observação geral do pedido. Omitida quando vazia.

    money:
      type: object
      description: Valor monetário.
      required:
        - value
        - currency
      properties:
        value:
          type: number
          description: Valor, com até 4 casas decimais.
          example: 39.9
        currency:
          type: string
          description: Moeda (código ISO 4217).
          enum:
            - BRL

    orderOption:
      type: object
      description: Complemento escolhido em um item do pedido.
      properties:
        id:
          type: string
          format: uuid
        index:
          type: integer
          description: Posição do complemento na lista.
        name:
          type: string
        externalCode:
          type: string
          description: Código externo do complemento. Omitido quando vazio.
        unit:
          type: string
          description: Unidade de medida. Sempre `UN`.
          enum:
            - UN
        quantity:
          type: integer
        unitPrice:
          $ref: "#/components/schemas/money"
        totalPrice:
          $ref: "#/components/schemas/money"

    orderOptionGroup:
      type: object
      description: Grupo de complementos de um item do pedido (views `optionGroups`/`groupOptions`).
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        externalCode:
          type: string
          description: Código externo do grupo. Omitido quando vazio.
        totalPrice:
          $ref: "#/components/schemas/money"
        options:
          type: array
          items:
            $ref: "#/components/schemas/orderOption"

    loyaltyBlock:
      type: object
      description: >-
        Presente no pedido apenas para aplicativos cujo programa de fidelidade o cliente aderiu. Cada
        aplicativo recebe somente o bloco do seu próprio programa.


        O bloco identifica o cliente no operador e informa o que foi resgatado neste pedido. Ele não traz
        nenhum valor calculado pela plataforma: as regras de acúmulo pertencem ao operador, que escolhe sua
        própria base a partir do `total` do pedido (por exemplo, `itemsPrice` menos `discount`, se frete e
        taxas não devem acumular).


        O bloco descreve o pedido como ele está no momento da leitura, não um instante do seu histórico. Um
        aplicativo que recebe um evento CONCLUDED consulta o pedido e faz o acúmulo; um que recebe um evento
        CANCELLED estorna o acúmulo que havia concedido para aquele pedido.


        Quando um resgate está REVERSED, o saldo voltou para o cliente, que portanto pagou esse valor por
        outros meios — mas os totais do pedido continuam mostrando o desconto que ele havia financiado. Some
        `redemption.amount.value` de volta a qualquer base derivada dos totais do pedido. Um pedido que nunca
        teve resgate não traz a chave `redemption`.
      required:
        - accountId
        - programId
      properties:
        accountId:
          type: string
          description: Identificador da conta do cliente no operador.
        programId:
          type: string
          description: Identificador do programa no operador.
        redemption:
          type: object
          description: >-
            O resgate debitado neste pedido, presente somente na entrega para o aplicativo que foi debitado.
            CONFIRMED significa que o resgate vale: o desconto que ele financia está dentro de
            `total.discount` do pedido. REVERSED significa que o saldo foi devolvido ao cliente.
          required:
            - externalId
            - status
            - amount
          properties:
            externalId:
              type: string
              description: Identificador do resgate gerado pelo operador quando o débito foi criado.
            status:
              type: string
              enum:
                - CONFIRMED
                - REVERSED
            amount:
              $ref: "#/components/schemas/money"

    address:
      type: object
      description: Endereço.
      properties:
        country:
          type: string
          description: Sigla do país.
          example: BR
        state:
          type: string
          description: Sigla do estado.
          example: SP
        city:
          type: string
          example: São Paulo
        district:
          type: string
          description: Bairro.
          example: Moema
        street:
          type: string
          description: Logradouro.
          example: Avenida Ibirapuera
        number:
          type: string
          example: "100"
        complement:
          type: string
          description: Complemento. Omitido quando vazio.
          example: Bloco 2, apto 31
        reference:
          type: string
          description: Ponto de referência. Omitido quando vazio.
          example: Casa amarela
        postalCode:
          type: string
          description: CEP.
          example: 04029-000
        formattedAddress:
          type: string
          description: Endereço completo formatado.
        coordinates:
          type: object
          properties:
            latitude:
              type: number
              example: -23.54809
            longitude:
              type: number
              example: -46.63638

    trackingDetails:
      type: object
      properties:
        vehicle:
          type: object
          description: Veículo do entregador.
          required:
            - type
          properties:
            type:
              type: string
              enum:
                - MOTORBIKE_BAG
                - MOTORBIKE_BOX
                - CAR
                - BICYCLE
                - SCOOTER
                - VUC
            licencePlate:
              type: string
              description: Placa do veículo.
        eta:
          type: object
          description: Previsões de coleta e entrega.
          properties:
            pickupEtaInMinutes:
              type: integer
              description: Minutos previstos até a coleta.
            pickupEtaDatetime:
              type: string
              format: date-time
              description: Momento previsto da coleta.
            deliveryEtaInMinutes:
              type: integer
              description: Minutos previstos até a entrega.
            deliveryEtaDatetime:
              type: string
              format: date-time
              description: Momento previsto da entrega.
            maxDeliveryTime:
              type: string
              format: date-time
              description: Prazo máximo de entrega.
        deliveryPerson:
          type: object
          description: Entregador.
          properties:
            id:
              type: string
            name:
              type: string
            pictureURL:
              type: string
              format: uri
        geoLocalization:
          type: object
          description: Localização atual do entregador.
          properties:
            latitude:
              type: number
            longitude:
              type: number
            lastAddress:
              type: object
              required:
                - distanceToPickup
                - distanceToDelivery
                - timestamp
              properties:
                country:
                  type: string
                state:
                  type: string
                city:
                  type: string
                district:
                  type: string
                street:
                  type: string
                postalCode:
                  type: string
                distanceToPickup:
                  type: string
                distanceToDelivery:
                  type: string
                timestamp:
                  type: string
                  format: date-time
        externalTrackingURL:
          type: string
          format: uri
          description: URL pública de rastreamento.

    deliveryTrackingInfo:
      description: >-
        Envie `event` (andamento da entrega) ou `problem` (ocorrência), opcionalmente com
        `vehicle`, `eta`, `deliveryPerson`, `geoLocalization` e `externalTrackingURL`. Campos
        fora desta lista são rejeitados.
      oneOf:
        - title: Evento de entrega
          allOf:
            - type: object
              required:
                - event
              properties:
                event:
                  type: object
                  required:
                    - type
                    - datetime
                  properties:
                    type:
                      type: string
                      enum:
                        - PICKUP_ONGOING
                        - ARRIVED_AT_MERCHANT
                        - ORDER_PICKED
                        - DELIVERY_ONGOING
                        - ARRIVED_AT_CUSTOMER
                        - ORDER_DELIVERED
                        - CANCELLED
                    message:
                      type: string
                      description: Mensagem livre.
                    datetime:
                      type: string
                      format: date-time
                      description: Momento do evento.
            - $ref: "#/components/schemas/trackingDetails"
        - title: Ocorrência
          allOf:
            - type: object
              required:
                - problem
              properties:
                problem:
                  type: object
                  required:
                    - reason
                    - datetime
                  properties:
                    reason:
                      type: string
                      enum:
                        - DELIVERYPERSON_OCCURRENCE
                        - PAYMENT_PROBLEMS
                        - WRONG_PRODUCT_OR_ITEM
                        - ORDER_DELAYED
                        - ORDER_DAMAGED_OR_VIOLATED
                        - CUSTOMER_DID_NOT_PLACE_ORDER
                        - CUSTOMER_ADDRESS_UNKNOWN
                        - ORDER_MISSING_ITEMS
                        - NOBODY_TO_RECEIVE
                        - DELIVERYPERSON_WAITING_PAYMENT_FOR_ALREADY_PAID_ORDER
                        - ORDER_DELIVERED_WITHOUT_PAYMENT
                        - FRAUD_OR_THEFT
                    message:
                      type: string
                      description: Mensagem livre.
                    datetime:
                      type: string
                      format: date-time
                      description: Momento da ocorrência.
            - $ref: "#/components/schemas/trackingDetails"

    oauthError:
      type: object
      description: Erro no formato OAuth 2.0 (RFC 6749, seção 5.2).
      properties:
        error:
          type: string
          example: invalid_client
        error_description:
          type: string

    actionResponse:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Identificador do pedido.

    Error:
      type: object
      required:
        - title
        - status
      properties:
        title:
          type: string
          description: Descrição do problema. Várias mensagens vêm separadas por `|`.
          example: Record not found
        status:
          type: string
          description: Código HTTP da resposta, como texto.
          example: "404"

  responses:
    Action:
      description: Ação aceita.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/actionResponse"
    ActionOk:
      description: Ação processada.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/actionResponse"
    Unauthorized:
      description: Token ausente, inválido ou expirado.
      content:
        application/json:
          schema:
            type: object
            properties:
              title:
                type: string
                example: Unauthorized
              status:
                type: integer
                example: 401
    NotFound:
      description: Recurso não encontrado.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    NotAcceptable:
      description: Parâmetros em formato inválido.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    MultipleMerchants:
      description: >-
        O token está vinculado a mais de uma loja e a operação exige uma única
        (`Token must be associated with a single merchant`).
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    UnprocessableEntity:
      description: A transição não é permitida no estado atual do pedido ou os dados são inválidos.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"

  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: "`client_id` como usuário e `client_secret` como senha."
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Access token opaco obtido em `POST /oauth/token` (host `od.deliveryvip.com.br`) com
        `grant_type=client_credentials` e escopo `od.all`.
