{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/lexio-rent/json-schema/lexio-rent-organization-schema.json",
  "title": "Organization",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/lexio-rent-openapi.json#/components/schemas/Organization",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "description": "Identifiant de l’organisation du loueur."
    },
    "name": {
      "type": "string",
      "description": "Nom commercial du loueur."
    },
    "currency": {
      "type": "string",
      "enum": [
        "EUR",
        "XPF",
        "CHF",
        "CAD",
        "GBP",
        "USD",
        "XOF"
      ],
      "description": "Devise du loueur (ISO 4217), celle de tous les montants de son catalogue."
    },
    "currencyExponent": {
      "type": "integer",
      "minimum": 0,
      "maximum": 3,
      "description": "Nombre de décimales de la devise : 2 pour EUR, 0 pour XPF. Tout montant envoyé au-delà est refusé (400 `too_many_decimals`)."
    },
    "timezone": {
      "type": "string",
      "minLength": 1,
      "description": "Fuseau IANA du loueur : les heures de location sont des heures locales de ce fuseau."
    },
    "vatPercent": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "Taux de TVA appliqué aux prix HT, en % ; 0 si le loueur est exonéré."
    },
    "isVatExempt": {
      "type": "boolean",
      "description": "true : loueur exonéré de TVA, `vatPercent` vaut alors 0."
    },
    "isVatReverseChargeAvailable": {
      "type": "boolean",
      "description": "true : le loueur admet l’autoliquidation de TVA (`isVatReverseCharge`), sous réserve du client et de la durée (`reason` `NOT_ELIGIBLE`) ; sinon une telle demande répond 422 `VAT_REVERSE_CHARGE_NOT_ALLOWED`."
    },
    "toleranceHours": {
      "type": "integer",
      "minimum": 0,
      "description": "Retard toléré, en heures, avant de facturer un jour de plus : une durée de 3 jours et 2 h est facturée 3 jours si `toleranceHours` ≥ 2, sinon 4."
    },
    "rentalBufferMinutes": {
      "type": "integer",
      "minimum": 0,
      "description": "Battement, en minutes, laissé libre avant et après chaque location d’un véhicule : un véhicule n’est pas disponible pendant ce battement."
    },
    "businessHours": {
      "type": "object",
      "properties": {
        "isOpen24h": {
          "type": "boolean",
          "description": "true : ouvert tous les jours de 00:00 à 23:59, `days` le reflète."
        },
        "days": {
          "minItems": 7,
          "maxItems": 7,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "day": {
                "type": "string",
                "enum": [
                  "MONDAY",
                  "TUESDAY",
                  "WEDNESDAY",
                  "THURSDAY",
                  "FRIDAY",
                  "SATURDAY",
                  "SUNDAY"
                ],
                "description": "Jour de la semaine."
              },
              "isOpen": {
                "type": "boolean",
                "description": "false : loueur fermé ce jour-là."
              },
              "openingTime": {
                "anyOf": [
                  {
                    "type": "string",
                    "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Heure d’ouverture `HH:mm`, heure locale du loueur ; null un jour fermé."
              },
              "closingTime": {
                "anyOf": [
                  {
                    "type": "string",
                    "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Heure de fermeture `HH:mm`, incluse ; null un jour fermé."
              }
            },
            "required": [
              "day",
              "isOpen",
              "openingTime",
              "closingTime"
            ]
          },
          "description": "Les 7 jours de la semaine, du lundi au dimanche."
        }
      },
      "required": [
        "isOpen24h",
        "days"
      ],
      "description": "Horaires d’ouverture. Clé partenaire : départ et retour doivent tomber dans ces horaires (422 `BOOKING_RULE_VIOLATION`) ; une clé interne n’y est pas soumise."
    },
    "bookingRules": {
      "type": "object",
      "properties": {
        "minLeadHours": {
          "type": "integer",
          "minimum": 0,
          "description": "Délai minimal, en heures, entre maintenant et le départ."
        },
        "maxHorizonDays": {
          "type": "integer",
          "minimum": 0,
          "description": "Le départ tombe au plus tard ce nombre de jours après aujourd’hui."
        },
        "minRentalDays": {
          "type": "integer",
          "minimum": 0,
          "description": "Nombre minimal de jours calendaires entre le jour du départ et celui du retour."
        }
      },
      "required": [
        "minLeadHours",
        "maxHorizonDays",
        "minRentalDays"
      ],
      "description": "Règles de réservation, appliquées aux seules clés partenaires (422 `BOOKING_RULE_VIOLATION`)."
    },
    "apiKey": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "description": "Identifiant de la clé qui appelle."
        },
        "name": {
          "type": "string",
          "description": "Nom donné à la clé dans Lexio."
        },
        "partnerCode": {
          "description": "Code partenaire de la clé : elle ne voit que les clients, devis, locations et événements de ce code. null pour une clé interne, qui voit tous les clients et locations du loueur.",
          "type": [
            "string",
            "null"
          ]
        },
        "scopes": {
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "offers.read",
              "quotes.write",
              "rentals.read",
              "rentals.write",
              "rentals.operate",
              "rentals.delete",
              "payments.write",
              "payments.refund",
              "customers.read",
              "customers.write",
              "customers.delete",
              "vehicles.read",
              "vehicles.write",
              "vehicles.delete",
              "catalog.read",
              "catalog.write",
              "pricing.read",
              "pricing.write",
              "maintenance.read",
              "maintenance.write"
            ]
          },
          "description": "Scopes accordés à la clé."
        },
        "expiresAt": {
          "anyOf": [
            {
              "type": "string",
              "format": "date-time"
            },
            {
              "type": "null"
            }
          ],
          "description": "Fin de validité de la clé ; null si elle n’expire pas."
        }
      },
      "required": [
        "id",
        "name",
        "partnerCode",
        "scopes",
        "expiresAt"
      ],
      "description": "La clé API qui fait l’appel."
    }
  },
  "required": [
    "id",
    "name",
    "currency",
    "currencyExponent",
    "timezone",
    "vatPercent",
    "isVatExempt",
    "isVatReverseChargeAvailable",
    "toleranceHours",
    "rentalBufferMinutes",
    "businessHours",
    "bookingRules",
    "apiKey"
  ]
}