{
  "openapi": "3.0.0",
  "info": {
    "title": "DriveCars Partner API",
    "version": "1.0.0",
    "description": "A partner's server calls this API after exchanging OAuth client credentials for an access token at POST /oauth/token. Every /v1 route requires that token as a Bearer Authorization header. CAR RENTALS keep the reserve-then-book split: GET /coverage or GET /rentals/countries → GET /rentals/availability → POST /rentals/reservations → POST /rentals/reservations/{reference}/book → GET /bookings/{reference} → cancel (DELETE /rentals/reservations/{reference} for an unpaid draft, POST /bookings/{reference}/cancel for a paid booking). Four things that cost a partner money or trust if misread: (1) a RENTAL reservation never holds inventory — it is a draft booking, and nothing about creating one removes a car from availability; (2) a rental reservation auto-expires (~30 minutes) and is swept away, so a draft you abandon does not linger — but equally, do not treat one as a guarantee your customer can still book later; (3) GET /rentals/availability is THE rental search — there is no second one. It answers most calls completely in that one request (`use_polling: false`); when a search needs longer than a request allows it returns `use_polling: true` with a `search_id`, and you call the SAME url again with `?search_id={id}` and nothing else until `status` is `complete`; (4) every vehicle it returns has the SAME shape and is booked the same way — pass its `slug` back as `car_slug`. You never branch on where a vehicle came from, because the API never tells you and never needs to."
  },
  "servers": [
    {
      "url": "https://{your-base-url}/v1",
      "description": "Issued to you at onboarding"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "A partner API access token minted by POST /oauth/token (client-credentials grant). One-hour lifetime."
      }
    },
    "schemas": {
      "Fulfilment": {
        "type": "object",
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "none",
              "pending",
              "reserved",
              "failed",
              "cancelled"
            ],
            "description": "Whether the rental itself is secured yet. `pending` = the order is placed and paid but nothing is held for your customer. `reserved` = secured; `reference` now carries the confirmation code. `failed` = it could not be secured and will not be retried. `cancelled` = it was secured and has since been voided. `none` = no attempt yet."
          },
          "reference": {
            "type": "string",
            "nullable": true,
            "description": "Confirmation code for the secured rental. Null until `state` is `reserved`."
          }
        },
        "required": [
          "state",
          "reference"
        ]
      },
      "Booking": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "Where the order stands. Branch on `confirmed` alone. While an externally-fulfilled booking is not yet secured this reads `pending_confirmation` rather than the plain `pending` an ordinary booking awaiting a crew bid uses, so the two are never confused."
          },
          "fulfilment": {
            "$ref": "#/components/schemas/Fulfilment"
          }
        },
        "required": [
          "status"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/sdk/sessions/exchange": {
      "post": {
        "tags": [
          "sdk"
        ],
        "summary": "Exchange a partner's own end-user token for an SDK session.",
        "description": "Called by the BROWSER, not by the partner's backend — it is the only /v1 route that does not take a Bearer API token. Identify yourself with the public `client_id` and present your end user's own access token; DriveCars validates it against the introspection endpoint configured on your partner account and mints an SDK session for the customer it names. Requires `auth_provider = partner` on your account.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "access_token": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8192
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "web",
                      "native"
                    ]
                  },
                  "origin": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2048
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "exclusiveMinimum": true
                  }
                },
                "required": [
                  "client_id",
                  "access_token",
                  "channel"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A session token bound to the partner-authenticated customer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_token": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string"
                    },
                    "partner": {
                      "type": "object",
                      "properties": {
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "mor_mode": {
                          "type": "string",
                          "enum": [
                            "drivecars",
                            "partner_invoiced"
                          ]
                        },
                        "enabled_components": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "theme_overrides": {
                          "type": "object",
                          "additionalProperties": {
                            "nullable": true
                          }
                        },
                        "enabled_products": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "default_product": {
                          "type": "string",
                          "nullable": true
                        }
                      },
                      "required": [
                        "slug",
                        "name",
                        "mor_mode",
                        "enabled_components",
                        "theme_overrides",
                        "enabled_products",
                        "default_product"
                      ]
                    },
                    "customer": {
                      "type": "object",
                      "properties": {
                        "ref": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string",
                          "nullable": true
                        },
                        "name": {
                          "type": "string",
                          "nullable": true
                        }
                      },
                      "required": [
                        "ref",
                        "email",
                        "name"
                      ]
                    }
                  },
                  "required": [
                    "session_token",
                    "expires_at",
                    "partner",
                    "customer"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid request, or `origin` missing for channel `web`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "partner_auth_rejected — the partner's own auth server did not vouch for the token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "403": {
            "description": "partner_inactive, or origin_not_allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "404": {
            "description": "unknown_client — no such client_id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "auth_provider_not_partner — this partner has not configured partner-provided auth.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "502": {
            "description": "partner_auth_unavailable — the partner's auth server could not be reached, or answered unusably.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sdk/sessions/first-party": {
      "post": {
        "tags": [
          "sdk"
        ],
        "summary": "Mint a widget session for a DriveCars first-party surface.",
        "description": "INTERNAL. Used by the DriveCars website (server-side, holding the shared first-party key and presenting a browser Origin) and the DriveCars mobile app (presenting the signed-in customer's own JWT). The `surface` names which of the two; the partner row is resolved server-side from it and can never be chosen by the caller.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "surface": {
                    "type": "string",
                    "enum": [
                      "website",
                      "mobile"
                    ]
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "web",
                      "native"
                    ]
                  },
                  "origin": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2048
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "exclusiveMinimum": true
                  }
                },
                "required": [
                  "surface",
                  "channel"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A session token for the first-party surface that asked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_token": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string"
                    },
                    "partner": {
                      "type": "object",
                      "properties": {
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "mor_mode": {
                          "type": "string",
                          "enum": [
                            "drivecars",
                            "partner_invoiced"
                          ]
                        },
                        "enabled_components": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "theme_overrides": {
                          "type": "object",
                          "additionalProperties": {
                            "nullable": true
                          }
                        },
                        "enabled_products": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "default_product": {
                          "type": "string",
                          "nullable": true
                        }
                      },
                      "required": [
                        "slug",
                        "name",
                        "mor_mode",
                        "enabled_components",
                        "theme_overrides",
                        "enabled_products",
                        "default_product"
                      ]
                    }
                  },
                  "required": [
                    "session_token",
                    "expires_at",
                    "partner"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid request, or `origin` missing for channel `web`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "first_party_key_required, or no valid customer token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "403": {
            "description": "origin_not_allowed, or wrong_audience.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "503": {
            "description": "The first-party mint is not configured in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sdk/sessions/first-party/refresh": {
      "post": {
        "tags": [
          "sdk"
        ],
        "summary": "Re-authenticate a DriveCars first-party surface and issue a NEW session.",
        "description": "INTERNAL. Issues a fresh session for the same surface by RE-CHECKING the same credential the mint required — the shared first-party key plus an allowlisted Origin for `website`, the signed-in customer's JWT for `mobile`. It deliberately does NOT accept the existing session token as proof: an expired or leaked session must not be able to renew itself. The response is the same envelope the mint returns.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "surface": {
                    "type": "string",
                    "enum": [
                      "website",
                      "mobile"
                    ]
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "web",
                      "native"
                    ]
                  },
                  "origin": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2048
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "exclusiveMinimum": true
                  }
                },
                "required": [
                  "surface",
                  "channel"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A NEW session token for the surface that re-authenticated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_token": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string"
                    },
                    "partner": {
                      "type": "object",
                      "properties": {
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "mor_mode": {
                          "type": "string",
                          "enum": [
                            "drivecars",
                            "partner_invoiced"
                          ]
                        },
                        "enabled_components": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "theme_overrides": {
                          "type": "object",
                          "additionalProperties": {
                            "nullable": true
                          }
                        },
                        "enabled_products": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "default_product": {
                          "type": "string",
                          "nullable": true
                        }
                      },
                      "required": [
                        "slug",
                        "name",
                        "mor_mode",
                        "enabled_components",
                        "theme_overrides",
                        "enabled_products",
                        "default_product"
                      ]
                    }
                  },
                  "required": [
                    "session_token",
                    "expires_at",
                    "partner"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid request, or `origin` missing for channel `web`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "first_party_key_required, or no valid customer token. A session token alone lands here.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "403": {
            "description": "origin_not_allowed, or wrong_audience.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many mints/refreshes for this surface — shared bucket. Do not retry in a loop.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "503": {
            "description": "The first-party mint is not configured in this environment.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/rentals/locations": {
      "get": {
        "tags": [
          "rentals"
        ],
        "summary": "Published rental pickup locations (cities, airports, stations).",
        "description": "Cursor-paginated, ordered by type then name (matching the grouped, alphabetical-within-type order this endpoint has always used) — NOT by creation time. `q` matches against the location name in the requested `locale` (falling back to English).",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 10
            },
            "required": false,
            "name": "locale",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            },
            "required": false,
            "name": "country",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 100
            },
            "required": false,
            "name": "types",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "required": false,
            "name": "q",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Locations page.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": {
                          "nullable": true
                        }
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  },
                  "required": [
                    "rows",
                    "has_more",
                    "next_cursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid query.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/rentals/countries": {
      "get": {
        "tags": [
          "rentals"
        ],
        "summary": "Countries where car rentals are available.",
        "description": "The countries with at least one published pickup city. This is coverage, not a supply guarantee for any one search: whether a given location and stay actually has vehicles can only be known by running the search. Use GET /rentals/locations for the full location list within a country you already know is covered, and GET /rentals/availability to find out what is bookable there on your dates.",
        "responses": {
          "200": {
            "description": "Countries with at least one published pickup city.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "country_code": {
                            "type": "string",
                            "example": "ma"
                          },
                          "city_count": {
                            "type": "integer",
                            "example": 7
                          }
                        },
                        "required": [
                          "country_code",
                          "city_count"
                        ]
                      }
                    }
                  },
                  "required": [
                    "rows"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "500": {
            "description": "Could not load countries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/rentals/cars/{slug}": {
      "get": {
        "tags": [
          "rentals"
        ],
        "summary": "A single published rental car, priced at the calling partner's own commercial terms.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            },
            "required": true,
            "name": "slug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 10
            },
            "required": false,
            "name": "locale",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 3
            },
            "required": false,
            "name": "currency",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Car detail.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/rentals/availability": {
      "get": {
        "tags": [
          "rentals"
        ],
        "summary": "Dated, priced, bookable rental availability — one call, one vehicle shape.",
        "description": "THE ONE RENTAL SEARCH. Give a location (`location`, or `pickup_location` / `delivery_location`, which additionally pin the mode) and a stay (`date_from`, `date_to`, both required, `date_to` strictly after `date_from`), and every vehicle comes back with a REAL DATED TOTAL for that stay — not a per-day figure you have to multiply. `days` is reported ONCE at the top level: it is a property of the stay window and identical for every vehicle. `total` reflects duration tiers and date exceptions where the crew set them (`variable_pricing: true` says so), and follows a sale price when one is in effect — the same numbers POST /rentals/bookings will bill, so `total` is what belongs in the `expected_total` a booking asserts. EVERY VEHICLE HAS THE SAME SHAPE, and every vehicle is booked the same way: pass its `slug` back as `car_slug`. Fields that do not apply to a given vehicle (`location`, `fleet_size`, `vehicle_type`) are `null`, never omitted. POLLING: most searches are answered completely in this one call — `use_polling` is then `false` and `search_id`, `status`, `poll_after_ms` and `expires_at` are all `null`. Some searches need longer than one request allows; this endpoint waits for them briefly and answers the moment they finish. If one is still running when the response goes out, `use_polling` is `true` and `vehicles` may be empty — call THIS SAME URL again with `?search_id={search_id}` after `poll_after_ms`, and nothing else (dates and location are not needed on a poll), until `status` is `complete`. A `search_id` is also returned when the search DID finish in time, so you may poll it again for the same result until `expires_at`; `use_polling: false` tells you there is no need. `status` is pending | complete | failed | expired. `vehicle_type` accepts either the canonical prefixed slug (`vehicle-suv`) or the bare one (`suv`); the response always emits the canonical stored slug. A `search_id` belonging to another partner 404s, never 403s.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            },
            "required": false,
            "name": "location",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            },
            "required": false,
            "name": "pickup_location",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            },
            "required": false,
            "name": "delivery_location",
            "in": "query"
          },
          {
            "schema": {
              "type": "number",
              "nullable": true,
              "minimum": -90,
              "maximum": 90,
              "description": "Latitude of the delivery address. With `delivery_lng`, replaces `delivery_location`: the point is snapped to the nearest city we serve and the response says which (`delivery.city_slug`) and how far.",
              "example": 33.5731
            },
            "required": false,
            "name": "delivery_lat",
            "in": "query"
          },
          {
            "schema": {
              "type": "number",
              "nullable": true,
              "minimum": -180,
              "maximum": 180,
              "description": "Longitude of the delivery address. Pair with `delivery_lat`.",
              "example": -7.5898
            },
            "required": false,
            "name": "delivery_lng",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date"
            },
            "required": false,
            "name": "date_from",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date"
            },
            "required": false,
            "name": "date_to",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 21,
              "maximum": 99
            },
            "required": false,
            "name": "age",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "required": false,
            "name": "vehicle_type",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "maximum": 23
            },
            "required": false,
            "name": "pickup_hour",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "maximum": 23
            },
            "required": false,
            "name": "return_hour",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "pickup",
                "delivery"
              ]
            },
            "required": false,
            "name": "pickup_type",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            },
            "required": false,
            "name": "price_min",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            },
            "required": false,
            "name": "price_max",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "q",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "attrs",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{2}$"
            },
            "required": false,
            "name": "country",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 12
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "default": "en"
            },
            "required": false,
            "name": "locale",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "description": "Poll handle from a previous call to THIS endpoint. Send it ALONE — no dates, no location; the stay is read from the search it refers to. A handle belonging to another partner 404s."
            },
            "required": false,
            "name": "search_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            },
            "required": false,
            "name": "car_slug",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 3
            },
            "required": false,
            "name": "currency",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Dated availability — vehicles, plus a search handle when one is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "days": {
                      "type": "number",
                      "description": "Billable days for this stay — TOP LEVEL, not per vehicle: it is a property of the stay window and identical for every card. Computed by the same billableDays the storefront and the booking charge use, so it cannot disagree with what a booking bills."
                    },
                    "date_from": {
                      "type": "string"
                    },
                    "date_to": {
                      "type": "string"
                    },
                    "vehicles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": {
                          "nullable": true
                        }
                      },
                      "description": "ONE shape for every vehicle: slug, title, vehicle_type, image_url, price_per_day, total, currency, variable_pricing, location, fleet_size. Every key is always present; a field that does not apply to a vehicle is null. Book any of them by passing `slug` back as `car_slug`."
                    },
                    "total": {
                      "type": "number"
                    },
                    "page": {
                      "type": "number"
                    },
                    "limit": {
                      "type": "number"
                    },
                    "use_polling": {
                      "type": "boolean",
                      "description": "Whether calling again can still change this answer. `false` means this response is the complete answer and the four handle fields below are all null. `true` means a search is still running: poll this same URL with `?search_id={search_id}` after `poll_after_ms`."
                    },
                    "search_id": {
                      "type": "string",
                      "nullable": true,
                      "description": "Handle for this search, or null when nothing was left running. Poll it on THIS URL with `?search_id={id}` and nothing else. Returned even when the search already completed, so the same result stays readable until `expires_at`."
                    },
                    "status": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "pending",
                        "complete",
                        "failed",
                        "expired"
                      ],
                      "description": "Status of the search this handle refers to; null when there is no handle."
                    },
                    "poll_after_ms": {
                      "type": "number",
                      "nullable": true,
                      "description": "How long to wait before polling again. Null once the answer is final."
                    },
                    "expires_at": {
                      "type": "string",
                      "nullable": true,
                      "description": "When this search result stops being quotable. A stale quote is never honoured — search again past this point."
                    },
                    "booking_mode": {
                      "type": "string",
                      "enum": [
                        "variable",
                        "fixed"
                      ],
                      "description": "How this partner sells. `variable` is the marketplace model: the quoted price is what the customer pays unless they explicitly approve a higher one. `fixed` means the quoted price is firm — and the grid then holds only crews that committed to honouring it, so it can legitimately be narrower than a variable one. Stated on every response so a partner never has to infer the mode from what is missing."
                    },
                    "hint": {
                      "type": "string",
                      "description": "Present only on an EMPTY result this endpoint can explain — never on a result with vehicles, and never an error. Human-readable; branch on `hint_code`, not on this text."
                    },
                    "hint_code": {
                      "type": "string",
                      "description": "The machine-readable form of `hint`. `no_fixed_price_crews`: crews serve this city but none has opted in to fixed prices, and our wider inventory could not answer this search either, e.g. a delivery search (fixed mode only). `filters_matched_nothing`: the location has cars but your attrs/q/price filters matched none. Broaden or drop one — a wider search may also reach inventory these filters cannot describe."
                    }
                  },
                  "required": [
                    "days",
                    "date_from",
                    "date_to",
                    "vehicles",
                    "total",
                    "page",
                    "limit",
                    "use_polling",
                    "search_id",
                    "status",
                    "poll_after_ms",
                    "expires_at",
                    "booking_mode"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Missing/invalid dates or location.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "No such `search_id`, or it belongs to another partner.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "500": {
            "description": "Availability lookup failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/rentals/reservations": {
      "post": {
        "tags": [
          "rentals"
        ],
        "summary": "Create a rental reservation — a draft booking, NOT a held car.",
        "description": "Creates a draft booking (`status: \"draft\"`) exactly like POST /rentals/bookings with `confirm:false`, under a name a partner integration expects for a two-step flow. A RESERVATION DOES NOT HOLD A CAR: it is a draft booking with the system's existing ~30-minute expiry, and another customer can still book the same car while this reservation exists — nothing about creating one removes the car from availability. Confirm it with POST /rentals/reservations/{reference}/book before it expires, or it is auto-cancelled. Pass back the `slug` the search gave you as `car_slug` — every vehicle reserves the same way, whatever served it. `expected_total` is optional here and re-checked, not required, at `book` time.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "car_slug": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "date_from": {
                    "type": "string",
                    "format": "date"
                  },
                  "date_to": {
                    "type": "string",
                    "format": "date"
                  },
                  "units": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 50,
                    "default": 1
                  },
                  "pickup_hour": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 0,
                    "maximum": 23
                  },
                  "return_hour": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 0,
                    "maximum": 23
                  },
                  "pickup_type": {
                    "type": "string",
                    "enum": [
                      "pickup",
                      "delivery"
                    ],
                    "default": "pickup"
                  },
                  "pickup_location_slug": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 255
                  },
                  "pickup_location_name": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 255
                  },
                  "delivery_address": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 500,
                    "description": "The delivery address as the crew should read it. With coordinates it is a label; alone, we geocode it.",
                    "example": "12 Rue Test, Casablanca"
                  },
                  "delivery_lat": {
                    "type": "number",
                    "nullable": true,
                    "minimum": -90,
                    "maximum": 90,
                    "description": "Latitude of the delivery point. Pair with `delivery_lng`. Stored as given.",
                    "example": 33.5731
                  },
                  "delivery_lng": {
                    "type": "number",
                    "nullable": true,
                    "minimum": -180,
                    "maximum": 180,
                    "description": "Longitude of the delivery point. Pair with `delivery_lat`.",
                    "example": -7.5898
                  },
                  "customer": {
                    "type": "object",
                    "properties": {
                      "first_name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      },
                      "last_name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      },
                      "email": {
                        "type": "string",
                        "format": "email"
                      },
                      "phone": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 40
                      }
                    },
                    "required": [
                      "first_name",
                      "last_name",
                      "email"
                    ]
                  },
                  "payment_method": {
                    "type": "string",
                    "enum": [
                      "card",
                      "klarna",
                      "crypto"
                    ],
                    "default": "card"
                  },
                  "currency": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 3,
                    "maxLength": 3
                  },
                  "expected_total": {
                    "type": "number",
                    "minimum": 0,
                    "exclusiveMinimum": true,
                    "maximum": 1000000
                  },
                  "external_ref": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "customer_ref": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "car_slug",
                  "date_from",
                  "date_to",
                  "customer"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reservation created (a draft booking).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "No such car, or it is not available to this partner.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "Unavailable, the search result has expired, or the vehicle is supplied by a crew your account is not set up to sell (`crew_not_included`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "500": {
            "description": "Reservation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A key you choose, unique per booking attempt. Replaying the SAME key returns the original response with `Idempotent-Replayed: true` instead of creating a second booking -- which is what makes a timed-out request safe to retry. Reusing a key with a DIFFERENT body is a 422.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/rentals/reservations/{reference}/book": {
      "post": {
        "tags": [
          "rentals"
        ],
        "summary": "Confirm a reservation into a real, paid booking.",
        "description": "Authorizes payment on an existing draft reservation — the same confirm step POST /rentals/bookings runs internally, split out so a partner can reserve first and book later. Refuses (404) a reservation that does not belong to the caller, (409 `reservation_expired`) one past its ~30-minute draft window, and (409 `already_booked`) one that was already turned into a real booking — never creates a second booking for the same reservation. If `expected_total` is supplied it is checked against the reservation's actual total with the same cent-tolerance rule POST /rentals/bookings applies. EVERY reservation books exactly the same way, whatever vehicle it holds, and the response is the same shape in every case — see POST /rentals/bookings's own description for what the resulting booking status means and how to follow it to confirmation.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "required": true,
            "name": "reference",
            "in": "path"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A key you choose, unique per booking attempt. Replaying the SAME key returns the original response with `Idempotent-Replayed: true` instead of creating a second booking -- which is what makes a timed-out request safe to retry. Reusing a key with a DIFFERENT body is a 422.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_reference": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "expected_total": {
                    "type": "number",
                    "minimum": 0,
                    "exclusiveMinimum": true,
                    "maximum": 1000000
                  },
                  "customer_ref": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "payment_reference"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Booked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "No such reservation, or it does not belong to this partner.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "Expired, already booked, or a price mismatch.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "500": {
            "description": "Book failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/rentals/reservations/{reference}": {
      "delete": {
        "tags": [
          "rentals"
        ],
        "summary": "Cancel a reservation (a draft booking) — never a confirmed booking.",
        "description": "Drops a draft reservation nobody has paid for. Refuses a reservation that has already been turned into a real booking (409 `not_a_reservation`) — cancelling a booking with money attached is a different, deliberately separate operation: POST /v1/bookings/{reference}/cancel. Calling DELETE here on a confirmed/pending booking never cancels it silently.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "required": true,
            "name": "reference",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "No such reservation, or it does not belong to this partner.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "Not a reservation (already booked) — use POST /v1/bookings/{reference}/cancel instead.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "500": {
            "description": "Cancel failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/rentals/bookings": {
      "post": {
        "tags": [
          "rentals"
        ],
        "summary": "Book a rental as merchant of record for the partner's own customer.",
        "description": "Pass back the `slug` GET /rentals/availability gave you as `car_slug` — every vehicle books the same way, and you never branch on where it came from. Booked with the `expected_total` discipline described in this API's header: the total you already showed your customer, refused (409 `price_mismatch`) if the priced draft disagrees by more than a cent. A 201 MEANS THE ORDER IS PLACED WITH DRIVECARS, NOT THAT A CAR IS HELD. A new booking comes back in a not-yet-`confirmed` state, and there is no fixed SLA for when it becomes `confirmed`. TREAT ANY STATUS THAT IS NOT `confirmed` AS PENDING — more than one such status exists, they carry no obligation you need to act on differently, and new ones may be added without notice; branch on `confirmed` alone. Poll GET /v1/bookings/{reference} or subscribe to the booking webhook events; never infer confirmation from the absence of an error. A slug you were given more than an hour ago may no longer be priceable (409 `search_expired`) — search again and book from the fresh result, since a stale quote is never honoured. Not every vehicle can be delivered: `pickup_type: \"delivery\"` on one that must be collected in person is refused as `unavailable`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "car_slug": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "date_from": {
                    "type": "string",
                    "format": "date"
                  },
                  "date_to": {
                    "type": "string",
                    "format": "date"
                  },
                  "units": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 50,
                    "default": 1
                  },
                  "pickup_hour": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 0,
                    "maximum": 23
                  },
                  "return_hour": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 0,
                    "maximum": 23
                  },
                  "pickup_type": {
                    "type": "string",
                    "enum": [
                      "pickup",
                      "delivery"
                    ],
                    "default": "pickup"
                  },
                  "pickup_location_slug": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 255
                  },
                  "pickup_location_name": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 255
                  },
                  "delivery_address": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 500,
                    "description": "The delivery address as the crew should read it. With coordinates it is a label; alone, we geocode it.",
                    "example": "12 Rue Test, Casablanca"
                  },
                  "delivery_lat": {
                    "type": "number",
                    "nullable": true,
                    "minimum": -90,
                    "maximum": 90,
                    "description": "Latitude of the delivery point. Pair with `delivery_lng`. Stored as given.",
                    "example": 33.5731
                  },
                  "delivery_lng": {
                    "type": "number",
                    "nullable": true,
                    "minimum": -180,
                    "maximum": 180,
                    "description": "Longitude of the delivery point. Pair with `delivery_lat`.",
                    "example": -7.5898
                  },
                  "customer": {
                    "type": "object",
                    "properties": {
                      "first_name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      },
                      "last_name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      },
                      "email": {
                        "type": "string",
                        "format": "email"
                      },
                      "phone": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 40
                      }
                    },
                    "required": [
                      "first_name",
                      "last_name",
                      "email"
                    ]
                  },
                  "payment_method": {
                    "type": "string",
                    "enum": [
                      "card",
                      "klarna",
                      "crypto"
                    ],
                    "default": "card"
                  },
                  "currency": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 3,
                    "maxLength": 3
                  },
                  "expected_total": {
                    "type": "number",
                    "minimum": 0,
                    "exclusiveMinimum": true,
                    "maximum": 1000000
                  },
                  "payment_reference": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "external_ref": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "customer_ref": {
                    "type": "string",
                    "nullable": true,
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "confirm": {
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "car_slug",
                  "date_from",
                  "date_to",
                  "customer",
                  "expected_total",
                  "payment_reference"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Booking created — not yet confirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "No such car, or it is not available to this partner.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "Unavailable, price mismatch, the search result has expired, or the vehicle is supplied by a crew your account is not set up to sell (`crew_not_included`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "500": {
            "description": "Booking failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A key you choose, unique per booking attempt. Replaying the SAME key returns the original response with `Idempotent-Replayed: true` instead of creating a second booking -- which is what makes a timed-out request safe to retry. Reusing a key with a DIFFERENT body is a 422.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/bookings": {
      "get": {
        "tags": [
          "bookings"
        ],
        "summary": "List the calling partner's own bookings.",
        "description": "Fetch GET /v1/bookings/{reference} for a specific booking to get its driver name, vehicle and plate.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "car-rentals"
              ]
            },
            "required": false,
            "name": "product",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "pending",
                "confirmed",
                "completed",
                "cancelled"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "required": false,
            "name": "external_ref",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "created_after",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "created_before",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Bookings page.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Booking"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  },
                  "required": [
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid query.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/bookings/{reference}": {
      "get": {
        "tags": [
          "bookings"
        ],
        "summary": "A single booking, if it belongs to the calling partner.",
        "description": "A `201`/`200` from book means the order is placed with DriveCars and payment is authorized; poll this endpoint for the booking's current `status`, which is the single field that tells you where the order stands. BRANCH ON `confirmed` ALONE: more than one not-yet-confirmed status exists, they carry no obligation you need to act on differently, and new ones may be added without notice — treat every status that is not `confirmed` (and not `cancelled`) as still pending.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "required": true,
            "name": "reference",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Booking detail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/bookings/ext/{external_ref}": {
      "get": {
        "tags": [
          "bookings"
        ],
        "summary": "A single booking looked up by the partner's own external_ref.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "required": true,
            "name": "external_ref",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Booking detail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/bookings/{reference}/cancel": {
      "post": {
        "tags": [
          "bookings"
        ],
        "summary": "Cancel one of the calling partner's own bookings.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "required": true,
            "name": "reference",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "Not cancellable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "500": {
            "description": "Cancel failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/bookings/{reference}/payment": {
      "post": {
        "tags": [
          "bookings"
        ],
        "summary": "Confirm, from your server, that you have taken payment for one of your own bookings.",
        "description": "Partner-MoR only. Call this from your backend once your PSP has authorised the charge for a booking created through the Web SDK. Until you do, the booking stays a draft: it is not confirmed, not fulfilled and not invoiced. The widget on the customer's page advances on its own once this call lands. Idempotent for the same payment_reference.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "required": true,
            "name": "reference",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_reference": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Your own PSP's reference for the charge you took. Stored for reconciliation and shown on your invoice; never sent to any card processor.",
                    "example": "ch_3P8k2Q…"
                  }
                },
                "required": [
                  "payment_reference"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment recorded; the booking is now pending confirmation with the crew.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "409": {
            "description": "Not a partner-invoiced booking, cancelled, or already confirmed with a different reference.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "500": {
            "description": "Confirmation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/me": {
      "get": {
        "tags": [
          "me"
        ],
        "summary": "The calling partner's own profile and the scopes this token holds.",
        "responses": {
          "200": {
            "description": "Partner profile.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "slug": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "suspended",
                        "revoked"
                      ]
                    },
                    "mor_mode": {
                      "type": "string",
                      "enum": [
                        "drivecars",
                        "partner_invoiced"
                      ]
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "id",
                    "slug",
                    "name",
                    "status",
                    "mor_mode",
                    "scopes"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/sdk/sessions": {
      "post": {
        "tags": [
          "sdk"
        ],
        "summary": "Exchange the caller's API token for a short-lived SDK session token.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "web",
                      "native"
                    ]
                  },
                  "origin": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2048
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "exclusiveMinimum": true
                  },
                  "customer_ref": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "channel"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A session token for a browser or app to use against the SDK elements.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_token": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string"
                    },
                    "partner": {
                      "type": "object",
                      "properties": {
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "mor_mode": {
                          "type": "string",
                          "enum": [
                            "drivecars",
                            "partner_invoiced"
                          ]
                        },
                        "booking_mode": {
                          "type": "string",
                          "enum": [
                            "variable",
                            "fixed"
                          ]
                        },
                        "enabled_components": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "theme_overrides": {
                          "type": "object",
                          "additionalProperties": {
                            "nullable": true
                          }
                        },
                        "enabled_products": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "default_product": {
                          "type": "string",
                          "nullable": true
                        }
                      },
                      "required": [
                        "slug",
                        "name",
                        "mor_mode",
                        "booking_mode",
                        "enabled_components",
                        "theme_overrides",
                        "enabled_products",
                        "default_product"
                      ]
                    }
                  },
                  "required": [
                    "session_token",
                    "expires_at",
                    "partner"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Origin not allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "List the calling partner's own webhook endpoints.",
        "description": "Returns every endpoint for the caller in one page when `limit` is omitted. Pass `limit` (max 100) to page explicitly, then follow `next_cursor` the same way as GET /v1/bookings.",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "number"
                          },
                          "url": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "event_types": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "disabled",
                              "auto_disabled"
                            ]
                          },
                          "consecutive_failures": {
                            "type": "number"
                          },
                          "last_success_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_failure_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "updated_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "url",
                          "description",
                          "event_types",
                          "status",
                          "consecutive_failures",
                          "last_success_at",
                          "last_failure_at",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  },
                  "required": [
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid query.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Register a new webhook endpoint.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2048
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "event_types": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1
                  }
                },
                "required": [
                  "url",
                  "event_types"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created. `secret` is returned ONCE, here — it is never included in any other response (list, get, or a later patch). Store it now.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "url": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "event_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled",
                        "auto_disabled"
                      ]
                    },
                    "consecutive_failures": {
                      "type": "number"
                    },
                    "last_success_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "last_failure_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    },
                    "secret": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "description",
                    "event_types",
                    "status",
                    "consecutive_failures",
                    "last_success_at",
                    "last_failure_at",
                    "created_at",
                    "updated_at",
                    "secret"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid payload, or an unsafe url.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/webhooks/{id}": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "A single webhook endpoint, if it belongs to the calling partner.",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "url": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "event_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled",
                        "auto_disabled"
                      ]
                    },
                    "consecutive_failures": {
                      "type": "number"
                    },
                    "last_success_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "last_failure_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "description",
                    "event_types",
                    "status",
                    "consecutive_failures",
                    "last_success_at",
                    "last_failure_at",
                    "created_at",
                    "updated_at"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "webhooks"
        ],
        "summary": "Update a webhook endpoint.",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2048
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "event_types": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "disabled"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "url": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "event_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled",
                        "auto_disabled"
                      ]
                    },
                    "consecutive_failures": {
                      "type": "number"
                    },
                    "last_success_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "last_failure_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "description",
                    "event_types",
                    "status",
                    "consecutive_failures",
                    "last_success_at",
                    "last_failure_at",
                    "created_at",
                    "updated_at"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid payload, or an unsafe url.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "webhooks"
        ],
        "summary": "Disable a webhook endpoint (soft delete — delivery history is preserved).",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Disabled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "status"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Rotate the signing secret. The OLD secret keeps signing deliveries for an overlap window so a deploy of the new secret never drops a delivery.",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Rotated. `secret` is the NEW secret, returned ONCE, here.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "url": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "event_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled",
                        "auto_disabled"
                      ]
                    },
                    "consecutive_failures": {
                      "type": "number"
                    },
                    "last_success_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "last_failure_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    },
                    "secret": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "description",
                    "event_types",
                    "status",
                    "consecutive_failures",
                    "last_success_at",
                    "last_failure_at",
                    "created_at",
                    "updated_at",
                    "secret"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Send a `ping` event to this partner's active webhook endpoints.",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "202": {
            "description": "Ping queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "An endpoint's delivery history, newest first.",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Deliveries page.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "number"
                          },
                          "event_id": {
                            "type": "string"
                          },
                          "endpoint_id": {
                            "type": "number"
                          },
                          "status": {
                            "type": "string"
                          },
                          "attempt": {
                            "type": "number"
                          },
                          "next_attempt_at": {
                            "type": "string"
                          },
                          "replay_of": {
                            "type": "number",
                            "nullable": true
                          },
                          "attempts": {
                            "type": "array",
                            "items": {
                              "nullable": true
                            }
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "updated_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "event_id",
                          "endpoint_id",
                          "status",
                          "attempt",
                          "next_attempt_at",
                          "replay_of",
                          "attempts",
                          "created_at",
                          "updated_at"
                        ]
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  },
                  "required": [
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid cursor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/deliveries/{id}/replay": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Replay a delivery as a fresh attempt lineage.",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "202": {
            "description": "Replay queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "event_id": {
                      "type": "string"
                    },
                    "endpoint_id": {
                      "type": "number"
                    },
                    "status": {
                      "type": "string"
                    },
                    "attempt": {
                      "type": "number"
                    },
                    "next_attempt_at": {
                      "type": "string"
                    },
                    "replay_of": {
                      "type": "number",
                      "nullable": true
                    },
                    "attempts": {
                      "type": "array",
                      "items": {
                        "nullable": true
                      }
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "event_id",
                    "endpoint_id",
                    "status",
                    "attempt",
                    "next_attempt_at",
                    "replay_of",
                    "attempts",
                    "created_at",
                    "updated_at"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/events": {
      "get": {
        "tags": [
          "events"
        ],
        "summary": "Poll the calling partner's own event outbox (the polling fallback to webhooks).",
        "description": "Events older than 90 days are not returned. `since_id` is the numeric `id` field of the last event you saw — NOT its `event_id` string — pass it back to page forward.",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            },
            "required": false,
            "name": "since_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "types",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Events page, ordered oldest-to-newest by internal id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "livemode": {
                            "type": "boolean"
                          },
                          "data": {
                            "nullable": true
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "created_at",
                          "livemode"
                        ]
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "last_id": {
                      "type": "number",
                      "nullable": true
                    }
                  },
                  "required": [
                    "data",
                    "has_more",
                    "last_id"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid `types`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/events/{event_id}": {
      "get": {
        "tags": [
          "events"
        ],
        "summary": "A single event, if it belongs to the calling partner and is within the 90-day window.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "required": true,
            "name": "event_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "livemode": {
                      "type": "boolean"
                    },
                    "data": {
                      "nullable": true
                    }
                  },
                  "required": [
                    "id",
                    "type",
                    "created_at",
                    "livemode"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/coverage": {
      "get": {
        "tags": [
          "coverage"
        ],
        "summary": "Every country DriveCars serves, with per-product availability.",
        "description": "`car_rentals.available` is true when the country has at least one published pickup city — the operator's own statement of \"we serve here\". It is COVERAGE, NOT A SUPPLY GUARANTEE for any one request: whether a particular location and stay actually has vehicles can only be known by calling GET /rentals/availability for it. A country missing a product key is not served for that product at all.",
        "responses": {
          "200": {
            "description": "Countries with at least one available product.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "countries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "country_code": {
                            "type": "string",
                            "example": "ma"
                          },
                          "name": {
                            "type": "string",
                            "example": "Morocco"
                          },
                          "products": {
                            "type": "object",
                            "properties": {
                              "car_rentals": {
                                "type": "object",
                                "properties": {
                                  "available": {
                                    "type": "boolean"
                                  },
                                  "locations": {
                                    "type": "integer"
                                  },
                                  "airports": {
                                    "type": "integer"
                                  }
                                },
                                "required": [
                                  "available"
                                ]
                              }
                            }
                          }
                        },
                        "required": [
                          "country_code",
                          "name",
                          "products"
                        ]
                      }
                    }
                  },
                  "required": [
                    "countries"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No token or a malformed one (`unauthorized`, `invalid_token`). Note the wrong KIND of token is a 403 `wrong_token_type`, not a 401: /v1 requires an API access token from POST /oauth/token, and an SDK session token is refused as a permission problem rather than an authentication one."
          },
          "403": {
            "description": "Authenticated, but not permitted. `wrong_token_type`: an SDK session token was sent to a route that needs an API access token. `insufficient_scope`: the credential was issued without the scope this route needs -- a new credential fixes it. `product_not_enabled`: your account is not enabled for this product, which is a commercial setting rather than a bug, so contact your account manager instead of retrying. Note ownership answers 404, never 403."
          },
          "500": {
            "description": "Could not load coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/oauth/token": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Exchange client credentials for an API access token",
        "description": "RFC 6749 §4.4 client-credentials grant. Present the client_id and client_secret issued to you, either as HTTP Basic auth or in the body. Returns a Bearer token valid for one hour, carrying the scopes granted to that credential. Every failure returns a uniform `invalid_client`, so the endpoint cannot be used to discover which client ids exist.",
        "servers": [
          {
            "url": "https://{your-base-url}",
            "description": "Issued to you at onboarding"
          }
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "client_credentials"
                    ]
                  },
                  "client_id": {
                    "type": "string",
                    "example": "dc_ci_0123456789abcdef01234567"
                  },
                  "client_secret": {
                    "type": "string",
                    "example": "dc_cs_0123456789abcdef0123456789abcdef"
                  },
                  "scope": {
                    "type": "string",
                    "description": "Optional, space-separated. Narrows the token to a subset of what the credential holds; it can never widen it. Omit for everything granted.",
                    "example": "bookings:read"
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "client_credentials"
                    ]
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "client_secret": {
                    "type": "string"
                  },
                  "scope": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "An access token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "enum": [
                        "Bearer"
                      ]
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 3600
                    },
                    "scope": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "unsupported_grant_type, or invalid_scope."
          },
          "401": {
            "description": "invalid_client — uniform for every credential failure."
          },
          "503": {
            "description": "temporarily_unavailable — PARTNER_TOKEN_SECRET is not configured in this environment, so no verifiable token can be issued."
          }
        }
      }
    }
  }
}
