openapi: 3.0.3
info:
  title: All Delivery — API de Parceiros
  version: "1.0"
  description: |
    API pública pra plataformas de e-commerce e apps de pedido (ex: iFood)
    solicitarem um entregador da frota própria ou despacharem uma mercadoria
    por transportadora (Correios).

    **Ambientes**: use uma chave `alldev_live_...` pra operações reais
    (debita a carteira do parceiro, despacha motorista de verdade) ou
    `alldev_test_...` pra sandbox (nada real acontece — motorista e status
    são simulados, transportadora gera etiqueta fake).

    **Idempotência**: em todo POST que cria algo (entrega, envio), mande um
    header `Idempotency-Key` com um valor único seu por tentativa — se a
    chamada repetir (retry de rede, por exemplo), a mesma resposta anterior
    é devolvida em vez de duplicar o pedido.
servers:
  - url: /api/v1
security:
  - bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: alldev_live_... ou alldev_test_...
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code: { type: string, example: invalid_request }
            message: { type: string }
    Delivery:
      type: object
      properties:
        id: { type: string }
        status: { type: string, enum: [draft, searching, accepted, in_transit, delivered, cancelled] }
        is_sandbox: { type: boolean }
        vehicle_type: { type: string }
        price: { type: number, format: float }
        pickup_address: { type: string }
        dropoff_address: { type: string }
        driver:
          type: object
          nullable: true
          properties:
            name: { type: string }
            phone: { type: string }
            vehicle_type: { type: string }
        tracking_url: { type: string }
        created_at: { type: string }
    Shipment:
      type: object
      properties:
        id: { type: string }
        is_sandbox: { type: boolean }
        status: { type: string }
        carrier_code: { type: string }
        service_code: { type: string }
        price: { type: number, format: float }
        tracking_code: { type: string, nullable: true }
        label_url: { type: string, nullable: true }
        last_tracking_status: { type: string, nullable: true }
        created_at: { type: string }
paths:
  /deliveries/quote:
    post:
      summary: Cotar uma entrega da frota própria
      tags: [Entregas]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [pickup, dropoff]
              properties:
                pickup:
                  type: object
                  required: [address]
                  properties: { address: { type: string } }
                dropoff:
                  type: object
                  required: [address]
                  properties:
                    address: { type: string }
                    complement: { type: string }
                package:
                  type: object
                  properties:
                    description: { type: string }
                    declared_value: { type: number, format: float }
                recipient:
                  type: object
                  properties: { name: { type: string }, phone: { type: string } }
                city: { type: string, description: "Nome da cidade, pra aplicar a tarifa local certa (opcional)." }
            example:
              pickup: { address: "Av. Paulista, 1000, São Paulo, SP" }
              dropoff: { address: "Rua Augusta, 500, São Paulo, SP" }
              package: { description: "Caixa pequena", declared_value: 150.00 }
              recipient: { name: "João Cliente", phone: "5511999999999" }
      responses:
        "200":
          description: Cotação gerada
          content:
            application/json:
              schema:
                type: object
                properties:
                  quote_id: { type: string }
                  expires_in_seconds: { type: integer }
                  distance: { type: object }
                  duration: { type: object }
                  vehicles:
                    type: object
                    additionalProperties:
                      type: object
                      properties: { label: { type: string }, price: { type: number } }
        "422":
          description: Endereço inválido ou rota não encontrada
          content:
            application/json: { schema: { $ref: "#/components/schemas/Error" } }
  /deliveries:
    post:
      summary: Confirmar e despachar uma entrega (a partir de um quote_id)
      tags: [Entregas]
      parameters:
        - name: Idempotency-Key
          in: header
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [quote_id, vehicle_type]
              properties:
                quote_id: { type: string }
                vehicle_type: { type: string, example: motorcycle }
      responses:
        "201":
          description: Entrega criada e despachada
          content:
            application/json: { schema: { $ref: "#/components/schemas/Delivery" } }
        "402":
          description: Saldo insuficiente na carteira do parceiro
        "404":
          description: Cotação não encontrada, já usada ou expirada
  /deliveries/{id}:
    get:
      summary: Consultar status de uma entrega
      tags: [Entregas]
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        "200":
          description: Status atual
          content:
            application/json: { schema: { $ref: "#/components/schemas/Delivery" } }
        "404": { description: Não encontrada }
  /deliveries/{id}/cancel:
    post:
      summary: Cancelar uma entrega (só antes de aceita por um motorista)
      tags: [Entregas]
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        "200":
          description: Cancelada
          content:
            application/json: { schema: { $ref: "#/components/schemas/Delivery" } }
        "409": { description: Já foi aceita/finalizada, não cancelável mais pela API }
  /sender-profile:
    put:
      summary: Cadastrar/atualizar o endereço de remetente (obrigatório antes de despachar por transportadora)
      tags: [Transportadora]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, document, cep, address, number, district, city, state]
              properties:
                name: { type: string }
                document: { type: string }
                phone: { type: string }
                cep: { type: string }
                address: { type: string }
                number: { type: string }
                complement: { type: string }
                district: { type: string }
                city: { type: string }
                state: { type: string, example: SP }
      responses:
        "200": { description: Salvo }
  /shipments/quote:
    post:
      summary: Cotar envio por transportadora
      tags: [Transportadora]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [destination_cep, package]
              properties:
                destination_cep: { type: string, example: "01310-930" }
                package:
                  type: object
                  required: [format, weight_grams, length_cm, width_cm, height_cm]
                  properties:
                    format: { type: string, enum: [envelope, pacote, rolo_prisma] }
                    weight_grams: { type: integer }
                    length_cm: { type: number }
                    width_cm: { type: number }
                    height_cm: { type: number }
      responses:
        "200":
          description: Cotações por transportadora/serviço
        "422":
          description: Endereço de remetente não cadastrado (use PUT /sender-profile primeiro)
  /shipments:
    post:
      summary: Gerar etiqueta e despachar por transportadora
      tags: [Transportadora]
      parameters:
        - name: Idempotency-Key
          in: header
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [carrier_code, service_code, package, recipient]
              properties:
                carrier_code: { type: string, example: correios }
                service_code: { type: string }
                package:
                  type: object
                  properties:
                    format: { type: string }
                    weight_grams: { type: integer }
                    length_cm: { type: number }
                    width_cm: { type: number }
                    height_cm: { type: number }
                    description: { type: string }
                    declared_value: { type: number }
                recipient:
                  type: object
                  required: [name, cep, address, number, district, city, state]
                  properties:
                    name: { type: string }
                    document: { type: string }
                    cep: { type: string }
                    address: { type: string }
                    number: { type: string }
                    complement: { type: string }
                    district: { type: string }
                    city: { type: string }
                    state: { type: string }
                    phone: { type: string }
      responses:
        "201":
          description: Etiqueta gerada
          content:
            application/json: { schema: { $ref: "#/components/schemas/Shipment" } }
        "402": { description: Saldo insuficiente }
        "502": { description: Falha na transportadora }
  /shipments/{id}:
    get:
      summary: Consultar status/rastreio de um envio
      tags: [Transportadora]
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        "200":
          description: Status atual
          content:
            application/json: { schema: { $ref: "#/components/schemas/Shipment" } }
  /shipments/{id}/cancel:
    post:
      summary: Cancelar um envio
      tags: [Transportadora]
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        "200": { description: Cancelado }
  /vehicle-categories:
    get:
      summary: Listar tipos de veículo disponíveis
      tags: [Referência]
      responses:
        "200": { description: Lista de categorias }
