{
  "openapi": "3.1.0",
  "info": {
    "title": "Pagajob Logistics — API publique de prix de convoyage",
    "version": "1",
    "summary": "Prix de convoyage et de transport de véhicules (France) en temps réel.",
    "description": "API publique et sans authentification de Pagajob Logistics (convoyage de véhicules B2B, Lyon, France). Elle renvoie le même prix que le simulateur du site https://pagajob.com/tarifs : convoyage par chauffeur (simple ou Express 24 h en convoi navette) et estimation camion porte-voitures. Tous les prix sont en euros hors taxes (HT), par véhicule, tout inclus (chauffeur et retour, carburant, péages, assurance, états des lieux). Aucune réservation n'est faite par ces appels.\n\nErreurs : toujours en JSON `{ error, message, code, status, hint, docs }`. Limitation de débit par adresse IP, annoncée par les en-têtes `RateLimit-Policy` / `RateLimit` (draft IETF) et `X-RateLimit-*` ; `Retry-After` sur une réponse 429. Versionnement : en-tête `API-Version` ; politique de dépréciation : https://pagajob.com/developers#versions",
    "contact": {
      "name": "Pagajob Logistics",
      "email": "contact@pagajob.com",
      "url": "https://pagajob.com/developers"
    },
    "termsOfService": "https://pagajob.com/cgv"
  },
  "externalDocs": {
    "description": "Documentation développeurs et agents",
    "url": "https://pagajob.com/developers"
  },
  "servers": [
    {
      "url": "https://pagajob.com/functions",
      "description": "Production (version 1)"
    }
  ],
  "security": [],
  "paths": {
    "/calculateQuote": {
      "post": {
        "operationId": "calculateQuote",
        "summary": "Prix de convoyage d'un ou plusieurs véhicules entre deux adresses",
        "description": "Renvoie le prix HT par véhicule et total pour le convoyage simple (date convenue) et Express 24 h, ainsi que la fourchette estimative en camion porte-voitures. Prix ferme en ligne jusqu'à 350 km (`eligible`), au-delà sur devis.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteInput"
              },
              "example": {
                "departure": "Lyon, France",
                "arrival": "Grenoble, France",
                "vehicle_type": "citadine",
                "vehicle_count": 3
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Prix calculé",
            "headers": {
              "API-Version": {
                "$ref": "#/components/headers/APIVersion"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/estimateTruck": {
      "post": {
        "operationId": "estimateTruck",
        "summary": "Estimation transport en camion porte-voitures (fourchette HT par véhicule)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TruckInput"
              },
              "example": {
                "departure_coords": {
                  "lat": 45.764,
                  "lng": 4.8357
                },
                "arrival_coords": {
                  "lat": 48.8566,
                  "lng": 2.3522
                },
                "vehicle_type": "citadine",
                "vehicle_count": 5
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fourchette estimative ; le tarif ferme est confirmé par Pagajob sous 2 h ouvrées",
            "headers": {
              "API-Version": {
                "$ref": "#/components/headers/APIVersion"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TruckEstimate"
                },
                "example": {
                  "distance_km": 465,
                  "estimate_low": 410,
                  "estimate_high": 500,
                  "total_low": 2050,
                  "total_high": 2500
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/contactMessage": {
      "post": {
        "operationId": "contactMessage",
        "summary": "Envoyer un message à l'équipe Pagajob Logistics (demande de devis, question)",
        "description": "Transmet le message à contact@pagajob.com. À n'utiliser qu'avec l'accord explicite de la personne dont les coordonnées sont envoyées.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "email",
                  "message"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "company": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message transmis",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "Error": {
        "description": "Erreur",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Trop de requêtes",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Secondes à attendre"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "VehicleType": {
        "type": "string",
        "enum": [
          "citadine",
          "berline",
          "monospace",
          "suv",
          "util6",
          "util12",
          "util20"
        ],
        "description": "citadine, berline, monospace, SUV / 4x4, utilitaire ≤ 6 m³, ≤ 12 m³, ≤ 20 m³"
      },
      "Point": {
        "type": "object",
        "required": [
          "lat",
          "lng"
        ],
        "properties": {
          "lat": {
            "type": "number"
          },
          "lng": {
            "type": "number"
          }
        }
      },
      "QuoteInput": {
        "type": "object",
        "required": [
          "departure",
          "arrival",
          "vehicle_type",
          "vehicle_count"
        ],
        "properties": {
          "departure": {
            "type": "string",
            "description": "Adresse ou ville de départ (France, Suisse, Belgique)"
          },
          "arrival": {
            "type": "string",
            "description": "Adresse ou ville d'arrivée"
          },
          "departure_coords": {
            "$ref": "#/components/schemas/Point"
          },
          "arrival_coords": {
            "$ref": "#/components/schemas/Point"
          },
          "vehicle_type": {
            "$ref": "#/components/schemas/VehicleType"
          },
          "vehicle_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50
          },
          "pickup_at": {
            "type": "string",
            "format": "date-time",
            "description": "Facultatif : date et heure d'enlèvement (majorations nuit / week-end)"
          }
        }
      },
      "Quote": {
        "type": "object",
        "properties": {
          "distance_km": {
            "type": "number"
          },
          "duration_min": {
            "type": "number"
          },
          "eligible": {
            "type": "boolean",
            "description": "true : prix ferme réservable en ligne (≤ 350 km)"
          },
          "standard": {
            "type": "object",
            "properties": {
              "price_veh": {
                "type": "number"
              },
              "total": {
                "type": "number"
              }
            }
          },
          "express": {
            "type": "object",
            "properties": {
              "price_veh": {
                "type": "number"
              },
              "total": {
                "type": "number"
              },
              "card_type": {
                "type": "string"
              }
            }
          },
          "planned": {
            "type": "object",
            "description": "Camion porte-voitures (estimation)",
            "properties": {
              "estimate_low": {
                "type": "number"
              },
              "estimate_high": {
                "type": "number"
              },
              "total_low": {
                "type": "number"
              },
              "total_high": {
                "type": "number"
              }
            }
          },
          "degressif_pct": {
            "type": "number"
          },
          "majorations": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "TruckInput": {
        "type": "object",
        "required": [
          "departure_coords",
          "arrival_coords",
          "vehicle_type",
          "vehicle_count"
        ],
        "properties": {
          "departure_coords": {
            "$ref": "#/components/schemas/Point"
          },
          "arrival_coords": {
            "$ref": "#/components/schemas/Point"
          },
          "vehicle_type": {
            "$ref": "#/components/schemas/VehicleType"
          },
          "vehicle_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50
          }
        }
      },
      "TruckEstimate": {
        "type": "object",
        "properties": {
          "distance_km": {
            "type": "number"
          },
          "estimate_low": {
            "type": "number"
          },
          "estimate_high": {
            "type": "number"
          },
          "total_low": {
            "type": "number"
          },
          "total_high": {
            "type": "number"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "code",
          "status",
          "docs"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Message lisible (ou code historique)"
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "examples": [
              "BAD_REQUEST",
              "INVALID_JSON",
              "ADDRESS_NOT_RESOLVED",
              "RATE_LIMITED",
              "METHOD_NOT_ALLOWED",
              "INTERNAL_ERROR"
            ]
          },
          "status": {
            "type": "integer"
          },
          "hint": {
            "type": "string",
            "description": "Comment corriger la requête"
          },
          "docs": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    },
    "headers": {
      "APIVersion": {
        "schema": {
          "type": "string"
        },
        "description": "Version de l'API (actuellement 1)"
      },
      "RateLimitPolicy": {
        "schema": {
          "type": "string"
        },
        "description": "Ex. `30;w=60` : 30 requêtes par fenêtre de 60 s et par IP"
      },
      "RateLimit": {
        "schema": {
          "type": "string"
        },
        "description": "Ex. `limit=30, remaining=29, reset=60`"
      }
    }
  }
}
