{
    "openapi": "3.0.3",
    "info": {
        "title": "frete.center App API",
        "description": "API para apps mobile (React Native, Flutter, Swift, Kotlin) do frete.center. Bearer JWT.",
        "version": "1.0.0",
        "contact": {
            "email": "contato@frete.center"
        },
        "license": {
            "name": "Proprietary"
        }
    },
    "servers": [
        {
            "url": "https://frete.center",
            "description": "Produção"
        }
    ],
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "JWT"
            }
        },
        "schemas": {
            "LoginRequest": {
                "type": "object",
                "required": [
                    "email",
                    "password"
                ],
                "properties": {
                    "email": {
                        "type": "string",
                        "format": "email"
                    },
                    "password": {
                        "type": "string"
                    },
                    "device": {
                        "type": "string",
                        "description": "Identificador opcional do dispositivo (ex: iPhone 14)"
                    }
                }
            },
            "TokenPair": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean"
                    },
                    "access_token": {
                        "type": "string",
                        "description": "JWT HS256 com TTL 1h"
                    },
                    "refresh_token": {
                        "type": "string",
                        "description": "Token opaco com TTL 30 dias, single-use"
                    },
                    "token_type": {
                        "type": "string",
                        "example": "Bearer"
                    },
                    "expires_in": {
                        "type": "integer",
                        "example": 3600
                    },
                    "user": {
                        "$ref": "#/components/schemas/User"
                    },
                    "tenant": {
                        "$ref": "#/components/schemas/Tenant"
                    }
                }
            },
            "User": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "email": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "role": {
                        "type": "string",
                        "enum": [
                            "superadmin",
                            "owner",
                            "admin",
                            "manager",
                            "driver",
                            "viewer",
                            "fiscal",
                            "operacoes",
                            "auditor_externo",
                            "cliente_externo"
                        ]
                    },
                    "persona": {
                        "type": "string",
                        "enum": [
                            "caminhoneiro",
                            "carro_van",
                            "motoboy"
                        ],
                        "nullable": true
                    },
                    "phone": {
                        "type": "string",
                        "nullable": true
                    },
                    "pix_key": {
                        "type": "string",
                        "nullable": true
                    }
                }
            },
            "Tenant": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "tipo": {
                        "type": "string"
                    },
                    "is_motorista": {
                        "type": "boolean"
                    }
                }
            },
            "Delivery": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string"
                    },
                    "tier": {
                        "type": "string",
                        "enum": [
                            "turbo",
                            "express",
                            "padrao"
                        ],
                        "nullable": true
                    },
                    "deadline_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "distance_km": {
                        "type": "number",
                        "nullable": true
                    },
                    "origem": {
                        "$ref": "#/components/schemas/Place"
                    },
                    "destino": {
                        "$ref": "#/components/schemas/Place"
                    },
                    "sender": {
                        "$ref": "#/components/schemas/Contact"
                    },
                    "recipient": {
                        "$ref": "#/components/schemas/Contact"
                    },
                    "timeline": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TimelineEvent"
                        }
                    },
                    "photos": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Photo"
                        }
                    }
                }
            },
            "Place": {
                "type": "object",
                "properties": {
                    "address": {
                        "type": "string"
                    },
                    "lat": {
                        "type": "number",
                        "nullable": true
                    },
                    "lng": {
                        "type": "number",
                        "nullable": true
                    }
                }
            },
            "Contact": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "phone": {
                        "type": "string"
                    },
                    "remarks": {
                        "type": "string",
                        "nullable": true
                    }
                }
            },
            "TimelineEvent": {
                "type": "object",
                "properties": {
                    "ts": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "type": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string"
                    }
                }
            },
            "Photo": {
                "type": "object",
                "properties": {
                    "stage": {
                        "type": "string",
                        "enum": [
                            "pickup",
                            "delivery",
                            "signature",
                            "damage",
                            "photo"
                        ]
                    },
                    "name": {
                        "type": "string"
                    },
                    "note": {
                        "type": "string"
                    },
                    "ts": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "url": {
                        "type": "string"
                    }
                }
            },
            "Position": {
                "type": "object",
                "required": [
                    "lat",
                    "lng"
                ],
                "properties": {
                    "lat": {
                        "type": "number",
                        "minimum": -34,
                        "maximum": 6
                    },
                    "lng": {
                        "type": "number",
                        "minimum": -74,
                        "maximum": -28
                    }
                }
            },
            "OrderCreateRequest": {
                "type": "object",
                "required": [
                    "cotacao_id",
                    "tier",
                    "sender_phone",
                    "recipient_name",
                    "recipient_phone"
                ],
                "properties": {
                    "cotacao_id": {
                        "type": "string"
                    },
                    "tier": {
                        "type": "string",
                        "enum": [
                            "turbo",
                            "express"
                        ]
                    },
                    "sender_name": {
                        "type": "string"
                    },
                    "sender_phone": {
                        "type": "string"
                    },
                    "recipient_name": {
                        "type": "string"
                    },
                    "recipient_phone": {
                        "type": "string"
                    },
                    "remarks": {
                        "type": "string"
                    },
                    "pod": {
                        "type": "boolean"
                    }
                }
            },
            "Error": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "example": false
                    },
                    "error": {
                        "type": "string"
                    }
                }
            }
        }
    },
    "paths": {
        "/api/app/v1/auth/login": {
            "post": {
                "tags": [
                    "auth"
                ],
                "summary": "Login com email + senha",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LoginRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Token pair",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TokenPair"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Não autenticado",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/app/v1/auth/refresh": {
            "post": {
                "tags": [
                    "auth"
                ],
                "summary": "Trocar refresh por novo par",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "refresh_token"
                                ],
                                "properties": {
                                    "refresh_token": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Novo par",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TokenPair"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/app/v1/auth/logout": {
            "post": {
                "tags": [
                    "auth"
                ],
                "summary": "Revoga refresh",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "refresh_token": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/me": {
            "get": {
                "tags": [
                    "auth"
                ],
                "summary": "Perfil + tenant",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries": {
            "get": {
                "tags": [
                    "driver"
                ],
                "summary": "Lista entregas atribuídas",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries/{code}": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "get": {
                "tags": [
                    "driver"
                ],
                "summary": "Detalhe da entrega",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries/{code}/accept": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Motorista aceita o pedido",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries/{code}/arrived": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Motorista chegou na coleta",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries/{code}/picked": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Coletou (com foto base64)",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "photo_b64": {
                                        "type": "string"
                                    },
                                    "note": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries/{code}/on-route": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Saiu para entrega",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries/{code}/delivered": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Entregou (com foto + assinatura)",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "photo_b64": {
                                        "type": "string"
                                    },
                                    "signature_b64": {
                                        "type": "string"
                                    },
                                    "note": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries/{code}/problem": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Reporta problema",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/deliveries/{code}/position": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Atualiza GPS do motorista",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Position"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/availability": {
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Toggle disponível agora",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "available"
                                ],
                                "properties": {
                                    "available": {
                                        "type": "boolean"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/earnings": {
            "get": {
                "tags": [
                    "driver"
                ],
                "summary": "Painel de ganhos",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/push/register": {
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Registra device token (FCM/APNs/Expo)",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "device_token",
                                    "platform"
                                ],
                                "properties": {
                                    "device_token": {
                                        "type": "string"
                                    },
                                    "platform": {
                                        "type": "string",
                                        "enum": [
                                            "fcm",
                                            "apns",
                                            "expo"
                                        ]
                                    },
                                    "app_version": {
                                        "type": "string"
                                    },
                                    "device": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/driver/push/unregister": {
            "post": {
                "tags": [
                    "driver"
                ],
                "summary": "Remove device token",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/wallet": {
            "get": {
                "tags": [
                    "embarcador"
                ],
                "summary": "Saldo + extrato",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/orders": {
            "get": {
                "tags": [
                    "embarcador"
                ],
                "summary": "Lista pedidos do tenant",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            },
            "post": {
                "tags": [
                    "embarcador"
                ],
                "summary": "Cria pedido (debita carteira)",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/OrderCreateRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/orders/{order_id}": {
            "parameters": [
                {
                    "name": "order_id",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "get": {
                "tags": [
                    "embarcador"
                ],
                "summary": "Detalhe + tracking",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/app/v1/orders/{order_id}/cancel": {
            "parameters": [
                {
                    "name": "order_id",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    }
                }
            ],
            "post": {
                "tags": [
                    "embarcador"
                ],
                "summary": "Cancela e estorna",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/cotar/lalamove": {
            "get": {
                "tags": [
                    "public"
                ],
                "summary": "Cotação Lalamove (público, com markup tier)",
                "parameters": [
                    {
                        "name": "cep_origem",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "minLength": 8,
                            "maxLength": 8
                        }
                    },
                    {
                        "name": "cep_destino",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "minLength": 8,
                            "maxLength": 8
                        }
                    },
                    {
                        "name": "service_type",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "example": "CAR"
                        }
                    },
                    {
                        "name": "tier",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "turbo",
                                "express"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/api/drivers-nearby": {
            "get": {
                "tags": [
                    "public"
                ],
                "summary": "Motoristas online próximos (com jitter LGPD)",
                "parameters": [
                    {
                        "name": "cep",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "lat",
                        "in": "query",
                        "schema": {
                            "type": "number"
                        }
                    },
                    {
                        "name": "lng",
                        "in": "query",
                        "schema": {
                            "type": "number"
                        }
                    },
                    {
                        "name": "km",
                        "in": "query",
                        "schema": {
                            "type": "number",
                            "default": 10
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "tags": [
        {
            "name": "auth",
            "description": "Login, refresh, logout"
        },
        {
            "name": "driver",
            "description": "Endpoints do app do motorista"
        },
        {
            "name": "embarcador",
            "description": "Endpoints do app do embarcador"
        },
        {
            "name": "public",
            "description": "Endpoints públicos (sem auth)"
        }
    ]
}