{"info":{"description":"Find, price and book stays through Mavio's partner API. Send your API key as `Authorization: Bearer`. Read the [guides and API reference](https://docs.mavio.com) to get started.","title":"Mavio Unified Travel API","version":"1.2.3"},"openapi":"3.0.3","servers":[{"url":"https://api.mavio.com"}],"tags":[{"description":"Committed booking events for pull recovery.","name":"Events"},{"description":"Partner-owned webhook registrations and durable event delivery.","name":"Webhooks"},{"description":"Places to stay in the Mavio catalogue.","name":"Listings"},{"description":"Prices for a stay at one listing. Test keys price the same listings without reaching a hotel.","name":"Quotes"},{"description":"The shopper's hold on their card for one offer, which Adyen's own card component takes, so the card never reaches your servers. Test keys charge no card: a test payment is authorized with the authorize test helper.","name":"Payments"},{"description":"What your partner booked, as it was sold, and where each booking stands. Reading them never reaches a supplier.","name":"Bookings"},{"description":"What Mavio owes you: your markup on confirmed bookings and your share of cancellation penalties, in each currency the bookings were sold in.","name":"Balance"},{"description":"How your partner used the API: its requests, errors and latency per endpoint, and its bookings, a day at a time.","name":"Usage"},{"description":"Cause a bad day on purpose in test mode, so you can build for it before going live. Only test keys can call them, and they only change what your partner's test keys see.","name":"Test helpers"},{"description":"The partner your API key belongs to, and the sites Adyen's component takes your test payments on. Changing them takes an admin key.","name":"Partner"},{"description":"Your fixed markup rules for individual listings and hotel chains, across suppliers and modes.","name":"Pricing rules"},{"description":"The keys your servers call the API with. Managing them takes an admin key, which signing in to the app gives you.","name":"API keys","x-displayName":"API keys"}],"components":{"securitySchemes":{"bearerAuth":{"description":"Your API key, as `Authorization: Bearer sk_test_...`.","scheme":"bearer","type":"http"}},"schemas":{"ChainList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Chain"},"description":"Every hotel chain, by name.","example":[{"brands":[{"code":"westin","name":"Westin"}],"code":"marriott","name":"Marriott International","object":"chain"}]},"object":{"type":"string","enum":["list"],"description":"The type of object. Always `list`.","example":"list"}},"required":["data","object"]},"Chain":{"type":"object","properties":{"code":{"type":"string","description":"The normalized Mavio code.","example":"marriott"},"name":{"type":"string","description":"The name to show, untranslated.","example":"Marriott International"},"brands":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"The normalized Mavio code.","example":"westin"},"name":{"type":"string","description":"The name to show, untranslated.","example":"Westin"}},"required":["code","name"]},"description":"Its brands, by name. A company with one brand lists it under its own code.","example":[{"code":"westin","name":"Westin"}]},"object":{"type":"string","enum":["chain"],"description":"The type of object. Always `chain`.","example":"chain"}},"required":["code","name","brands","object"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["api_key_expired","api_key_invalid","api_key_limit_reached","api_key_missing","api_key_revoked","body_too_large","booking_already_cancelled","booking_not_at_supplier","booking_status_unexpected","cancellation_deadline_passed","cancellation_in_progress","currency_not_supported","idempotency_key_in_use","idempotency_key_reused","internal_error","invalid_request","offer_changed","offer_unavailable","payment_not_found","payment_status_unexpected","payment_unavailable","permission_denied","quote_expired","rate_limited","refund_status_unexpected","resource_missing","route_not_found","supplier_unavailable","test_origin_exists","test_origin_limit_reached","unsupported_media_type","usage_unavailable"],"description":"Stable error code. Branch on this, not on `message`. See [error codes](https://docs.mavio.com/errors) for what each means and what to do.\n\n- [`api_key_expired`](https://docs.mavio.com/errors/api_key_expired)\n- [`api_key_invalid`](https://docs.mavio.com/errors/api_key_invalid)\n- [`api_key_limit_reached`](https://docs.mavio.com/errors/api_key_limit_reached)\n- [`api_key_missing`](https://docs.mavio.com/errors/api_key_missing)\n- [`api_key_revoked`](https://docs.mavio.com/errors/api_key_revoked)\n- [`body_too_large`](https://docs.mavio.com/errors/body_too_large)\n- [`booking_already_cancelled`](https://docs.mavio.com/errors/booking_already_cancelled)\n- [`booking_not_at_supplier`](https://docs.mavio.com/errors/booking_not_at_supplier)\n- [`booking_status_unexpected`](https://docs.mavio.com/errors/booking_status_unexpected)\n- [`cancellation_deadline_passed`](https://docs.mavio.com/errors/cancellation_deadline_passed)\n- [`cancellation_in_progress`](https://docs.mavio.com/errors/cancellation_in_progress)\n- [`currency_not_supported`](https://docs.mavio.com/errors/currency_not_supported)\n- [`idempotency_key_in_use`](https://docs.mavio.com/errors/idempotency_key_in_use)\n- [`idempotency_key_reused`](https://docs.mavio.com/errors/idempotency_key_reused)\n- [`internal_error`](https://docs.mavio.com/errors/internal_error)\n- [`invalid_request`](https://docs.mavio.com/errors/invalid_request)\n- [`offer_changed`](https://docs.mavio.com/errors/offer_changed)\n- [`offer_unavailable`](https://docs.mavio.com/errors/offer_unavailable)\n- [`payment_not_found`](https://docs.mavio.com/errors/payment_not_found)\n- [`payment_status_unexpected`](https://docs.mavio.com/errors/payment_status_unexpected)\n- [`payment_unavailable`](https://docs.mavio.com/errors/payment_unavailable)\n- [`permission_denied`](https://docs.mavio.com/errors/permission_denied)\n- [`quote_expired`](https://docs.mavio.com/errors/quote_expired)\n- [`rate_limited`](https://docs.mavio.com/errors/rate_limited)\n- [`refund_status_unexpected`](https://docs.mavio.com/errors/refund_status_unexpected)\n- [`resource_missing`](https://docs.mavio.com/errors/resource_missing)\n- [`route_not_found`](https://docs.mavio.com/errors/route_not_found)\n- [`supplier_unavailable`](https://docs.mavio.com/errors/supplier_unavailable)\n- [`test_origin_exists`](https://docs.mavio.com/errors/test_origin_exists)\n- [`test_origin_limit_reached`](https://docs.mavio.com/errors/test_origin_limit_reached)\n- [`unsupported_media_type`](https://docs.mavio.com/errors/unsupported_media_type)\n- [`usage_unavailable`](https://docs.mavio.com/errors/usage_unavailable)","example":"invalid_request"},"message":{"type":"string","description":"Human-readable explanation. Its wording can change.","example":"Invalid request"},"param":{"type":"string","description":"The request parameter the error is about, when there is one.","example":"id"}},"required":["code","message"],"description":"What went wrong."}},"required":["error"]},"ListingChangeList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ListingChange"},"description":"The changes on this page, in feed order. Changes to one listing can be merged into its latest.","example":[{"changedAt":"2026-10-15T14:30:00.000Z","id":"lch_031OeqUcl4UtGlNOdBpZCM","kind":"updated","listing":{"address":"9 Rue de Lancry, 75010 Paris","amenities":["air_conditioning","free_wifi_internet"],"brand":null,"chain":null,"contactInformation":null,"countryCode":"FR","createdAt":"2026-10-01T09:00:00.000Z","description":"Twelve rooms on the Canal Saint-Martin, five minutes from République.\n\n- Breakfast in the courtyard\n- Bikes to borrow","guestRating":{"reviewCount":1284,"score":8.6},"id":"lst_031OeqUcl4UtGlNOdBpZCK","importantInformation":"Check-in from 15:00.","legalInformation":null,"location":{"lat":48.8702,"lng":2.3627},"name":"Hôtel du Canal","object":"listing","photos":[{"caption":"Courtyard","url":"https://photos.mavio.com/7b0c7ce955ae0f6f9a3d7b32b2f7be047e22a8b17a16dd19d36e2c929f6b1bf1.jpg"},{"caption":null,"url":"https://photos.mavio.com/47d68a396845b5ce9618357bc394e2606fbb18bbebba31f2e4bdd24b02a99325.jpg"}],"policies":null,"propertyType":"hotel","rooms":[{"amenities":["minibar"],"beds":[{"count":1,"type":"double_bed"}],"description":"Overlooks the canal.","id":"rm_031OeqUcl4UtGlNOdBpZCL","maxGuests":2,"name":"Double Room","object":"room","photos":[{"caption":"Double Room","url":"https://photos.mavio.com/4c11774a7d4de83dbeb8702238398c337a3d5aa4ef6f45eca27b07bbb81ed10c.jpg"}],"sizeSqm":18}],"stars":3.5,"updatedAt":"2026-10-15T14:30:00.000Z"},"listingId":"lst_031OeqUcl4UtGlNOdBpZCK","mergedIntoListingId":null,"object":"listing_change"}]},"hasMore":{"type":"boolean","description":"Whether more changes are ready now. When false, call again later with nextCursor.","example":true},"nextCursor":{"type":"string","description":"Pass it as `after` to get the changes after this page. Every page has one, including an empty page.","example":"WyI3NDUxIiwiMDE5YTBmM2MtN2IyZS03YzQxLTlhNmQtM2Y1ZThiMmMxZDQwIl0"},"object":{"type":"string","enum":["list"],"description":"The type of object. Always `list`.","example":"list"}},"required":["data","hasMore","nextCursor","object"]},"ListingChange":{"type":"object","properties":{"changedAt":{"type":"string","format":"date-time","description":"When the change happened, in UTC.","example":"2026-10-15T14:30:00.000Z"},"id":{"type":"string","pattern":"^lch_[0-9A-Za-z]{22}$","description":"Unique identifier for the change.","example":"lch_031OeqUcl4UtGlNOdBpZCM"},"kind":{"type":"string","enum":["created","updated","removed","merged"],"description":"What happened: `created` when the listing became available, `updated` when it changed in a way you can see, `removed` when it stopped being available, `merged` when it turned out to be the same place as `mergedIntoListingId`.","example":"updated"},"listing":{"type":"object","nullable":true,"properties":{"address":{"type":"string","nullable":true,"description":"Street address of the listing on one line, or null when we have none.","example":"9 Rue de Lancry, 75010 Paris"},"amenities":{"type":"array","items":{"type":"string","enum":["accessible_bath_shower","accessible_by_elevator","accessible_by_lift","accessible_by_stairs_only","accessible_parking","accessible_property","accessible_rooms_available","additional_bathroom","air_conditioning","airport_transportation_available","all_inclusive","balcony_or_terrace","bar","bath","bath_or_shower","bathroom","bathtub","beach_access","beach_front","body_soap","breakfast_available","business_facilities","carbon_monoxide_detector","childcare_services","childrens_high_chair","city_view","cleaning_products","coffee_tea_maker","computer","concierge_services","conditioner","connecting_room_available","courtyard_view","cribs_or_cots_available","desk","dining_area","dining_table","dishwasher","dressing_room","dryer","electric_vehicle_charging_station","emergency_cord_in_bathroom","extra_long_bed","family_friendly","fan","fire_alarm","fire_extinguisher","fireplace","foldup_bed_available","free_airport_transportation","free_breakfast","free_laundry_services","free_parking","free_shuttle_available","free_toiletries","free_wifi_internet","front_desk_24_hour","garden","garden_view","golf_course_within_2_mi","ground_floor_unit","gym","hairdryer","heating","hot_tub_jacuzzi","housekeeping_available","internet","ironing_facilities","kettle","key_access","key_card_access","kitchen","kitchenette","kitchenware","lake_view","large_vehicle_parking","laundry_services","linens","microwave","minibar","mountain_view","no_pets_allowed","non_smoking","ocean_front","outdoor_bathroom","outdoor_cooking","outdoor_dining_area","oven","parking","patio","pets_allowed","pool","private_bathroom","private_beach_access","private_entrance","private_hot_tub_jacuzzi","private_pool_access","private_unit_in_building","refrigerator","restaurant","river_view","rollin_shower","room_service","safe","satellite_cable_channels","sauna","sea_ocean_view","self_check_in","shampoo","shared_bathroom","shared_kitchen","shared_living_spaces","shower","shuttle_available","ski_in_ski_out","smoking_allowed","sofa","sofa_bed","spa","spa_bath","stove","streaming_service","street_or_offsite_parking","telephone","tennis_court","toilet","toilet_paper","toilet_with_grab_rails","towels","towels_sheets_extra_fee","tv","view","wardrobe_or_closet","washer_dryer","washing_machine","water_view","waterfront","wheelchair_accessible","wine_glasses"]},"description":"Codes of the amenities the listing offers.","example":["air_conditioning","free_wifi_internet"]},"brand":{"type":"object","nullable":true,"properties":{"code":{"type":"string","description":"The code `chains[]` on `GET /v1/listings` takes.","example":"westin"},"name":{"type":"string","description":"The name to show, untranslated.","example":"Westin"}},"required":["code","name"],"description":"The name the listing trades under, one of its chain’s brands, or null when it has no chain or we don’t know which brand.","example":{"code":"westin","name":"Westin"}},"chain":{"type":"object","nullable":true,"properties":{"code":{"type":"string","description":"The code `chains[]` on `GET /v1/listings` takes.","example":"marriott"},"name":{"type":"string","description":"The name to show, untranslated.","example":"Marriott International"}},"required":["code","name"],"description":"The hotel company the listing belongs to, or null for an independent.","example":{"code":"marriott","name":"Marriott International"}},"contactInformation":{"type":"object","nullable":true,"properties":{"email":{"type":"string","nullable":true,"minLength":1,"description":"Public property email contact as supplied.","example":null},"fax":{"type":"string","nullable":true,"minLength":1,"description":"Public property fax number.","example":null},"phone":{"type":"string","nullable":true,"minLength":1,"description":"Public property telephone, retaining the supplier formatting.","example":null},"website":{"type":"string","nullable":true,"minLength":1,"description":"Public property website as supplied; not assumed to be a validated URL.","example":null}},"required":["email","fax","phone","website"],"additionalProperties":false,"description":"Public property contacts, or null when unknown."},"countryCode":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter code of the country the listing is in.","example":"FR"},"createdAt":{"type":"string","format":"date-time","description":"When the listing entered our catalogue, in UTC. It can be earlier than when partners could first see it.","example":"2026-10-01T09:00:00.000Z"},"description":{"type":"string","description":"Free-text description of the listing, in plain text, never HTML. Paragraphs are separated by a blank line, and each list item is a line starting with `- `.","example":"Twelve rooms on the Canal Saint-Martin, five minutes from République.\n\n- Breakfast in the courtyard\n- Bikes to borrow"},"guestRating":{"type":"object","nullable":true,"properties":{"reviewCount":{"type":"integer","minimum":1,"description":"How many guest reviews the score averages.","example":1284},"score":{"type":"number","minimum":0,"maximum":10,"description":"Average guest review score, from 0 to 10.","example":8.6}},"required":["reviewCount","score"],"description":"What guests rated their stay, or null when no reviews back a score.","example":{"reviewCount":1284,"score":8.6}},"id":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"Unique identifier for the listing.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"importantInformation":{"type":"string","nullable":true,"description":"Important property information in plain text, including conditions not captured in structured policies.","example":"Check-in from 15:00."},"legalInformation":{"type":"object","nullable":true,"properties":{"legalEntity":{"type":"string","nullable":true,"minLength":1,"description":"Registered legal entity operating the property.","example":"Hotel SAS"},"licenceNumbers":{"type":"array","items":{"type":"string","minLength":1},"description":"Property licence numbers as supplied.","example":[]},"registrationNumber":{"type":"string","nullable":true,"minLength":1,"description":"Registration number as supplied, without an assumed jurisdiction.","example":null}},"required":["legalEntity","licenceNumbers","registrationNumber"],"additionalProperties":false,"description":"Legal entity and property registration details, or null when unknown."},"location":{"$ref":"#/components/schemas/Location"},"name":{"type":"string","description":"Display name of the listing.","example":"Hôtel du Canal"},"object":{"type":"string","enum":["listing"],"description":"The type of object. Always `listing`.","example":"listing"},"photos":{"type":"array","items":{"$ref":"#/components/schemas/Photo"},"description":"Photos of the listing, in the order to show them, the first being its cover. A listing you can see always has at least one.","example":[{"caption":"Courtyard","url":"https://photos.mavio.com/7b0c7ce955ae0f6f9a3d7b32b2f7be047e22a8b17a16dd19d36e2c929f6b1bf1.jpg"},{"caption":null,"url":"https://photos.mavio.com/47d68a396845b5ce9618357bc394e2606fbb18bbebba31f2e4bdd24b02a99325.jpg"}]},"policies":{"type":"object","nullable":true,"properties":{"cancellationDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"General property text only. Rate-specific cancellation terms come from the quote.","example":null},"checkInEndTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Check-in deadline, in local HH:mm. May be after midnight.","example":"23:00"},"checkInEndTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-in deadline text when no HH:mm value can be established.","example":null},"checkInInstructions":{"type":"array","items":{"type":"string","minLength":1},"default":[],"description":"Arrival instructions in plain text.","example":["Bring photo ID."]},"checkInTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Usual check-in start, in local HH:mm without an assumed timezone.","example":"15:00"},"checkInTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-in start text when no HH:mm value can be established.","example":null},"checkOutTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Usual check-out deadline, in local HH:mm.","example":"11:00"},"checkOutTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-out deadline text when no HH:mm value can be established.","example":null},"children":{"type":"object","nullable":true,"properties":{"allowed":{"type":"boolean","nullable":true,"default":null,"description":"Whether children are admitted; null when unstated.","example":true},"cribAvailable":{"type":"boolean","nullable":true,"default":null,"description":"Whether a crib is available; null when unstated.","example":null},"cribCharge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Crib charge, without an assumed currency or unit.","example":null},"cribMaxAge":{"type":"integer","nullable":true,"minimum":0,"default":null,"description":"Maximum age eligible for a crib; null when unstated.","example":null},"infantsAllowed":{"type":"boolean","nullable":true,"default":null,"description":"Whether infants are admitted; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Child admission and crib conditions.","example":null},"descriptions":{"type":"array","items":{"type":"object","properties":{"children":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Child admission conditions in plain text.","example":null},"description":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Policy or restriction in plain text, or null when unstated.","example":null},"name":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier name for this policy.","example":"Pets"},"parking":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Parking conditions in plain text.","example":null},"pets":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Pet conditions in plain text.","example":null},"type":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier policy category, retained as text.","example":"pets"}},"additionalProperties":false},"default":[],"description":"Supplier policy text retaining conditions not represented by structured fields.","example":[]},"groups":{"type":"object","nullable":true,"properties":{"minimumRoomCount":{"type":"integer","minimum":0,"description":"Minimum rooms for group booking conditions, not a maximum per reservation.","example":5}},"default":null,"required":["minimumRoomCount"],"additionalProperties":false,"description":"Group booking conditions.","example":null},"houseRules":{"type":"array","items":{"type":"string","minLength":1},"default":[],"description":"Property house rules in plain text.","example":[]},"minimumCheckInAge":{"type":"integer","nullable":true,"minimum":0,"default":null,"description":"Minimum age of the person checking in, not the minimum age of every guest.","example":18},"parking":{"type":"object","nullable":true,"properties":{"available":{"type":"boolean","nullable":true,"default":null,"description":"Whether any parking is available, independent of self-parking or valet availability.","example":true},"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"chargeMode":{"type":"string","nullable":true,"enum":["free","per_day","per_hour","charges_may_apply","charges_apply",null],"default":null,"description":"Distinguishes free, daily, hourly, definite and possible charges.","example":"charges_may_apply"},"evCharger":{"type":"boolean","nullable":true,"default":null,"description":"Whether electric vehicle charging is available; null when unstated.","example":null},"free":{"type":"boolean","nullable":true,"default":null,"description":"Whether parking is free; null when unstated.","example":null},"location":{"type":"string","nullable":true,"enum":["on_site","off_site",null],"default":null,"description":"Whether parking is at the property or off site.","example":"on_site"},"reservationRequired":{"type":"boolean","nullable":true,"default":null,"description":"Whether parking must be reserved; null when unstated.","example":null},"selfParking":{"type":"boolean","nullable":true,"default":null,"description":"Whether self-parking is available; null when unstated.","example":null},"valet":{"type":"boolean","nullable":true,"default":null,"description":"Whether valet parking is available; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Parking availability and charges.","example":null},"payment":{"type":"object","nullable":true,"properties":{"cardsAccepted":{"type":"boolean","nullable":true,"default":null,"description":"Whether the property accepts cards.","example":true},"cashAccepted":{"type":"boolean","nullable":true,"default":null,"description":"Whether the property accepts cash.","example":null}},"default":null,"additionalProperties":false,"description":"Property payment acceptance, independent of the booking payment method.","example":null},"pets":{"type":"object","nullable":true,"properties":{"allowed":{"type":"string","nullable":true,"enum":["allowed","not_allowed","assistive_animals_only","by_arrangement","other",null],"default":null,"description":"OpenTravel PetsAllowed concepts. Null means unstated; prose may impose additional restrictions.","example":"by_arrangement"},"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"chargeRequired":{"type":"boolean","nullable":true,"default":null,"description":"Whether a pet fee applies; null when unstated.","example":null},"description":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Policy or restriction in plain text, or null when unstated.","example":null},"maximumWeight":{"type":"object","nullable":true,"properties":{"unit":{"type":"string","enum":["lb"],"description":"Weight unit, pounds.","example":"lb"},"value":{"type":"number","minimum":0,"description":"Maximum pet weight.","example":25}},"default":null,"required":["unit","value"],"additionalProperties":false,"description":"Maximum permitted pet weight with its original unit.","example":null},"refundable":{"type":"boolean","nullable":true,"default":null,"description":"Whether the pet fee is refundable; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Pet admission, charges and restrictions.","example":null},"securityDeposit":{"type":"object","nullable":true,"properties":{"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"collectedAt":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of when the security deposit is collected.","example":"checkin"},"paymentMethod":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of the security deposit payment method.","example":"credit_card"},"refundedAt":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of when the security deposit is returned.","example":"checkout"},"required":{"type":"boolean","nullable":true,"default":null,"description":"Whether a refundable security deposit is required.","example":true}},"default":null,"additionalProperties":false,"description":"Refundable property security deposit, not booking prepayment or a cancellation penalty.","example":null},"specialCheckInInstructions":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Additional arrival instructions in plain text.","example":null}},"additionalProperties":false,"description":"OpenTravel-aligned property policies, or null when unknown. Text follows the requested language with English fallback; rate-specific terms come from the quote."},"propertyType":{"type":"string","nullable":true,"enum":["aparthotel","apartment","bed_and_breakfast","cabin","capsule_hotel","chalet","guest_house","holiday_home","homestay","hostel","hotel","resort","villa",null],"description":"Mavio property type, or null when unmapped.","example":"hotel"},"rooms":{"type":"array","items":{"$ref":"#/components/schemas/Room"},"description":"Rooms a guest can book at the listing, merged across sources.","example":[{"amenities":["minibar"],"beds":[{"count":1,"type":"double_bed"}],"description":"Overlooks the canal.","id":"rm_031OeqUcl4UtGlNOdBpZCL","maxGuests":2,"name":"Double Room","object":"room","photos":[{"caption":"Double Room","url":"https://photos.mavio.com/4c11774a7d4de83dbeb8702238398c337a3d5aa4ef6f45eca27b07bbb81ed10c.jpg"}],"sizeSqm":18}]},"stars":{"type":"number","nullable":true,"minimum":0,"maximum":5,"description":"Official star rating from 0 to 5 in half steps, or null when the listing has none.","example":3.5},"updatedAt":{"type":"string","format":"date-time","description":"When the listing last changed in a way partners can see, in UTC.","example":"2026-10-15T14:30:00.000Z"}},"required":["address","amenities","brand","chain","contactInformation","countryCode","createdAt","description","guestRating","id","importantInformation","legalInformation","location","name","object","photos","policies","propertyType","rooms","stars","updatedAt"],"description":"The listing as it is now, which can already include later changes, or null when it is no longer available. Store it, or delete your copy when it is null.","example":{"address":"9 Rue de Lancry, 75010 Paris","amenities":["air_conditioning","free_wifi_internet"],"brand":null,"chain":null,"contactInformation":null,"countryCode":"FR","createdAt":"2026-10-01T09:00:00.000Z","description":"Twelve rooms on the Canal Saint-Martin, five minutes from République.\n\n- Breakfast in the courtyard\n- Bikes to borrow","guestRating":{"reviewCount":1284,"score":8.6},"id":"lst_031OeqUcl4UtGlNOdBpZCK","importantInformation":"Check-in from 15:00.","legalInformation":null,"location":{"lat":48.8702,"lng":2.3627},"name":"Hôtel du Canal","object":"listing","photos":[{"caption":"Courtyard","url":"https://photos.mavio.com/7b0c7ce955ae0f6f9a3d7b32b2f7be047e22a8b17a16dd19d36e2c929f6b1bf1.jpg"},{"caption":null,"url":"https://photos.mavio.com/47d68a396845b5ce9618357bc394e2606fbb18bbebba31f2e4bdd24b02a99325.jpg"}],"policies":null,"propertyType":"hotel","rooms":[{"amenities":["minibar"],"beds":[{"count":1,"type":"double_bed"}],"description":"Overlooks the canal.","id":"rm_031OeqUcl4UtGlNOdBpZCL","maxGuests":2,"name":"Double Room","object":"room","photos":[{"caption":"Double Room","url":"https://photos.mavio.com/4c11774a7d4de83dbeb8702238398c337a3d5aa4ef6f45eca27b07bbb81ed10c.jpg"}],"sizeSqm":18}],"stars":3.5,"updatedAt":"2026-10-15T14:30:00.000Z"}},"listingId":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The listing that changed.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"mergedIntoListingId":{"type":"string","nullable":true,"pattern":"^lst_[0-9A-Za-z]{22}$","description":"For `merged`, the listing that replaces this one: move anything you keep under listingId to it. Null for every other kind.","example":null},"object":{"type":"string","enum":["listing_change"],"description":"The type of object. Always `listing_change`.","example":"listing_change"}},"required":["changedAt","id","kind","listing","listingId","mergedIntoListingId","object"]},"Location":{"type":"object","properties":{"lat":{"type":"number","minimum":-90,"maximum":90,"description":"Latitude in decimal degrees (WGS 84).","example":48.8702},"lng":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude in decimal degrees (WGS 84).","example":2.3627}},"required":["lat","lng"],"description":"Where the listing is, as a point on the map."},"Photo":{"type":"object","properties":{"caption":{"type":"string","nullable":true,"description":"Short text saying what the photo shows, or null when it has none.","example":"Courtyard"},"url":{"type":"string","format":"uri","description":"Where to load the photo, at its original size. Load it from this URL or copy it: the file behind a URL never changes, so you can cache it for as long as you like. A URL can keep working after the photo leaves the gallery.","example":"https://photos.mavio.com/7b0c7ce955ae0f6f9a3d7b32b2f7be047e22a8b17a16dd19d36e2c929f6b1bf1.jpg"}},"required":["caption","url"]},"Room":{"type":"object","properties":{"amenities":{"type":"array","items":{"type":"string","enum":["accessible_bath_shower","accessible_by_elevator","accessible_by_lift","accessible_by_stairs_only","accessible_parking","accessible_property","accessible_rooms_available","additional_bathroom","air_conditioning","airport_transportation_available","all_inclusive","balcony_or_terrace","bar","bath","bath_or_shower","bathroom","bathtub","beach_access","beach_front","body_soap","breakfast_available","business_facilities","carbon_monoxide_detector","childcare_services","childrens_high_chair","city_view","cleaning_products","coffee_tea_maker","computer","concierge_services","conditioner","connecting_room_available","courtyard_view","cribs_or_cots_available","desk","dining_area","dining_table","dishwasher","dressing_room","dryer","electric_vehicle_charging_station","emergency_cord_in_bathroom","extra_long_bed","family_friendly","fan","fire_alarm","fire_extinguisher","fireplace","foldup_bed_available","free_airport_transportation","free_breakfast","free_laundry_services","free_parking","free_shuttle_available","free_toiletries","free_wifi_internet","front_desk_24_hour","garden","garden_view","golf_course_within_2_mi","ground_floor_unit","gym","hairdryer","heating","hot_tub_jacuzzi","housekeeping_available","internet","ironing_facilities","kettle","key_access","key_card_access","kitchen","kitchenette","kitchenware","lake_view","large_vehicle_parking","laundry_services","linens","microwave","minibar","mountain_view","no_pets_allowed","non_smoking","ocean_front","outdoor_bathroom","outdoor_cooking","outdoor_dining_area","oven","parking","patio","pets_allowed","pool","private_bathroom","private_beach_access","private_entrance","private_hot_tub_jacuzzi","private_pool_access","private_unit_in_building","refrigerator","restaurant","river_view","rollin_shower","room_service","safe","satellite_cable_channels","sauna","sea_ocean_view","self_check_in","shampoo","shared_bathroom","shared_kitchen","shared_living_spaces","shower","shuttle_available","ski_in_ski_out","smoking_allowed","sofa","sofa_bed","spa","spa_bath","stove","streaming_service","street_or_offsite_parking","telephone","tennis_court","toilet","toilet_paper","toilet_with_grab_rails","towels","towels_sheets_extra_fee","tv","view","wardrobe_or_closet","washer_dryer","washing_machine","water_view","waterfront","wheelchair_accessible","wine_glasses"]},"description":"Codes of the amenities the room offers.","example":["minibar"]},"beds":{"type":"array","items":{"$ref":"#/components/schemas/Bed"},"description":"Beds in the room.","example":[{"count":1,"type":"double_bed"}]},"description":{"type":"string","nullable":true,"description":"Free-text description of the room, in the same plain text as the listing’s, or null when we have none.","example":"Overlooks the canal."},"id":{"type":"string","pattern":"^rm_[0-9A-Za-z]{22}$","description":"Unique identifier for the room.","example":"rm_031OeqUcl4UtGlNOdBpZCL"},"maxGuests":{"type":"integer","nullable":true,"minimum":1,"description":"Most guests the room sleeps, or null when unknown.","example":2},"name":{"type":"string","description":"Display name of the room.","example":"Double Room"},"object":{"type":"string","enum":["room"],"description":"The type of object. Always `room`.","example":"room"},"photos":{"type":"array","items":{"$ref":"#/components/schemas/Photo"},"description":"Photos of the room, in the order to show them, or empty when we have none.","example":[{"caption":"Double Room","url":"https://photos.mavio.com/4c11774a7d4de83dbeb8702238398c337a3d5aa4ef6f45eca27b07bbb81ed10c.jpg"}]},"sizeSqm":{"type":"integer","nullable":true,"minimum":1,"description":"Floor area in square metres, or null when unknown.","example":18}},"required":["amenities","beds","description","id","maxGuests","name","object","photos","sizeSqm"]},"Bed":{"type":"object","properties":{"count":{"type":"integer","minimum":1,"description":"How many beds of this type the room has.","example":1},"type":{"type":"string","enum":["air_mattress","bunk_bed","crib","double_bed","futon","king_bed","murphy_bed","queen_bed","rollaway_bed","single_bed","sofa_bed","super_king_bed"],"description":"Type of bed.","example":"double_bed"}},"required":["count","type"]},"Listing":{"type":"object","properties":{"address":{"type":"string","nullable":true,"description":"Street address of the listing on one line, or null when we have none.","example":"9 Rue de Lancry, 75010 Paris"},"amenities":{"type":"array","items":{"type":"string","enum":["accessible_bath_shower","accessible_by_elevator","accessible_by_lift","accessible_by_stairs_only","accessible_parking","accessible_property","accessible_rooms_available","additional_bathroom","air_conditioning","airport_transportation_available","all_inclusive","balcony_or_terrace","bar","bath","bath_or_shower","bathroom","bathtub","beach_access","beach_front","body_soap","breakfast_available","business_facilities","carbon_monoxide_detector","childcare_services","childrens_high_chair","city_view","cleaning_products","coffee_tea_maker","computer","concierge_services","conditioner","connecting_room_available","courtyard_view","cribs_or_cots_available","desk","dining_area","dining_table","dishwasher","dressing_room","dryer","electric_vehicle_charging_station","emergency_cord_in_bathroom","extra_long_bed","family_friendly","fan","fire_alarm","fire_extinguisher","fireplace","foldup_bed_available","free_airport_transportation","free_breakfast","free_laundry_services","free_parking","free_shuttle_available","free_toiletries","free_wifi_internet","front_desk_24_hour","garden","garden_view","golf_course_within_2_mi","ground_floor_unit","gym","hairdryer","heating","hot_tub_jacuzzi","housekeeping_available","internet","ironing_facilities","kettle","key_access","key_card_access","kitchen","kitchenette","kitchenware","lake_view","large_vehicle_parking","laundry_services","linens","microwave","minibar","mountain_view","no_pets_allowed","non_smoking","ocean_front","outdoor_bathroom","outdoor_cooking","outdoor_dining_area","oven","parking","patio","pets_allowed","pool","private_bathroom","private_beach_access","private_entrance","private_hot_tub_jacuzzi","private_pool_access","private_unit_in_building","refrigerator","restaurant","river_view","rollin_shower","room_service","safe","satellite_cable_channels","sauna","sea_ocean_view","self_check_in","shampoo","shared_bathroom","shared_kitchen","shared_living_spaces","shower","shuttle_available","ski_in_ski_out","smoking_allowed","sofa","sofa_bed","spa","spa_bath","stove","streaming_service","street_or_offsite_parking","telephone","tennis_court","toilet","toilet_paper","toilet_with_grab_rails","towels","towels_sheets_extra_fee","tv","view","wardrobe_or_closet","washer_dryer","washing_machine","water_view","waterfront","wheelchair_accessible","wine_glasses"]},"description":"Codes of the amenities the listing offers.","example":["air_conditioning","free_wifi_internet"]},"brand":{"type":"object","nullable":true,"properties":{"code":{"type":"string","description":"The code `chains[]` on `GET /v1/listings` takes.","example":"westin"},"name":{"type":"string","description":"The name to show, untranslated.","example":"Westin"}},"required":["code","name"],"description":"The name the listing trades under, one of its chain’s brands, or null when it has no chain or we don’t know which brand.","example":{"code":"westin","name":"Westin"}},"chain":{"type":"object","nullable":true,"properties":{"code":{"type":"string","description":"The code `chains[]` on `GET /v1/listings` takes.","example":"marriott"},"name":{"type":"string","description":"The name to show, untranslated.","example":"Marriott International"}},"required":["code","name"],"description":"The hotel company the listing belongs to, or null for an independent.","example":{"code":"marriott","name":"Marriott International"}},"contactInformation":{"type":"object","nullable":true,"properties":{"email":{"type":"string","nullable":true,"minLength":1,"description":"Public property email contact as supplied.","example":null},"fax":{"type":"string","nullable":true,"minLength":1,"description":"Public property fax number.","example":null},"phone":{"type":"string","nullable":true,"minLength":1,"description":"Public property telephone, retaining the supplier formatting.","example":null},"website":{"type":"string","nullable":true,"minLength":1,"description":"Public property website as supplied; not assumed to be a validated URL.","example":null}},"required":["email","fax","phone","website"],"additionalProperties":false,"description":"Public property contacts, or null when unknown."},"countryCode":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter code of the country the listing is in.","example":"FR"},"createdAt":{"type":"string","format":"date-time","description":"When the listing entered our catalogue, in UTC. It can be earlier than when partners could first see it.","example":"2026-10-01T09:00:00.000Z"},"description":{"type":"string","description":"Free-text description of the listing, in plain text, never HTML. Paragraphs are separated by a blank line, and each list item is a line starting with `- `.","example":"Twelve rooms on the Canal Saint-Martin, five minutes from République.\n\n- Breakfast in the courtyard\n- Bikes to borrow"},"guestRating":{"type":"object","nullable":true,"properties":{"reviewCount":{"type":"integer","minimum":1,"description":"How many guest reviews the score averages.","example":1284},"score":{"type":"number","minimum":0,"maximum":10,"description":"Average guest review score, from 0 to 10.","example":8.6}},"required":["reviewCount","score"],"description":"What guests rated their stay, or null when no reviews back a score.","example":{"reviewCount":1284,"score":8.6}},"id":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"Unique identifier for the listing.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"importantInformation":{"type":"string","nullable":true,"description":"Important property information in plain text, including conditions not captured in structured policies.","example":"Check-in from 15:00."},"legalInformation":{"type":"object","nullable":true,"properties":{"legalEntity":{"type":"string","nullable":true,"minLength":1,"description":"Registered legal entity operating the property.","example":"Hotel SAS"},"licenceNumbers":{"type":"array","items":{"type":"string","minLength":1},"description":"Property licence numbers as supplied.","example":[]},"registrationNumber":{"type":"string","nullable":true,"minLength":1,"description":"Registration number as supplied, without an assumed jurisdiction.","example":null}},"required":["legalEntity","licenceNumbers","registrationNumber"],"additionalProperties":false,"description":"Legal entity and property registration details, or null when unknown."},"location":{"$ref":"#/components/schemas/Location"},"name":{"type":"string","description":"Display name of the listing.","example":"Hôtel du Canal"},"object":{"type":"string","enum":["listing"],"description":"The type of object. Always `listing`.","example":"listing"},"photos":{"type":"array","items":{"$ref":"#/components/schemas/Photo"},"description":"Photos of the listing, in the order to show them, the first being its cover. A listing you can see always has at least one.","example":[{"caption":"Courtyard","url":"https://photos.mavio.com/7b0c7ce955ae0f6f9a3d7b32b2f7be047e22a8b17a16dd19d36e2c929f6b1bf1.jpg"},{"caption":null,"url":"https://photos.mavio.com/47d68a396845b5ce9618357bc394e2606fbb18bbebba31f2e4bdd24b02a99325.jpg"}]},"policies":{"type":"object","nullable":true,"properties":{"cancellationDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"General property text only. Rate-specific cancellation terms come from the quote.","example":null},"checkInEndTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Check-in deadline, in local HH:mm. May be after midnight.","example":"23:00"},"checkInEndTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-in deadline text when no HH:mm value can be established.","example":null},"checkInInstructions":{"type":"array","items":{"type":"string","minLength":1},"default":[],"description":"Arrival instructions in plain text.","example":["Bring photo ID."]},"checkInTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Usual check-in start, in local HH:mm without an assumed timezone.","example":"15:00"},"checkInTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-in start text when no HH:mm value can be established.","example":null},"checkOutTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Usual check-out deadline, in local HH:mm.","example":"11:00"},"checkOutTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-out deadline text when no HH:mm value can be established.","example":null},"children":{"type":"object","nullable":true,"properties":{"allowed":{"type":"boolean","nullable":true,"default":null,"description":"Whether children are admitted; null when unstated.","example":true},"cribAvailable":{"type":"boolean","nullable":true,"default":null,"description":"Whether a crib is available; null when unstated.","example":null},"cribCharge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Crib charge, without an assumed currency or unit.","example":null},"cribMaxAge":{"type":"integer","nullable":true,"minimum":0,"default":null,"description":"Maximum age eligible for a crib; null when unstated.","example":null},"infantsAllowed":{"type":"boolean","nullable":true,"default":null,"description":"Whether infants are admitted; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Child admission and crib conditions.","example":null},"descriptions":{"type":"array","items":{"type":"object","properties":{"children":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Child admission conditions in plain text.","example":null},"description":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Policy or restriction in plain text, or null when unstated.","example":null},"name":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier name for this policy.","example":"Pets"},"parking":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Parking conditions in plain text.","example":null},"pets":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Pet conditions in plain text.","example":null},"type":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier policy category, retained as text.","example":"pets"}},"additionalProperties":false},"default":[],"description":"Supplier policy text retaining conditions not represented by structured fields.","example":[]},"groups":{"type":"object","nullable":true,"properties":{"minimumRoomCount":{"type":"integer","minimum":0,"description":"Minimum rooms for group booking conditions, not a maximum per reservation.","example":5}},"default":null,"required":["minimumRoomCount"],"additionalProperties":false,"description":"Group booking conditions.","example":null},"houseRules":{"type":"array","items":{"type":"string","minLength":1},"default":[],"description":"Property house rules in plain text.","example":[]},"minimumCheckInAge":{"type":"integer","nullable":true,"minimum":0,"default":null,"description":"Minimum age of the person checking in, not the minimum age of every guest.","example":18},"parking":{"type":"object","nullable":true,"properties":{"available":{"type":"boolean","nullable":true,"default":null,"description":"Whether any parking is available, independent of self-parking or valet availability.","example":true},"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"chargeMode":{"type":"string","nullable":true,"enum":["free","per_day","per_hour","charges_may_apply","charges_apply",null],"default":null,"description":"Distinguishes free, daily, hourly, definite and possible charges.","example":"charges_may_apply"},"evCharger":{"type":"boolean","nullable":true,"default":null,"description":"Whether electric vehicle charging is available; null when unstated.","example":null},"free":{"type":"boolean","nullable":true,"default":null,"description":"Whether parking is free; null when unstated.","example":null},"location":{"type":"string","nullable":true,"enum":["on_site","off_site",null],"default":null,"description":"Whether parking is at the property or off site.","example":"on_site"},"reservationRequired":{"type":"boolean","nullable":true,"default":null,"description":"Whether parking must be reserved; null when unstated.","example":null},"selfParking":{"type":"boolean","nullable":true,"default":null,"description":"Whether self-parking is available; null when unstated.","example":null},"valet":{"type":"boolean","nullable":true,"default":null,"description":"Whether valet parking is available; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Parking availability and charges.","example":null},"payment":{"type":"object","nullable":true,"properties":{"cardsAccepted":{"type":"boolean","nullable":true,"default":null,"description":"Whether the property accepts cards.","example":true},"cashAccepted":{"type":"boolean","nullable":true,"default":null,"description":"Whether the property accepts cash.","example":null}},"default":null,"additionalProperties":false,"description":"Property payment acceptance, independent of the booking payment method.","example":null},"pets":{"type":"object","nullable":true,"properties":{"allowed":{"type":"string","nullable":true,"enum":["allowed","not_allowed","assistive_animals_only","by_arrangement","other",null],"default":null,"description":"OpenTravel PetsAllowed concepts. Null means unstated; prose may impose additional restrictions.","example":"by_arrangement"},"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"chargeRequired":{"type":"boolean","nullable":true,"default":null,"description":"Whether a pet fee applies; null when unstated.","example":null},"description":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Policy or restriction in plain text, or null when unstated.","example":null},"maximumWeight":{"type":"object","nullable":true,"properties":{"unit":{"type":"string","enum":["lb"],"description":"Weight unit, pounds.","example":"lb"},"value":{"type":"number","minimum":0,"description":"Maximum pet weight.","example":25}},"default":null,"required":["unit","value"],"additionalProperties":false,"description":"Maximum permitted pet weight with its original unit.","example":null},"refundable":{"type":"boolean","nullable":true,"default":null,"description":"Whether the pet fee is refundable; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Pet admission, charges and restrictions.","example":null},"securityDeposit":{"type":"object","nullable":true,"properties":{"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"collectedAt":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of when the security deposit is collected.","example":"checkin"},"paymentMethod":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of the security deposit payment method.","example":"credit_card"},"refundedAt":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of when the security deposit is returned.","example":"checkout"},"required":{"type":"boolean","nullable":true,"default":null,"description":"Whether a refundable security deposit is required.","example":true}},"default":null,"additionalProperties":false,"description":"Refundable property security deposit, not booking prepayment or a cancellation penalty.","example":null},"specialCheckInInstructions":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Additional arrival instructions in plain text.","example":null}},"additionalProperties":false,"description":"OpenTravel-aligned property policies, or null when unknown. Text follows the requested language with English fallback; rate-specific terms come from the quote."},"propertyType":{"type":"string","nullable":true,"enum":["aparthotel","apartment","bed_and_breakfast","cabin","capsule_hotel","chalet","guest_house","holiday_home","homestay","hostel","hotel","resort","villa",null],"description":"Mavio property type, or null when unmapped.","example":"hotel"},"rooms":{"type":"array","items":{"$ref":"#/components/schemas/Room"},"description":"Rooms a guest can book at the listing, merged across sources.","example":[{"amenities":["minibar"],"beds":[{"count":1,"type":"double_bed"}],"description":"Overlooks the canal.","id":"rm_031OeqUcl4UtGlNOdBpZCL","maxGuests":2,"name":"Double Room","object":"room","photos":[{"caption":"Double Room","url":"https://photos.mavio.com/4c11774a7d4de83dbeb8702238398c337a3d5aa4ef6f45eca27b07bbb81ed10c.jpg"}],"sizeSqm":18}]},"stars":{"type":"number","nullable":true,"minimum":0,"maximum":5,"description":"Official star rating from 0 to 5 in half steps, or null when the listing has none.","example":3.5},"updatedAt":{"type":"string","format":"date-time","description":"When the listing last changed in a way partners can see, in UTC.","example":"2026-10-15T14:30:00.000Z"}},"required":["address","amenities","brand","chain","contactInformation","countryCode","createdAt","description","guestRating","id","importantInformation","legalInformation","location","name","object","photos","policies","propertyType","rooms","stars","updatedAt"]},"ReviewList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Review"},"description":"The reviews on this page, newest first.","example":[{"comments":null,"cons":"There was no fridge in the room, so I had to ask for one.","headline":"A great central location in Midtown","id":"rev_031OeqUcl4UtGlNOdBpZCN","language":"en-US","object":"review","pros":"The bed was very comfortable, and the subway is a block away.","reviewedAt":"2026-10-16T00:00:00.000Z","reviewerCountry":"US","reviewerName":"Jessica","score":8,"travelerType":"solo"}]},"hasMore":{"type":"boolean","description":"Whether another page follows this one.","example":true},"nextCursor":{"type":"string","nullable":true,"description":"Pass it as `after` to get the next page. Null on the last page.","example":"WyIyMDI2LTEwLTE2VDAwOjAwOjAwLjAwMFoiLCIwMTlhMGYzYy03YjJlLTdjNDEtOWE2ZC0zZjVlOGIyYzFkNDAiXQ"},"object":{"type":"string","enum":["list"],"description":"The type of object. Always `list`.","example":"list"}},"required":["data","hasMore","nextCursor","object"]},"Review":{"type":"object","properties":{"comments":{"type":"string","nullable":true,"description":"What the guest wrote, in plain text, when the review doesn't split it into `pros` and `cons`. Null when it does, or when they wrote nothing.","example":null},"cons":{"type":"string","nullable":true,"description":"What the guest liked less, in plain text as the guest wrote it, or null when they wrote none.","example":"There was no fridge in the room, so I had to ask for one."},"headline":{"type":"string","nullable":true,"description":"The title the guest gave their review, in plain text as the guest wrote it, or null when they wrote none.","example":"A great central location in Midtown"},"id":{"type":"string","pattern":"^rev_[0-9A-Za-z]{22}$","description":"Unique identifier for the review.","example":"rev_031OeqUcl4UtGlNOdBpZCN"},"language":{"type":"string","nullable":true,"pattern":"^[a-z]{2,3}(?:-[A-Z][a-z]{3})?(?:-(?:[A-Z]{2}|[0-9]{3}))?$","description":"The language the guest wrote in, as a BCP 47 tag such as `en-US`, or null when unknown. Reviews are never translated.","example":"en-US"},"object":{"type":"string","enum":["review"],"description":"The type of object. Always `review`.","example":"review"},"pros":{"type":"string","nullable":true,"description":"What the guest liked, in plain text as the guest wrote it, or null when they wrote none.","example":"The bed was very comfortable, and the subway is a block away."},"reviewedAt":{"type":"string","format":"date-time","description":"When the guest wrote the review, in UTC.","example":"2026-10-16T00:00:00.000Z"},"reviewerCountry":{"type":"string","nullable":true,"minLength":2,"maxLength":2,"description":"Two-letter code of the country the guest comes from, or null when unknown.","example":"US"},"reviewerName":{"type":"string","nullable":true,"description":"The first name the guest gave, or null when they gave none.","example":"Jessica"},"score":{"type":"number","minimum":0,"maximum":10,"description":"The score the guest gave their stay, from 0 to 10.","example":8},"travelerType":{"type":"string","nullable":true,"enum":["business","couple","family","group","solo",null],"description":"Who the guest travelled as: alone (`solo`), as a `couple`, a `family`, a `group` of friends or more, or on `business`. Null when unknown.","example":"solo"}},"required":["comments","cons","headline","id","language","object","pros","reviewedAt","reviewerCountry","reviewerName","score","travelerType"]},"ListingSearchResult":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ListingSearchItem"},"description":"The listings on this page, best score first.","example":[{"address":"9 Rue de Lancry, 75010 Paris","amenities":["air_conditioning","free_wifi_internet"],"brand":null,"chain":null,"contactInformation":null,"countryCode":"FR","createdAt":"2026-10-01T09:00:00.000Z","description":"Twelve rooms on the Canal Saint-Martin, five minutes from République.\n\n- Breakfast in the courtyard\n- Bikes to borrow","guestRating":{"reviewCount":1284,"score":8.6},"id":"lst_031OeqUcl4UtGlNOdBpZCK","importantInformation":"Check-in from 15:00.","legalInformation":null,"location":{"lat":48.8702,"lng":2.3627},"name":"Hôtel du Canal","object":"listing","photos":[{"caption":"Courtyard","url":"https://photos.mavio.com/7b0c7ce955ae0f6f9a3d7b32b2f7be047e22a8b17a16dd19d36e2c929f6b1bf1.jpg"},{"caption":null,"url":"https://photos.mavio.com/47d68a396845b5ce9618357bc394e2606fbb18bbebba31f2e4bdd24b02a99325.jpg"}],"policies":null,"propertyType":"hotel","rooms":[{"amenities":["minibar"],"beds":[{"count":1,"type":"double_bed"}],"description":"Overlooks the canal.","id":"rm_031OeqUcl4UtGlNOdBpZCL","maxGuests":2,"name":"Double Room","object":"room","photos":[{"caption":"Double Room","url":"https://photos.mavio.com/4c11774a7d4de83dbeb8702238398c337a3d5aa4ef6f45eca27b07bbb81ed10c.jpg"}],"sizeSqm":18}],"stars":3.5,"updatedAt":"2026-10-15T14:30:00.000Z","availability":null}]},"hasMore":{"type":"boolean","description":"Whether another page follows this one.","example":true},"nextPage":{"type":"string","nullable":true,"description":"Pass it as `page` to get the next page. Null on the last page.","example":"WzM5LjgsIjAxOWEwZjNjLTdiMmUtN2M0MS05YTZkLTNmNWU4YjJjMWQ0MCJd"},"object":{"type":"string","enum":["search_result"],"description":"The type of object. Always `search_result`.","example":"search_result"}},"required":["data","hasMore","nextPage","object"]},"ListingSearchItem":{"type":"object","properties":{"address":{"type":"string","nullable":true,"description":"Street address of the listing on one line, or null when we have none.","example":"9 Rue de Lancry, 75010 Paris"},"amenities":{"type":"array","items":{"type":"string","enum":["accessible_bath_shower","accessible_by_elevator","accessible_by_lift","accessible_by_stairs_only","accessible_parking","accessible_property","accessible_rooms_available","additional_bathroom","air_conditioning","airport_transportation_available","all_inclusive","balcony_or_terrace","bar","bath","bath_or_shower","bathroom","bathtub","beach_access","beach_front","body_soap","breakfast_available","business_facilities","carbon_monoxide_detector","childcare_services","childrens_high_chair","city_view","cleaning_products","coffee_tea_maker","computer","concierge_services","conditioner","connecting_room_available","courtyard_view","cribs_or_cots_available","desk","dining_area","dining_table","dishwasher","dressing_room","dryer","electric_vehicle_charging_station","emergency_cord_in_bathroom","extra_long_bed","family_friendly","fan","fire_alarm","fire_extinguisher","fireplace","foldup_bed_available","free_airport_transportation","free_breakfast","free_laundry_services","free_parking","free_shuttle_available","free_toiletries","free_wifi_internet","front_desk_24_hour","garden","garden_view","golf_course_within_2_mi","ground_floor_unit","gym","hairdryer","heating","hot_tub_jacuzzi","housekeeping_available","internet","ironing_facilities","kettle","key_access","key_card_access","kitchen","kitchenette","kitchenware","lake_view","large_vehicle_parking","laundry_services","linens","microwave","minibar","mountain_view","no_pets_allowed","non_smoking","ocean_front","outdoor_bathroom","outdoor_cooking","outdoor_dining_area","oven","parking","patio","pets_allowed","pool","private_bathroom","private_beach_access","private_entrance","private_hot_tub_jacuzzi","private_pool_access","private_unit_in_building","refrigerator","restaurant","river_view","rollin_shower","room_service","safe","satellite_cable_channels","sauna","sea_ocean_view","self_check_in","shampoo","shared_bathroom","shared_kitchen","shared_living_spaces","shower","shuttle_available","ski_in_ski_out","smoking_allowed","sofa","sofa_bed","spa","spa_bath","stove","streaming_service","street_or_offsite_parking","telephone","tennis_court","toilet","toilet_paper","toilet_with_grab_rails","towels","towels_sheets_extra_fee","tv","view","wardrobe_or_closet","washer_dryer","washing_machine","water_view","waterfront","wheelchair_accessible","wine_glasses"]},"description":"Codes of the amenities the listing offers.","example":["air_conditioning","free_wifi_internet"]},"brand":{"type":"object","nullable":true,"properties":{"code":{"type":"string","description":"The code `chains[]` on `GET /v1/listings` takes.","example":"westin"},"name":{"type":"string","description":"The name to show, untranslated.","example":"Westin"}},"required":["code","name"],"description":"The name the listing trades under, one of its chain’s brands, or null when it has no chain or we don’t know which brand.","example":{"code":"westin","name":"Westin"}},"chain":{"type":"object","nullable":true,"properties":{"code":{"type":"string","description":"The code `chains[]` on `GET /v1/listings` takes.","example":"marriott"},"name":{"type":"string","description":"The name to show, untranslated.","example":"Marriott International"}},"required":["code","name"],"description":"The hotel company the listing belongs to, or null for an independent.","example":{"code":"marriott","name":"Marriott International"}},"contactInformation":{"type":"object","nullable":true,"properties":{"email":{"type":"string","nullable":true,"minLength":1,"description":"Public property email contact as supplied.","example":null},"fax":{"type":"string","nullable":true,"minLength":1,"description":"Public property fax number.","example":null},"phone":{"type":"string","nullable":true,"minLength":1,"description":"Public property telephone, retaining the supplier formatting.","example":null},"website":{"type":"string","nullable":true,"minLength":1,"description":"Public property website as supplied; not assumed to be a validated URL.","example":null}},"required":["email","fax","phone","website"],"additionalProperties":false,"description":"Public property contacts, or null when unknown."},"countryCode":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter code of the country the listing is in.","example":"FR"},"createdAt":{"type":"string","format":"date-time","description":"When the listing entered our catalogue, in UTC. It can be earlier than when partners could first see it.","example":"2026-10-01T09:00:00.000Z"},"description":{"type":"string","description":"Free-text description of the listing, in plain text, never HTML. Paragraphs are separated by a blank line, and each list item is a line starting with `- `.","example":"Twelve rooms on the Canal Saint-Martin, five minutes from République.\n\n- Breakfast in the courtyard\n- Bikes to borrow"},"guestRating":{"type":"object","nullable":true,"properties":{"reviewCount":{"type":"integer","minimum":1,"description":"How many guest reviews the score averages.","example":1284},"score":{"type":"number","minimum":0,"maximum":10,"description":"Average guest review score, from 0 to 10.","example":8.6}},"required":["reviewCount","score"],"description":"What guests rated their stay, or null when no reviews back a score.","example":{"reviewCount":1284,"score":8.6}},"id":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"Unique identifier for the listing.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"importantInformation":{"type":"string","nullable":true,"description":"Important property information in plain text, including conditions not captured in structured policies.","example":"Check-in from 15:00."},"legalInformation":{"type":"object","nullable":true,"properties":{"legalEntity":{"type":"string","nullable":true,"minLength":1,"description":"Registered legal entity operating the property.","example":"Hotel SAS"},"licenceNumbers":{"type":"array","items":{"type":"string","minLength":1},"description":"Property licence numbers as supplied.","example":[]},"registrationNumber":{"type":"string","nullable":true,"minLength":1,"description":"Registration number as supplied, without an assumed jurisdiction.","example":null}},"required":["legalEntity","licenceNumbers","registrationNumber"],"additionalProperties":false,"description":"Legal entity and property registration details, or null when unknown."},"location":{"$ref":"#/components/schemas/Location"},"name":{"type":"string","description":"Display name of the listing.","example":"Hôtel du Canal"},"object":{"type":"string","enum":["listing"],"description":"The type of object. Always `listing`.","example":"listing"},"photos":{"type":"array","items":{"$ref":"#/components/schemas/Photo"},"description":"Photos of the listing, in the order to show them, the first being its cover. A listing you can see always has at least one.","example":[{"caption":"Courtyard","url":"https://photos.mavio.com/7b0c7ce955ae0f6f9a3d7b32b2f7be047e22a8b17a16dd19d36e2c929f6b1bf1.jpg"},{"caption":null,"url":"https://photos.mavio.com/47d68a396845b5ce9618357bc394e2606fbb18bbebba31f2e4bdd24b02a99325.jpg"}]},"policies":{"type":"object","nullable":true,"properties":{"cancellationDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"General property text only. Rate-specific cancellation terms come from the quote.","example":null},"checkInEndTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Check-in deadline, in local HH:mm. May be after midnight.","example":"23:00"},"checkInEndTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-in deadline text when no HH:mm value can be established.","example":null},"checkInInstructions":{"type":"array","items":{"type":"string","minLength":1},"default":[],"description":"Arrival instructions in plain text.","example":["Bring photo ID."]},"checkInTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Usual check-in start, in local HH:mm without an assumed timezone.","example":"15:00"},"checkInTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-in start text when no HH:mm value can be established.","example":null},"checkOutTime":{"type":"string","nullable":true,"pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d$","default":null,"description":"Usual check-out deadline, in local HH:mm.","example":"11:00"},"checkOutTimeDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original check-out deadline text when no HH:mm value can be established.","example":null},"children":{"type":"object","nullable":true,"properties":{"allowed":{"type":"boolean","nullable":true,"default":null,"description":"Whether children are admitted; null when unstated.","example":true},"cribAvailable":{"type":"boolean","nullable":true,"default":null,"description":"Whether a crib is available; null when unstated.","example":null},"cribCharge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Crib charge, without an assumed currency or unit.","example":null},"cribMaxAge":{"type":"integer","nullable":true,"minimum":0,"default":null,"description":"Maximum age eligible for a crib; null when unstated.","example":null},"infantsAllowed":{"type":"boolean","nullable":true,"default":null,"description":"Whether infants are admitted; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Child admission and crib conditions.","example":null},"descriptions":{"type":"array","items":{"type":"object","properties":{"children":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Child admission conditions in plain text.","example":null},"description":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Policy or restriction in plain text, or null when unstated.","example":null},"name":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier name for this policy.","example":"Pets"},"parking":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Parking conditions in plain text.","example":null},"pets":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Pet conditions in plain text.","example":null},"type":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier policy category, retained as text.","example":"pets"}},"additionalProperties":false},"default":[],"description":"Supplier policy text retaining conditions not represented by structured fields.","example":[]},"groups":{"type":"object","nullable":true,"properties":{"minimumRoomCount":{"type":"integer","minimum":0,"description":"Minimum rooms for group booking conditions, not a maximum per reservation.","example":5}},"default":null,"required":["minimumRoomCount"],"additionalProperties":false,"description":"Group booking conditions.","example":null},"houseRules":{"type":"array","items":{"type":"string","minLength":1},"default":[],"description":"Property house rules in plain text.","example":[]},"minimumCheckInAge":{"type":"integer","nullable":true,"minimum":0,"default":null,"description":"Minimum age of the person checking in, not the minimum age of every guest.","example":18},"parking":{"type":"object","nullable":true,"properties":{"available":{"type":"boolean","nullable":true,"default":null,"description":"Whether any parking is available, independent of self-parking or valet availability.","example":true},"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"chargeMode":{"type":"string","nullable":true,"enum":["free","per_day","per_hour","charges_may_apply","charges_apply",null],"default":null,"description":"Distinguishes free, daily, hourly, definite and possible charges.","example":"charges_may_apply"},"evCharger":{"type":"boolean","nullable":true,"default":null,"description":"Whether electric vehicle charging is available; null when unstated.","example":null},"free":{"type":"boolean","nullable":true,"default":null,"description":"Whether parking is free; null when unstated.","example":null},"location":{"type":"string","nullable":true,"enum":["on_site","off_site",null],"default":null,"description":"Whether parking is at the property or off site.","example":"on_site"},"reservationRequired":{"type":"boolean","nullable":true,"default":null,"description":"Whether parking must be reserved; null when unstated.","example":null},"selfParking":{"type":"boolean","nullable":true,"default":null,"description":"Whether self-parking is available; null when unstated.","example":null},"valet":{"type":"boolean","nullable":true,"default":null,"description":"Whether valet parking is available; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Parking availability and charges.","example":null},"payment":{"type":"object","nullable":true,"properties":{"cardsAccepted":{"type":"boolean","nullable":true,"default":null,"description":"Whether the property accepts cards.","example":true},"cashAccepted":{"type":"boolean","nullable":true,"default":null,"description":"Whether the property accepts cash.","example":null}},"default":null,"additionalProperties":false,"description":"Property payment acceptance, independent of the booking payment method.","example":null},"pets":{"type":"object","nullable":true,"properties":{"allowed":{"type":"string","nullable":true,"enum":["allowed","not_allowed","assistive_animals_only","by_arrangement","other",null],"default":null,"description":"OpenTravel PetsAllowed concepts. Null means unstated; prose may impose additional restrictions.","example":"by_arrangement"},"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"chargeRequired":{"type":"boolean","nullable":true,"default":null,"description":"Whether a pet fee applies; null when unstated.","example":null},"description":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Policy or restriction in plain text, or null when unstated.","example":null},"maximumWeight":{"type":"object","nullable":true,"properties":{"unit":{"type":"string","enum":["lb"],"description":"Weight unit, pounds.","example":"lb"},"value":{"type":"number","minimum":0,"description":"Maximum pet weight.","example":25}},"default":null,"required":["unit","value"],"additionalProperties":false,"description":"Maximum permitted pet weight with its original unit.","example":null},"refundable":{"type":"boolean","nullable":true,"default":null,"description":"Whether the pet fee is refundable; null when unstated.","example":null}},"default":null,"additionalProperties":false,"description":"Pet admission, charges and restrictions.","example":null},"securityDeposit":{"type":"object","nullable":true,"properties":{"charge":{"type":"object","nullable":true,"properties":{"amount":{"type":"number","nullable":true,"minimum":0,"default":null,"description":"Charge amount; zero means free, null means unknown.","example":20},"currency":{"type":"string","nullable":true,"pattern":"^[A-Z]{3}$","default":null,"description":"Three-letter currency code, null when the supplier does not provide it.","example":"EUR"},"unit":{"type":"string","nullable":true,"enum":["per_stay","per_night","per_day","per_hour","per_person","per_room","per_room_per_night","per_person_per_night",null],"default":null,"description":"Unit or frequency to which the charge applies.","example":"per_stay"},"unitDescription":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Original charging basis when it has no normalized unit.","example":null}},"default":null,"additionalProperties":false,"description":"Amount and charging basis kept together from one source.","example":null},"collectedAt":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of when the security deposit is collected.","example":"checkin"},"paymentMethod":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of the security deposit payment method.","example":"credit_card"},"refundedAt":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Supplier description of when the security deposit is returned.","example":"checkout"},"required":{"type":"boolean","nullable":true,"default":null,"description":"Whether a refundable security deposit is required.","example":true}},"default":null,"additionalProperties":false,"description":"Refundable property security deposit, not booking prepayment or a cancellation penalty.","example":null},"specialCheckInInstructions":{"type":"string","nullable":true,"minLength":1,"default":null,"description":"Additional arrival instructions in plain text.","example":null}},"additionalProperties":false,"description":"OpenTravel-aligned property policies, or null when unknown. Text follows the requested language with English fallback; rate-specific terms come from the quote."},"propertyType":{"type":"string","nullable":true,"enum":["aparthotel","apartment","bed_and_breakfast","cabin","capsule_hotel","chalet","guest_house","holiday_home","homestay","hostel","hotel","resort","villa",null],"description":"Mavio property type, or null when unmapped.","example":"hotel"},"rooms":{"type":"array","items":{"$ref":"#/components/schemas/Room"},"description":"Rooms a guest can book at the listing, merged across sources.","example":[{"amenities":["minibar"],"beds":[{"count":1,"type":"double_bed"}],"description":"Overlooks the canal.","id":"rm_031OeqUcl4UtGlNOdBpZCL","maxGuests":2,"name":"Double Room","object":"room","photos":[{"caption":"Double Room","url":"https://photos.mavio.com/4c11774a7d4de83dbeb8702238398c337a3d5aa4ef6f45eca27b07bbb81ed10c.jpg"}],"sizeSqm":18}]},"stars":{"type":"number","nullable":true,"minimum":0,"maximum":5,"description":"Official star rating from 0 to 5 in half steps, or null when the listing has none.","example":3.5},"updatedAt":{"type":"string","format":"date-time","description":"When the listing last changed in a way partners can see, in UTC.","example":"2026-10-15T14:30:00.000Z"},"availability":{"type":"object","nullable":true,"properties":{"hasRefundableOffer":{"type":"boolean","nullable":true,"description":"Whether any offer for the stay can be cancelled for a refund. Null unless status is `available`.","example":true},"price":{"type":"object","nullable":true,"properties":{"base":{"type":"integer","minimum":0,"description":"The price before your markup, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":31050},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"The currency of every amount but dueAtProperty.","example":"EUR"},"dueAtProperty":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"description":"What the guest pays at the property, in its own currency's minor units.","example":600},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"The currency the property charges it in.","example":"EUR"},"description":{"type":"string","nullable":true,"description":"What it is for, or null.","example":"Resort fee"}},"required":["amount","currency","description"],"additionalProperties":false},"description":"Fees the guest pays at the property, left out of total.","example":[{"amount":600,"currency":"EUR","description":"Resort fee"}]},"lines":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"description":"The line's amount, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":31700},"description":{"type":"string","nullable":true,"description":"The supplier's name for a tax or fee, or null.","example":"TAX"},"type":{"type":"string","enum":["room","tax_and_fee"],"description":"`room` for the stay itself, `tax_and_fee` for a tax or fee included in the total.","example":"room"}},"required":["amount","description","type"],"additionalProperties":false},"description":"What total is made of. The lines add up to it.","example":[{"amount":31700,"description":null,"type":"room"},{"amount":2700,"description":"TAX","type":"tax_and_fee"}]},"markup":{"type":"integer","minimum":0,"description":"Your markup, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":3350},"total":{"type":"integer","minimum":0,"description":"What the guest pays: base plus markup, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":34400}},"required":["base","currency","dueAtProperty","lines","markup","total"],"additionalProperties":false,"description":"The cheapest offer's price, which a quote for the same stay prices alike. Null unless status is `available`."},"status":{"type":"string","enum":["available","sold_out","unavailable"],"description":"`available` when the listing sells the stay, `sold_out` when it has nothing left to sell for it, `unavailable` when no supplier answered in time: search again later.","example":"available"}},"required":["hasRefundableOffer","price","status"],"description":"Whether the listing sells the stay you sent and from what price, or null when you sent no stay."}},"required":["address","amenities","brand","chain","contactInformation","countryCode","createdAt","description","guestRating","id","importantInformation","legalInformation","location","name","object","photos","policies","propertyType","rooms","stars","updatedAt","availability"]},"Quote":{"type":"object","properties":{"checkIn":{"type":"string","format":"date","description":"The first night of the stay.","example":"2026-12-04"},"checkOut":{"type":"string","format":"date","description":"The day the guests leave.","example":"2026-12-06"},"createdAt":{"type":"string","format":"date-time","description":"When the quote was created, in UTC.","example":"2026-11-20T09:30:00.000Z"},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"The currency the offers are priced in.","example":"EUR"},"expiresAt":{"type":"string","format":"date-time","description":"When the offers stop being bookable, in UTC. Read it on every quote: never assume a fixed lifetime.","example":"2026-11-20T09:45:00.000Z"},"guestNationality":{"type":"string","minLength":2,"maxLength":2,"description":"The lead guest's nationality.","example":"FR"},"id":{"type":"string","pattern":"^qt_[0-9A-Za-z]{22}$","description":"Unique identifier for the quote.","example":"qt_031OeqUcl4UtGlNOdBpZCM"},"listingId":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The listing priced.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"metadata":{"type":"object","additionalProperties":{"type":"string"},"description":"The metadata you sent.","example":{"order":"ord_1234"}},"mode":{"type":"string","enum":["test","live"],"description":"Whether a test or a live key created it.","example":"test"},"object":{"type":"string","enum":["quote"],"description":"The type of object. Always `quote`.","example":"quote"},"offers":{"type":"array","items":{"$ref":"#/components/schemas/Offer"},"description":"Every bookable choice for the stay, cheapest first: the cheapest for each set of rooms, board and cancellation terms. Empty when sold out.","example":[{"board":"breakfast","cancellationPolicy":{"cancellableUntil":"2026-12-03T23:00:00.000Z","freeCancellationUntil":"2026-12-01T23:59:00.000Z","penalties":[{"amount":34400,"from":"2026-12-01T23:59:00.000Z"}],"refundable":true},"id":"off_031OeqUcl4UtGlNOdBpZCN","object":"offer","price":{"base":31050,"currency":"EUR","dueAtProperty":[{"amount":600,"currency":"EUR","description":"Resort fee"}],"lines":[{"amount":31700,"description":null,"type":"room"},{"amount":2700,"description":"TAX","type":"tax_and_fee"}],"markup":3350,"total":34400},"rooms":[{"roomId":"rm_031OeqUcl4UtGlNOdBpZCL"}]}]},"pricing":{"type":"object","properties":{"markupPercent":{"type":"number","description":"The markup applied, as a percent of the supplier price.","example":12.5},"source":{"type":"string","enum":["default","request","listing","chain"],"description":"The applied layer, in precedence order: request override, listing rule, chain rule, partner default. Rules apply across suppliers.","example":"request"}},"required":["markupPercent","source"],"additionalProperties":false,"description":"Which markup the offers carry."},"rooms":{"type":"array","items":{"type":"object","properties":{"adults":{"type":"integer","minimum":1,"maximum":8,"description":"How many adults sleep in the room, from 1 to 8.","example":2},"childAges":{"type":"array","items":{"type":"integer","minimum":0,"maximum":17},"maxItems":4,"description":"The age of each child in the room, from 0 to 17, up to 4 children.","example":[7]}},"required":["adults","childAges"],"additionalProperties":false},"description":"Who sleeps in each room, as you sent it.","example":[{"adults":2,"childAges":[7]}]}},"required":["checkIn","checkOut","createdAt","currency","expiresAt","guestNationality","id","listingId","metadata","mode","object","offers","pricing","rooms"],"additionalProperties":false,"description":"One listing priced for one stay, holding its offers until it expires."},"Offer":{"type":"object","properties":{"board":{"type":"string","enum":["room_only","breakfast","half_board","full_board","all_inclusive"],"description":"The meals included.","example":"breakfast"},"cancellationPolicy":{"$ref":"#/components/schemas/CancellationPolicy"},"id":{"type":"string","pattern":"^off_[0-9A-Za-z]{22}$","description":"Unique identifier for the offer.","example":"off_031OeqUcl4UtGlNOdBpZCN"},"object":{"type":"string","enum":["offer"],"description":"The type of object. Always `offer`.","example":"offer"},"price":{"$ref":"#/components/schemas/Price"},"rooms":{"type":"array","items":{"type":"object","properties":{"roomId":{"type":"string","pattern":"^rm_[0-9A-Za-z]{22}$","description":"The listing's room.","example":"rm_031OeqUcl4UtGlNOdBpZCL"}},"required":["roomId"],"additionalProperties":false},"description":"One room per room you asked for, in the same order. They can be of different types.","example":[{"roomId":"rm_031OeqUcl4UtGlNOdBpZCL"}]}},"required":["board","cancellationPolicy","id","object","price","rooms"],"additionalProperties":false},"CancellationPolicy":{"type":"object","properties":{"cancellableUntil":{"type":"string","format":"date-time","description":"The cut-off for cancelling, in UTC: the start of check-in day in the listing's time zone for a refundable offer, or the quote's createdAt for a non-refundable offer. A booking keeps its offer's cut-off. This is separate from when cancelling starts to cost.","example":"2026-12-03T23:00:00.000Z"},"freeCancellationUntil":{"type":"string","nullable":true,"format":"date-time","description":"Until when cancelling is free, in UTC: the start of the first penalty, or null when cancelling is always free.","example":"2026-12-01T23:59:00.000Z"},"penalties":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"description":"What cancelling costs from `from`, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":34400},"from":{"type":"string","format":"date-time","description":"When this penalty starts, in UTC.","example":"2026-12-01T23:59:00.000Z"}},"required":["amount","from"],"additionalProperties":false},"description":"What cancelling costs, earliest first. A non-refundable offer has one penalty of the whole total from when it was quoted.","example":[{"amount":34400,"from":"2026-12-01T23:59:00.000Z"}]},"refundable":{"type":"boolean","description":"Whether the stay can be cancelled for any refund.","example":true}},"required":["cancellableUntil","freeCancellationUntil","penalties","refundable"],"additionalProperties":false,"description":"Until when the stay can be cancelled, what cancelling costs, and until when it is free."},"Price":{"type":"object","properties":{"base":{"type":"integer","minimum":0,"description":"The price before your markup, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":31050},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"The currency of every amount but dueAtProperty.","example":"EUR"},"dueAtProperty":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"description":"What the guest pays at the property, in its own currency's minor units.","example":600},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"The currency the property charges it in.","example":"EUR"},"description":{"type":"string","nullable":true,"description":"What it is for, or null.","example":"Resort fee"}},"required":["amount","currency","description"],"additionalProperties":false},"description":"Fees the guest pays at the property, left out of total.","example":[{"amount":600,"currency":"EUR","description":"Resort fee"}]},"lines":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"description":"The line's amount, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":31700},"description":{"type":"string","nullable":true,"description":"The supplier's name for a tax or fee, or null.","example":"TAX"},"type":{"type":"string","enum":["room","tax_and_fee"],"description":"`room` for the stay itself, `tax_and_fee` for a tax or fee included in the total.","example":"room"}},"required":["amount","description","type"],"additionalProperties":false},"description":"What total is made of. The lines add up to it.","example":[{"amount":31700,"description":null,"type":"room"},{"amount":2700,"description":"TAX","type":"tax_and_fee"}]},"markup":{"type":"integer","minimum":0,"description":"Your markup, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":3350},"total":{"type":"integer","minimum":0,"description":"What the guest pays: base plus markup, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":34400}},"required":["base","currency","dueAtProperty","lines","markup","total"],"additionalProperties":false,"description":"What the stay costs, and what of it is your markup."},"QuoteRequest":{"type":"object","properties":{"checkIn":{"type":"string","format":"date","description":"The first night of the stay, as YYYY-MM-DD.","example":"2026-12-04"},"checkOut":{"type":"string","format":"date","description":"The day the guests leave, as YYYY-MM-DD: 1 to 30 nights after checkIn.","example":"2026-12-06"},"currency":{"type":"string","pattern":"^[A-Z]{3}$","description":"The currency to price in, as an ISO 4217 code. Any other answers `currency_not_supported`.","enum":["AED","AUD","BDT","BHD","BRL","CAD","CHF","CNY","COP","CZK","DKK","EGP","EUR","FJD","GBP","HKD","HUF","IDR","ILS","INR","JOD","JPY","KHR","KRW","KWD","KZT","LAK","LKR","MVR","MXN","MYR","NGN","NOK","NZD","OMR","PHP","PKR","PLN","QAR","RON","RUB","SAR","SEK","SGD","THB","TRY","TWD","UAH","USD","VND","XPF","ZAR"],"example":"EUR"},"guestNationality":{"type":"string","pattern":"^[A-Z]{2}$","description":"The lead guest's nationality, as an ISO 3166-1 alpha-2 code. Suppliers price for it.","example":"FR"},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"default":{},"description":"Your own key-value pairs, returned with the quote: up to 50 keys of up to 40 characters, with values of up to 500. Never put sensitive data in it, such as a guest's name, email or card.","example":{"order":"ord_1234"}},"pricing":{"type":"object","properties":{"markupPercent":{"type":"number","minimum":0,"maximum":100,"description":"Your markup on this quote, as a percent of the supplier price from 0 to 100 with at most 2 decimals.","example":12.5}},"required":["markupPercent"],"additionalProperties":false,"description":"Overrides listing rules, chain rules and your default markup for this quote."},"rooms":{"type":"array","items":{"type":"object","properties":{"adults":{"type":"integer","minimum":1,"maximum":8,"description":"How many adults sleep in the room, from 1 to 8.","example":2},"childAges":{"type":"array","items":{"type":"integer","minimum":0,"maximum":17},"maxItems":4,"default":[],"description":"The age of each child in the room, from 0 to 17, up to 4 children. Leave it out for none.","example":[7]}},"required":["adults"],"additionalProperties":false},"minItems":1,"maxItems":8,"description":"Who sleeps in each room, from 1 to 8 rooms.","example":[{"adults":2,"childAges":[7]}]},"listingId":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The listing to price. It has to be active.","example":"lst_031OeqUcl4UtGlNOdBpZCK"}},"required":["checkIn","checkOut","currency","guestNationality","rooms","listingId"],"additionalProperties":false},"Payment":{"type":"object","properties":{"adyen":{"$ref":"#/components/schemas/PaymentAdyenSession"},"amount":{"type":"integer","minimum":0,"description":"What the shopper's card is held for, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":34400},"createdAt":{"type":"string","format":"date-time","description":"When the payment was created, in UTC.","example":"2026-11-20T09:31:00.000Z"},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"The currency of the amount.","example":"EUR"},"expiresAt":{"type":"string","format":"date-time","description":"Until when the shopper can pay and you can book with it, in UTC. Adyen ends the session at the same moment. A payment no booking took by then is `canceled`, and its hold released.","example":"2026-11-20T09:46:00.000Z"},"id":{"type":"string","pattern":"^pay_[0-9A-Za-z]{22}$","description":"Unique identifier for the payment.","example":"pay_031OeqUcl4UtGlNOdBpZCP"},"mode":{"type":"string","enum":["test","live"],"description":"Whether a test or a live key created it.","example":"test"},"object":{"type":"string","enum":["payment"],"description":"The type of object. Always `payment`.","example":"payment"},"offerId":{"type":"string","pattern":"^off_[0-9A-Za-z]{22}$","description":"The offer the shopper pays for.","example":"off_031OeqUcl4UtGlNOdBpZCN"},"quoteId":{"type":"string","pattern":"^qt_[0-9A-Za-z]{22}$","description":"The offer's quote.","example":"qt_031OeqUcl4UtGlNOdBpZCM"},"shopper":{"$ref":"#/components/schemas/PaymentShopper"},"status":{"type":"string","enum":["pending","authorized","captured","capture_failed","canceled"],"description":"`pending` until the shopper's card is held, `authorized` once it is, `captured` once the booking is confirmed, and `canceled` once nobody can book with it, when it expired unbooked or its booking failed, as its hold is released. `capture_failed` means Adyen could not capture the hold; a later recapture restores `captured`. A refused card leaves it `pending`, so the shopper can try another.","example":"pending"}},"required":["adyen","amount","createdAt","currency","expiresAt","id","mode","object","offerId","quoteId","shopper","status"],"additionalProperties":false},"PaymentAdyenSession":{"type":"object","properties":{"clientKey":{"type":"string","description":"The client key Adyen's component is created with.","example":"test_EXAMPLECLIENTKEYFORADYENCOMPONENT"},"environment":{"type":"string","description":"The Adyen environment the component connects to: `test` for a test key.","example":"test"},"sessionData":{"type":"string","description":"The session's data, which the component takes beside its id.","example":"Ab02b4c0!BQABAgCW5sxB4e/=="},"sessionId":{"type":"string","description":"The Adyen session's id.","example":"CS451F2AB1ED897A94"}},"required":["clientKey","environment","sessionData","sessionId"],"additionalProperties":false,"description":"What Adyen's Drop-in or Card Component needs to take the shopper's card."},"PaymentShopper":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"The shopper's email, which Adyen checks the card against for 3DS.","example":"ana.martin@example.com"},"id":{"type":"string","minLength":1,"maxLength":200,"description":"Your own id for the shopper.","example":"cus_8812"},"ipAddress":{"anyOf":[{"type":"string","format":"ip"},{"type":"string","format":"ip"}],"description":"The shopper's IP address as your servers saw it, IPv4 or IPv6, which Adyen checks the card against for 3DS.","example":"203.0.113.7"}},"required":["email","id","ipAddress"],"additionalProperties":false,"description":"The person paying, as your platform knows them."},"PaymentConflict":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["api_key_expired","api_key_invalid","api_key_limit_reached","api_key_missing","api_key_revoked","body_too_large","booking_already_cancelled","booking_not_at_supplier","booking_status_unexpected","cancellation_deadline_passed","cancellation_in_progress","currency_not_supported","idempotency_key_in_use","idempotency_key_reused","internal_error","invalid_request","offer_changed","offer_unavailable","payment_not_found","payment_status_unexpected","payment_unavailable","permission_denied","quote_expired","rate_limited","refund_status_unexpected","resource_missing","route_not_found","supplier_unavailable","test_origin_exists","test_origin_limit_reached","unsupported_media_type","usage_unavailable"],"description":"Stable error code. Branch on this, not on `message`. See [error codes](https://docs.mavio.com/errors) for what each means and what to do.\n\n- [`api_key_expired`](https://docs.mavio.com/errors/api_key_expired)\n- [`api_key_invalid`](https://docs.mavio.com/errors/api_key_invalid)\n- [`api_key_limit_reached`](https://docs.mavio.com/errors/api_key_limit_reached)\n- [`api_key_missing`](https://docs.mavio.com/errors/api_key_missing)\n- [`api_key_revoked`](https://docs.mavio.com/errors/api_key_revoked)\n- [`body_too_large`](https://docs.mavio.com/errors/body_too_large)\n- [`booking_already_cancelled`](https://docs.mavio.com/errors/booking_already_cancelled)\n- [`booking_not_at_supplier`](https://docs.mavio.com/errors/booking_not_at_supplier)\n- [`booking_status_unexpected`](https://docs.mavio.com/errors/booking_status_unexpected)\n- [`cancellation_deadline_passed`](https://docs.mavio.com/errors/cancellation_deadline_passed)\n- [`cancellation_in_progress`](https://docs.mavio.com/errors/cancellation_in_progress)\n- [`currency_not_supported`](https://docs.mavio.com/errors/currency_not_supported)\n- [`idempotency_key_in_use`](https://docs.mavio.com/errors/idempotency_key_in_use)\n- [`idempotency_key_reused`](https://docs.mavio.com/errors/idempotency_key_reused)\n- [`internal_error`](https://docs.mavio.com/errors/internal_error)\n- [`invalid_request`](https://docs.mavio.com/errors/invalid_request)\n- [`offer_changed`](https://docs.mavio.com/errors/offer_changed)\n- [`offer_unavailable`](https://docs.mavio.com/errors/offer_unavailable)\n- [`payment_not_found`](https://docs.mavio.com/errors/payment_not_found)\n- [`payment_status_unexpected`](https://docs.mavio.com/errors/payment_status_unexpected)\n- [`payment_unavailable`](https://docs.mavio.com/errors/payment_unavailable)\n- [`permission_denied`](https://docs.mavio.com/errors/permission_denied)\n- [`quote_expired`](https://docs.mavio.com/errors/quote_expired)\n- [`rate_limited`](https://docs.mavio.com/errors/rate_limited)\n- [`refund_status_unexpected`](https://docs.mavio.com/errors/refund_status_unexpected)\n- [`resource_missing`](https://docs.mavio.com/errors/resource_missing)\n- [`route_not_found`](https://docs.mavio.com/errors/route_not_found)\n- [`supplier_unavailable`](https://docs.mavio.com/errors/supplier_unavailable)\n- [`test_origin_exists`](https://docs.mavio.com/errors/test_origin_exists)\n- [`test_origin_limit_reached`](https://docs.mavio.com/errors/test_origin_limit_reached)\n- [`unsupported_media_type`](https://docs.mavio.com/errors/unsupported_media_type)\n- [`usage_unavailable`](https://docs.mavio.com/errors/usage_unavailable)","example":"invalid_request"},"message":{"type":"string","description":"Human-readable explanation. Its wording can change.","example":"Invalid request"},"param":{"type":"string","description":"The request parameter the error is about, when there is one.","example":"id"},"quote":{"$ref":"#/components/schemas/Quote"}},"required":["code","message"],"description":"What went wrong."}}}]},"PaymentRequest":{"type":"object","properties":{"offerId":{"type":"string","pattern":"^off_[0-9A-Za-z]{22}$","description":"The offer the shopper pays for. Its quote has to be open.","example":"off_031OeqUcl4UtGlNOdBpZCN"},"returnUrl":{"type":"string","maxLength":1024,"format":"uri","description":"Where Adyen sends the shopper back after a redirect, such as a bank's 3DS page: your checkout page on the web, or your app's own URL.","example":"https://acme.travel/checkout/return"},"shopper":{"$ref":"#/components/schemas/PaymentShopper"}},"required":["offerId","returnUrl","shopper"],"additionalProperties":false},"Booking":{"type":"object","properties":{"board":{"type":"string","enum":["room_only","breakfast","half_board","full_board","all_inclusive"],"description":"The meals included.","example":"breakfast"},"cancellation":{"type":"object","nullable":true,"properties":{"cancelledAt":{"type":"string","nullable":true,"format":"date-time","description":"When the booking was cancelled, in UTC, or null while cancelling.","example":"2026-11-22T14:05:00.000Z"},"cancelledBy":{"type":"string","enum":["partner","supplier","mavio"],"description":"Who asked for the cancellation: `partner` (you), `supplier` (the hotel or its supplier) or `mavio`. More can be added, so handle one you don't know.","example":"supplier"},"penalty":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"description":"The amount kept from the booking total, in minor units of its currency.","example":17200},"markup":{"type":"integer","minimum":0,"description":"Your share of the penalty, in minor units of the booking currency.","example":1675}},"required":["amount","markup"],"additionalProperties":false,"description":"The frozen cancellation penalty and your share of it."},"refund":{"type":"object","nullable":true,"properties":{"amount":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The amount returned to the shopper, in minor units of the booking currency.","example":17200},"failureReason":{"type":"string","nullable":true,"enum":["card_unavailable","refund_window_expired","disputed","not_charged",null],"description":"Why the refund needs action or ended unsuccessfully, or null. This is an open list: handle unknown reasons.","example":null},"status":{"type":"string","enum":["pending","succeeded","requires_action","failed","canceled"],"description":"Where the refund stands. This is an open list: treat an unknown status as pending.","example":"pending"}},"required":["amount","failureReason","status"],"additionalProperties":false,"description":"What comes back to the shopper and where it stands, or null when nothing comes back."}},"required":["cancelledAt","cancelledBy","penalty","refund"],"additionalProperties":false,"description":"The cancellation and frozen figures, or null unless status is `cancelling` or `cancelled`."},"cancellationPolicy":{"$ref":"#/components/schemas/CancellationPolicy"},"checkIn":{"type":"string","format":"date","description":"The first night of the stay.","example":"2026-12-04"},"checkOut":{"type":"string","format":"date","description":"The day the guests leave.","example":"2026-12-06"},"confirmedAt":{"type":"string","nullable":true,"format":"date-time","description":"When the booking was confirmed, in UTC, or null until it is. A cancelled booking keeps it.","example":"2026-11-20T09:31:15.000Z"},"createdAt":{"type":"string","format":"date-time","description":"When the booking was created, in UTC.","example":"2026-11-20T09:31:12.000Z"},"failure":{"type":"object","nullable":true,"properties":{"code":{"type":"string","description":"Stable code for why the booking failed. Branch on this, not on `message`. This is an open list: more codes can be added, so treat a code you don't know as `internal_error`. See [booking failure codes](https://docs.mavio.com/errors#booking-failures).\n\n- [`confirmation_timeout`](https://docs.mavio.com/booking-failures/confirmation_timeout)\n- [`internal_error`](https://docs.mavio.com/booking-failures/internal_error)\n- [`offer_changed`](https://docs.mavio.com/booking-failures/offer_changed)\n- [`offer_unavailable`](https://docs.mavio.com/booking-failures/offer_unavailable)\n- [`payment_declined`](https://docs.mavio.com/booking-failures/payment_declined)\n- [`supplier_refused`](https://docs.mavio.com/booking-failures/supplier_refused)","example":"supplier_refused"},"failedAt":{"type":"string","format":"date-time","description":"When the booking failed, in UTC.","example":"2026-11-20T09:31:15.000Z"},"message":{"type":"string","description":"Human-readable explanation. Its wording can change.","example":"The hotel refused the booking."}},"required":["code","failedAt","message"],"additionalProperties":false,"description":"Why the booking failed, or null unless status is `failed`."},"guestNationality":{"type":"string","minLength":2,"maxLength":2,"description":"The lead guest's nationality.","example":"FR"},"holder":{"$ref":"#/components/schemas/BookingHolder"},"id":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"Unique identifier for the booking.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"listing":{"$ref":"#/components/schemas/BookingListing"},"metadata":{"type":"object","additionalProperties":{"type":"string"},"description":"The metadata you set on the booking.","example":{"order":"ord_1234"}},"mode":{"type":"string","enum":["test","live"],"description":"Whether a test or a live key created it.","example":"test"},"object":{"type":"string","enum":["booking"],"description":"The type of object. Always `booking`.","example":"booking"},"offerId":{"type":"string","pattern":"^off_[0-9A-Za-z]{22}$","description":"The offer booked.","example":"off_031OeqUcl4UtGlNOdBpZCN"},"paymentId":{"type":"string","pattern":"^pay_[0-9A-Za-z]{22}$","description":"The payment the booking took.","example":"pay_031OeqUcl4UtGlNOdBpZCP"},"price":{"$ref":"#/components/schemas/Price"},"pricing":{"type":"object","properties":{"markupPercent":{"type":"number","description":"The markup applied, as a percent of the supplier price.","example":12.5},"source":{"type":"string","enum":["default","request","listing","chain"],"description":"The applied layer, in precedence order: request override, listing rule, chain rule, partner default. Rules apply across suppliers.","example":"request"}},"required":["markupPercent","source"],"additionalProperties":false,"description":"Which markup the price carries."},"quoteId":{"type":"string","pattern":"^qt_[0-9A-Za-z]{22}$","description":"The quote the offer came from.","example":"qt_031OeqUcl4UtGlNOdBpZCM"},"reference":{"type":"string","nullable":true,"description":"Your own reference for the booking, or null when you set none.","example":"ord_1234"},"rooms":{"type":"array","items":{"$ref":"#/components/schemas/BookingRoom"},"description":"Each room booked, in the order of the quote.","example":[{"adults":2,"childAges":[7],"guest":{"email":"ana.martin@example.com","firstName":"Ana","lastName":"Martin"},"hotelConfirmationCode":"HX-48213","name":"Double Room","roomId":"rm_031OeqUcl4UtGlNOdBpZCL"}]},"specialRequests":{"type":"string","nullable":true,"description":"What you asked the hotel for, or null when you asked nothing. It's passed on, but the hotel needn't honour it.","example":"A quiet room on a high floor, please."},"status":{"type":"string","enum":["processing","confirmed","failed","cancelling","cancelled"],"description":"`processing` until the booking is confirmed or fails, then `confirmed` or `failed`, `cancelling` once a cancel is accepted, and `cancelled` once cancelled. This is an open list: more statuses can be added, so handle one you don't know.","example":"confirmed"},"updatedAt":{"type":"string","format":"date-time","description":"When the booking last changed, in UTC.","example":"2026-11-20T09:31:15.000Z"}},"required":["board","cancellation","cancellationPolicy","checkIn","checkOut","confirmedAt","createdAt","failure","guestNationality","holder","id","listing","metadata","mode","object","offerId","paymentId","price","pricing","quoteId","reference","rooms","specialRequests","status","updatedAt"],"additionalProperties":false,"description":"The public booking snapshot.","example":{"board":"breakfast","cancellation":null,"cancellationPolicy":{"cancellableUntil":"2026-12-03T23:00:00.000Z","freeCancellationUntil":"2026-12-01T23:59:00.000Z","penalties":[{"amount":34400,"from":"2026-12-01T23:59:00.000Z"}],"refundable":true},"checkIn":"2026-12-04","checkOut":"2026-12-06","confirmedAt":"2026-11-20T09:31:15.000Z","createdAt":"2026-11-20T09:31:12.000Z","failure":null,"guestNationality":"FR","holder":{"email":"ana.martin@example.com","firstName":"Ana","lastName":"Martin","phone":"+33612345678"},"id":"bk_031OeqUcl4UtGlNOdBpZCN","listing":{"address":"9 Rue de Lancry, 75010 Paris","contactInformation":null,"countryCode":"FR","id":"lst_031OeqUcl4UtGlNOdBpZCK","location":{"lat":48.8702,"lng":2.3627},"name":"Hôtel du Canal"},"metadata":{"order":"ord_1234"},"mode":"test","object":"booking","offerId":"off_031OeqUcl4UtGlNOdBpZCN","paymentId":"pay_031OeqUcl4UtGlNOdBpZCP","price":{"base":31050,"currency":"EUR","dueAtProperty":[{"amount":600,"currency":"EUR","description":"Resort fee"}],"lines":[{"amount":31700,"description":null,"type":"room"},{"amount":2700,"description":"TAX","type":"tax_and_fee"}],"markup":3350,"total":34400},"pricing":{"markupPercent":12.5,"source":"request"},"quoteId":"qt_031OeqUcl4UtGlNOdBpZCM","reference":"ord_1234","rooms":[{"adults":2,"childAges":[7],"guest":{"email":"ana.martin@example.com","firstName":"Ana","lastName":"Martin"},"hotelConfirmationCode":"HX-48213","name":"Double Room","roomId":"rm_031OeqUcl4UtGlNOdBpZCL"}],"specialRequests":"A quiet room on a high floor, please.","status":"confirmed","updatedAt":"2026-11-20T09:31:15.000Z"}},"BookingHolder":{"type":"object","properties":{"email":{"type":"string","description":"Email address.","example":"ana.martin@example.com"},"firstName":{"type":"string","description":"First name.","example":"Ana"},"lastName":{"type":"string","description":"Last name.","example":"Martin"},"phone":{"type":"string","description":"Phone number, in E.164.","example":"+33612345678"}},"required":["email","firstName","lastName","phone"],"additionalProperties":false,"description":"Who the booking is in the name of."},"BookingListing":{"type":"object","properties":{"address":{"type":"string","nullable":true,"description":"Street address on one line, or null when we had none.","example":"9 Rue de Lancry, 75010 Paris"},"contactInformation":{"type":"object","nullable":true,"properties":{"email":{"type":"string","nullable":true,"minLength":1,"description":"Public property email contact as supplied.","example":null},"fax":{"type":"string","nullable":true,"minLength":1,"description":"Public property fax number.","example":null},"phone":{"type":"string","nullable":true,"minLength":1,"description":"Public property telephone, retaining the supplier formatting.","example":null},"website":{"type":"string","nullable":true,"minLength":1,"description":"Public property website as supplied; not assumed to be a validated URL.","example":null}},"required":["email","fax","phone","website"],"additionalProperties":false,"description":"Public property contacts, or null when unknown."},"countryCode":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter code of the country the listing is in.","example":"FR"},"id":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The listing booked.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"location":{"$ref":"#/components/schemas/Location"},"name":{"type":"string","description":"Display name of the listing.","example":"Hôtel du Canal"}},"required":["address","contactInformation","countryCode","id","location","name"],"additionalProperties":false,"description":"The listing as it was when booked. It stays the same when the listing changes or stops being active, so it's enough for a voucher."},"BookingRoom":{"type":"object","properties":{"adults":{"type":"integer","minimum":1,"maximum":8,"description":"How many adults sleep in the room, from 1 to 8.","example":2},"childAges":{"type":"array","items":{"type":"integer","minimum":0,"maximum":17},"maxItems":4,"description":"The age of each child in the room, from 0 to 17, up to 4 children.","example":[7]},"guest":{"type":"object","properties":{"email":{"type":"string","nullable":true,"description":"Email address, or null when you sent none.","example":"ana.martin@example.com"},"firstName":{"type":"string","description":"First name.","example":"Ana"},"lastName":{"type":"string","description":"Last name.","example":"Martin"}},"required":["email","firstName","lastName"],"additionalProperties":false,"description":"The guest the room is booked for."},"hotelConfirmationCode":{"type":"string","nullable":true,"description":"The code the guest gives at check-in, or null until the hotel sends it.","example":"HX-48213"},"name":{"type":"string","description":"The room's name when it was booked.","example":"Double Room"},"roomId":{"type":"string","pattern":"^rm_[0-9A-Za-z]{22}$","description":"The listing's room.","example":"rm_031OeqUcl4UtGlNOdBpZCL"}},"required":["adults","childAges","guest","hotelConfirmationCode","name","roomId"],"additionalProperties":false},"BookingRequest":{"type":"object","properties":{"adyen":{"type":"object","properties":{"sessionResult":{"type":"string","minLength":1,"maxLength":5000,"description":"The `sessionResult` Adyen's component gave you once the shopper paid, which lets Mavio confirm the payment at once.","example":"X3XtfGC9!H4sIAAAAAAAA"}},"required":["sessionResult"],"additionalProperties":false,"description":"What Adyen's component told you. Leave it out when you don't have it: Mavio then waits for Adyen to tell it."},"holder":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"The holder's email.","example":"ana.martin@example.com"},"firstName":{"type":"string","minLength":1,"maxLength":50,"description":"The holder's first name, as it should be booked: 1 to 50 characters. Must start with a Latin letter and hold only Latin letters, accented or not, spaces, '-' and \"'\".","example":"Ana"},"lastName":{"type":"string","minLength":1,"maxLength":50,"description":"The holder's last name, as it should be booked: 1 to 50 characters. Must start with a Latin letter and hold only Latin letters, accented or not, spaces, '-' and \"'\".","example":"Martin"},"phone":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"The holder's phone number in E.164: a +, the country code and the number.","example":"+33612345678"}},"required":["email","firstName","lastName","phone"],"additionalProperties":false,"description":"Who the booking is in the name of, whom the hotel contacts."},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500},"default":{},"description":"Your own key-value pairs, returned with the booking: up to 50 keys of up to 40 characters, with values of up to 500. Never copied from the quote. Never put sensitive data in it, such as a guest's name, email or card.","example":{"order":"ord_1234"}},"paymentId":{"type":"string","pattern":"^pay_[0-9A-Za-z]{22}$","description":"The payment the shopper made for the offer. A payment books once.","example":"pay_031OeqUcl4UtGlNOdBpZCP"},"reference":{"type":"string","minLength":1,"maxLength":200,"description":"Your own reference for the booking, such as your order's id: up to 200 characters, and needn't be unique.","example":"ord_1234"},"rooms":{"type":"array","items":{"type":"object","properties":{"guest":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"The guest's email. Leave it out for none: a supplier that needs one gets the holder's.","example":"ana.martin@example.com"},"firstName":{"type":"string","minLength":1,"maxLength":50,"description":"The guest's first name, as it should be booked: 1 to 50 characters. Must start with a Latin letter and hold only Latin letters, accented or not, spaces, '-' and \"'\".","example":"Ana"},"lastName":{"type":"string","minLength":1,"maxLength":50,"description":"The guest's last name, as it should be booked: 1 to 50 characters. Must start with a Latin letter and hold only Latin letters, accented or not, spaces, '-' and \"'\".","example":"Martin"}},"required":["firstName","lastName"],"additionalProperties":false,"description":"Who the room is booked for."}},"required":["guest"],"additionalProperties":false},"minItems":1,"maxItems":8,"description":"One guest per room of the payment's quote, in the quote's order.","example":[{"guest":{"firstName":"Ana","lastName":"Martin"}}]},"specialRequests":{"type":"string","minLength":1,"maxLength":1000,"description":"What to ask the hotel for, up to 1000 characters. It's passed on, but the hotel needn't honour it.","example":"A quiet room on a high floor, please."}},"required":["holder","paymentId","rooms"],"additionalProperties":false},"BookingList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Booking"},"description":"Your bookings in this mode, newest first.","example":[{"board":"breakfast","cancellation":null,"cancellationPolicy":{"cancellableUntil":"2026-12-03T23:00:00.000Z","freeCancellationUntil":"2026-12-01T23:59:00.000Z","penalties":[{"amount":34400,"from":"2026-12-01T23:59:00.000Z"}],"refundable":true},"checkIn":"2026-12-04","checkOut":"2026-12-06","confirmedAt":"2026-11-20T09:31:15.000Z","createdAt":"2026-11-20T09:31:12.000Z","failure":null,"guestNationality":"FR","holder":{"email":"ana.martin@example.com","firstName":"Ana","lastName":"Martin","phone":"+33612345678"},"id":"bk_031OeqUcl4UtGlNOdBpZCN","listing":{"address":"9 Rue de Lancry, 75010 Paris","contactInformation":null,"countryCode":"FR","id":"lst_031OeqUcl4UtGlNOdBpZCK","location":{"lat":48.8702,"lng":2.3627},"name":"Hôtel du Canal"},"metadata":{"order":"ord_1234"},"mode":"test","object":"booking","offerId":"off_031OeqUcl4UtGlNOdBpZCN","paymentId":"pay_031OeqUcl4UtGlNOdBpZCP","price":{"base":31050,"currency":"EUR","dueAtProperty":[{"amount":600,"currency":"EUR","description":"Resort fee"}],"lines":[{"amount":31700,"description":null,"type":"room"},{"amount":2700,"description":"TAX","type":"tax_and_fee"}],"markup":3350,"total":34400},"pricing":{"markupPercent":12.5,"source":"request"},"quoteId":"qt_031OeqUcl4UtGlNOdBpZCM","reference":"ord_1234","rooms":[{"adults":2,"childAges":[7],"guest":{"email":"ana.martin@example.com","firstName":"Ana","lastName":"Martin"},"hotelConfirmationCode":"HX-48213","name":"Double Room","roomId":"rm_031OeqUcl4UtGlNOdBpZCL"}],"specialRequests":"A quiet room on a high floor, please.","status":"confirmed","updatedAt":"2026-11-20T09:31:15.000Z"}]},"hasMore":{"type":"boolean","description":"Whether more bookings follow in the direction you paged.","example":false},"object":{"type":"string","enum":["list"],"description":"Always `list`.","example":"list"}},"required":["data","hasMore","object"],"additionalProperties":false},"Balance":{"type":"object","properties":{"mode":{"type":"string","enum":["test","live"],"description":"The mode of the key that asked, whose bookings it adds up.","example":"test"},"object":{"type":"string","enum":["balance"],"description":"The type of object. Always `balance`.","example":"balance"},"owed":{"type":"array","items":{"$ref":"#/components/schemas/BalanceAmount"},"description":"Your markup on confirmed bookings plus penalty shares on cancelling and cancelled bookings whose check-out date has passed in UTC, one entry per currency, ordered by currency.","example":[{"amount":124000,"bookings":12,"currency":"EUR"}]},"upcoming":{"type":"array","items":{"$ref":"#/components/schemas/BalanceAmount"},"description":"Your markup on confirmed bookings plus penalty shares on cancelling and cancelled bookings through their check-out date, one entry per currency. It moves to `owed` the day after check-out in UTC.","example":[{"amount":6700,"bookings":2,"currency":"EUR"},{"amount":31050,"bookings":3,"currency":"USD"}]}},"required":["mode","object","owed","upcoming"],"additionalProperties":false,"description":"What Mavio owes you: confirmed markup and cancellation penalty shares, regardless of refund status, never converted between currencies."},"BalanceAmount":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"description":"Your markup or cancellation penalty share on these bookings, in the currency's minor units, as Adyen counts them: cents for USD and EUR.","example":124000},"bookings":{"type":"integer","minimum":0,"description":"How many confirmed bookings and cancellations with a positive penalty share it adds up.","example":12},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"The currency the bookings were sold in.","example":"EUR"}},"required":["amount","bookings","currency"],"additionalProperties":false},"Usage":{"type":"object","properties":{"bookings":{"type":"object","properties":{"days":{"type":"array","items":{"$ref":"#/components/schemas/UsageBookingDay"},"description":"Every day from `from` to `to`, oldest first, with the bookings created that day by where each stands now.","example":[{"date":"2026-10-24","cancelled":0,"confirmed":2,"failed":1,"processing":0}]},"summary":{"$ref":"#/components/schemas/UsageBookings"}},"required":["days","summary"],"additionalProperties":false,"description":"The bookings your partner created in this mode."},"from":{"type":"string","format":"date","description":"The first day counted, in UTC.","example":"2026-09-25"},"mode":{"type":"string","enum":["test","live"],"description":"The mode of the key that asked, whose requests and bookings it counts.","example":"test"},"object":{"type":"string","enum":["usage"],"description":"The type of object. Always `usage`.","example":"usage"},"rateLimits":{"$ref":"#/components/schemas/UsageRateLimits"},"requests":{"type":"object","properties":{"days":{"type":"array","items":{"$ref":"#/components/schemas/UsageRequestDay"},"description":"Every day from `from` to `to`, oldest first, including days without requests.","example":[{"date":"2026-10-24","clientErrors":3,"latency":{"p50Ms":180,"p95Ms":2400},"rateLimited":1,"requests":1250,"serverErrors":0}]},"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/UsageEndpoint"},"description":"The endpoints your standard keys called over the range, most requested first.","example":[{"days":[{"date":"2026-10-24","clientErrors":3,"latency":{"p50Ms":180,"p95Ms":2400},"rateLimited":1,"requests":1250,"serverErrors":0}],"endpoint":"GET /v1/listings","summary":{"clientErrors":3,"latency":{"p50Ms":180,"p95Ms":2400},"rateLimited":1,"requests":1250,"serverErrors":0}}]},"summary":{"$ref":"#/components/schemas/UsageRequests"}},"required":["days","endpoints","summary"],"additionalProperties":false,"description":"The requests your standard keys sent in this mode. Admin keys, which the app uses, and requests without a valid key are left out."},"to":{"type":"string","format":"date","description":"The last day counted, in UTC. Today is counted so far.","example":"2026-10-24"}},"required":["bookings","from","mode","object","rateLimits","requests","to"],"additionalProperties":false,"description":"How your partner used the API, one UTC day at a time."},"UsageBookingDay":{"type":"object","properties":{"date":{"type":"string","format":"date","description":"The day, in UTC.","example":"2026-10-24"},"cancelled":{"type":"integer","minimum":0,"description":"Bookings that are cancelled now.","example":0},"confirmed":{"type":"integer","minimum":0,"description":"Bookings that are confirmed now.","example":2},"failed":{"type":"integer","minimum":0,"description":"Bookings that failed.","example":1},"processing":{"type":"integer","minimum":0,"description":"Bookings still waiting on the supplier.","example":0}},"required":["date","cancelled","confirmed","failed","processing"],"additionalProperties":false},"UsageBookings":{"type":"object","properties":{"cancelled":{"type":"integer","minimum":0,"description":"Bookings that are cancelled now.","example":0},"confirmed":{"type":"integer","minimum":0,"description":"Bookings that are confirmed now.","example":2},"failed":{"type":"integer","minimum":0,"description":"Bookings that failed.","example":1},"processing":{"type":"integer","minimum":0,"description":"Bookings still waiting on the supplier.","example":0}},"required":["cancelled","confirmed","failed","processing"],"additionalProperties":false,"description":"The bookings created over the whole range."},"UsageRateLimits":{"type":"object","properties":{"datedTestSearchesPerMinute":{"type":"integer","minimum":0,"description":"Searches with a stay your test keys can make a minute, on top of `requestsPerSecond`.","example":60},"nonDatedSearchesPerSecond":{"type":"integer","minimum":0,"description":"Searches without stay or pricing parameters your partner can make a second, apart from `requestsPerSecond`.","example":100},"quotesPerMinute":{"type":"integer","minimum":0,"description":"Quotes your partner can create a minute in this mode, on top of `requestsPerSecond`.","example":60},"requestsPerSecond":{"type":"integer","minimum":0,"description":"Requests your partner can make a second in this mode across every other endpoint.","example":20},"webhookSendsPerMinute":{"type":"integer","minimum":0,"description":"Webhook test sends and delivery replays your partner can make a minute in this mode, on top of `requestsPerSecond`.","example":6}},"required":["datedTestSearchesPerMinute","nonDatedSearchesPerSecond","quotesPerMinute","requestsPerSecond","webhookSendsPerMinute"],"additionalProperties":false,"description":"The allowances your standard keys share in this mode, the same for every partner. Admin keys have their own per-second counts."},"UsageRequestDay":{"type":"object","properties":{"date":{"type":"string","format":"date","description":"The day, in UTC.","example":"2026-10-24"},"clientErrors":{"type":"integer","minimum":0,"description":"Requests answered with a 4xx: a parameter or key the API refused, or a rate limit.","example":3},"latency":{"type":"object","nullable":true,"properties":{"p50Ms":{"type":"integer","minimum":0,"description":"Half of the requests were answered within this many milliseconds.","example":180},"p95Ms":{"type":"integer","minimum":0,"description":"95% of the requests were answered within this many milliseconds.","example":2400}},"required":["p50Ms","p95Ms"],"additionalProperties":false,"description":"How long the API took to answer, from receiving each request to sending its response, without the network between you and it. Estimated within a histogram whose buckets are 25% wide. `null` without requests."},"rateLimited":{"type":"integer","minimum":0,"description":"Requests answered with a 429 `rate_limited` because an allowance in `rateLimits` was used up. Also counted in `clientErrors`.","example":1},"requests":{"type":"integer","minimum":0,"description":"Requests your standard keys sent in this mode.","example":1250},"serverErrors":{"type":"integer","minimum":0,"description":"Requests answered with a 5xx: something went wrong on our side.","example":0}},"required":["date","clientErrors","latency","rateLimited","requests","serverErrors"],"additionalProperties":false},"UsageEndpoint":{"type":"object","properties":{"days":{"type":"array","items":{"$ref":"#/components/schemas/UsageRequestDay"},"description":"Every day from `from` to `to`, oldest first, including days without requests.","example":[{"date":"2026-10-24","clientErrors":3,"latency":{"p50Ms":180,"p95Ms":2400},"rateLimited":1,"requests":1250,"serverErrors":0}]},"endpoint":{"type":"string","description":"The method and path, such as `GET /v1/listings/{id}`. `/v1/*` holds the requests to a path that matches no endpoint.","example":"GET /v1/listings"},"summary":{"$ref":"#/components/schemas/UsageRequests"}},"required":["days","endpoint","summary"],"additionalProperties":false},"UsageRequests":{"type":"object","properties":{"clientErrors":{"type":"integer","minimum":0,"description":"Requests answered with a 4xx: a parameter or key the API refused, or a rate limit.","example":3},"latency":{"type":"object","nullable":true,"properties":{"p50Ms":{"type":"integer","minimum":0,"description":"Half of the requests were answered within this many milliseconds.","example":180},"p95Ms":{"type":"integer","minimum":0,"description":"95% of the requests were answered within this many milliseconds.","example":2400}},"required":["p50Ms","p95Ms"],"additionalProperties":false,"description":"How long the API took to answer, from receiving each request to sending its response, without the network between you and it. Estimated within a histogram whose buckets are 25% wide. `null` without requests."},"rateLimited":{"type":"integer","minimum":0,"description":"Requests answered with a 429 `rate_limited` because an allowance in `rateLimits` was used up. Also counted in `clientErrors`.","example":1},"requests":{"type":"integer","minimum":0,"description":"Requests your standard keys sent in this mode.","example":1250},"serverErrors":{"type":"integer","minimum":0,"description":"Requests answered with a 5xx: something went wrong on our side.","example":0}},"required":["clientErrors","latency","rateLimited","requests","serverErrors"],"additionalProperties":false,"description":"The requests over the whole range."},"FailBookingRefundRequest":{"type":"object","properties":{"reason":{"type":"string","enum":["card_unavailable","refund_window_expired","disputed"],"description":"Why the refund fails. A card or expired refund window needs another card; a dispute ends the refund.","example":"card_unavailable"}},"required":["reason"],"additionalProperties":false},"ListingTestState":{"type":"object","properties":{"expiresAt":{"type":"string","nullable":true,"format":"date-time","description":"When the scenario ends by itself, in UTC: an hour after the helper that set it. Null while your test quotes price normally.","example":"2026-10-23T15:00:00.000Z"},"listingId":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The listing.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"object":{"type":"string","enum":["listing_test_state"],"description":"The type of object. Always `listing_test_state`.","example":"listing_test_state"},"scenario":{"type":"string","nullable":true,"enum":["outage","sell_out",null],"description":"What your test quotes for the listing get: `sell_out` answers `201` with no offers, and `outage` answers `503 supplier_unavailable`. Null while they price normally.","example":"sell_out"}},"required":["expiresAt","listingId","object","scenario"],"description":"A listing's scenario in your partner's test mode. Your live quotes never see it."},"ChangePriceRequest":{"type":"object","properties":{"at":{"type":"string","enum":["payment","booking"],"description":"When the price moves: `payment`, the default, when you start a payment for the offer, or `booking`, after the shopper has paid, when its booking is made.","example":"booking"},"percent":{"type":"number","minimum":-50,"maximum":50,"description":"How far the price moves, in percent of the supplier's price: from -50 to 50, and 5 when left out.","example":-10}},"additionalProperties":false},"SellOutOfferRequest":{"type":"object","properties":{"at":{"type":"string","enum":["payment","booking"],"description":"When the room sells out: `payment`, the default, when you start a payment for the offer, or `booking`, after the shopper has paid, when its booking is made.","example":"booking"}},"additionalProperties":false},"AuthorizePaymentRequest":{"type":"object","properties":{"outcome":{"type":"string","enum":["authorized","declined"],"description":"`authorized` holds the shopper's card, and `declined` has the card refused, as a declined card is. `authorized` when left out.","example":"declined"}},"additionalProperties":false},"CancelBookingBySupplierRequest":{"type":"object","properties":{"at":{"type":"string","enum":["now","cancel"],"description":"`now` (the default) finds the supplier cancellation at once. `cancel` leaves it for your next cancel or the next hourly look-up.","example":"cancel"}},"additionalProperties":false},"UpdateHotelConfirmationCodeRequest":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":100,"description":"The hotel's code, up to 100 characters. Mavio makes one up when it's left out.","example":"HX-48213"}},"additionalProperties":false},"Partner":{"type":"object","properties":{"country":{"type":"string","nullable":true,"description":"Where the partner is based, as an ISO 3166-1 alpha-2 code","example":"FR"},"createdAt":{"type":"string","format":"date-time","description":"When the partner signed up","example":"2026-10-22T09:30:00.000Z"},"defaultMarkupPercent":{"type":"number","description":"The fallback markup when no request override, listing rule or chain rule applies, as a percent of the supplier price. 0 until you set one.","example":12.5},"id":{"type":"string","pattern":"^ptn_[0-9A-Za-z]{22}$","description":"The partner id","example":"ptn_034k4ttAcIm6BKxGcBxHHd"},"name":{"type":"string","description":"The company name","example":"Acme Travel"},"object":{"type":"string","enum":["partner"],"description":"Always `partner`","example":"partner"},"website":{"type":"string","nullable":true,"description":"The company's website","example":"https://acme.travel"}},"required":["country","createdAt","defaultMarkupPercent","id","name","object","website"],"additionalProperties":false},"UpdatePartner":{"type":"object","properties":{"defaultMarkupPercent":{"type":"number","minimum":0,"maximum":100,"description":"Your fallback markup when no request override, listing rule or chain rule applies, as a percent of the supplier price from 0 to 100 with at most 2 decimals. It applies from your next quote, in test and live mode alike.","example":12.5}},"required":["defaultMarkupPercent"],"additionalProperties":false},"PricingRuleList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PricingRule"},"description":"The current non-removed rules, newest version first.","example":[]},"hasMore":{"type":"boolean","description":"Whether another page follows.","example":false},"nextPage":{"type":"string","nullable":true,"pattern":"^prl_[0-9A-Za-z]{22}$","description":"Pass as page for the next page, or null at the end.","example":null},"object":{"type":"string","enum":["list"],"description":"Always list.","example":"list"}},"required":["data","hasMore","nextPage","object"],"additionalProperties":false},"PricingRule":{"allOf":[{"$ref":"#/components/schemas/SavePricingRule"},{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time","description":"When this version was saved, in UTC.","example":"2026-10-27T13:00:00.000Z"},"id":{"type":"string","pattern":"^prl_[0-9A-Za-z]{22}$","description":"This immutable rule version.","example":"prl_031OeqUcl4UtGlNOdBpZCM"},"object":{"type":"string","enum":["pricing_rule"],"description":"Always pricing_rule.","example":"pricing_rule"}},"required":["createdAt","id","object"],"additionalProperties":false}]},"SavePricingRule":{"type":"object","properties":{"markupPercent":{"type":"number","nullable":true,"minimum":0,"maximum":100,"description":"A fixed markup from 0 to 100 with at most 2 decimals. Null removes this target’s rule, restoring the next matching layer.","example":12.5},"target":{"oneOf":[{"type":"object","properties":{"listingId":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The merged Mavio listing, across all its suppliers.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"type":{"type":"string","enum":["listing"],"description":"One listing.","example":"listing"}},"required":["listingId","type"],"additionalProperties":false},{"type":"object","properties":{"chainCode":{"type":"string","minLength":1,"maxLength":100,"description":"A chain code from GET /v1/chains; brand codes are not accepted.","example":"hilton"},"type":{"type":"string","enum":["chain"],"description":"All listings with this normalized chain code.","example":"chain"}},"required":["chainCode","type"],"additionalProperties":false}],"description":"The listing or chain this rule applies to.","example":{"chainCode":"hilton","type":"chain"}}},"required":["markupPercent","target"],"additionalProperties":false},"SavedPricingRules":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PricingRule"},"description":"The saved rule versions, in the order of the request’s targets.","example":[]},"object":{"type":"string","enum":["list"],"description":"Always list.","example":"list"}},"required":["data","object"],"additionalProperties":false},"TestOriginList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TestOrigin"},"description":"The origins you added, oldest first. `http://localhost`, `http://127.0.0.1`, `http://*.localhost` are always allowed too, for every partner, so they aren't listed.","example":[{"createdAt":"2026-10-27T09:30:00.000Z","id":"tor_034k4ttIQ8IuYWaMbWx2ox","object":"test_origin","origin":"https://checkout-test.acme.travel"}]},"object":{"type":"string","enum":["list"],"description":"Always `list`","example":"list"}},"required":["data","object"],"additionalProperties":false},"TestOrigin":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time","description":"When the origin was added","example":"2026-10-27T09:30:00.000Z"},"id":{"type":"string","pattern":"^tor_[0-9A-Za-z]{22}$","description":"The test origin id","example":"tor_034k4ttIQ8IuYWaMbWx2ox"},"object":{"type":"string","enum":["test_origin"],"description":"Always `test_origin`","example":"test_origin"},"origin":{"type":"string","description":"An origin Adyen's component runs from with test payments","example":"https://checkout-test.acme.travel"}},"required":["createdAt","id","object","origin"],"additionalProperties":false},"CreateTestOrigin":{"type":"object","properties":{"origin":{"type":"string","maxLength":267,"description":"The origin your checkout page runs on, exactly as a browser sends it in `Origin`: `https`, a lowercase host, a port only when it isn't the default, and no path or trailing slash. Plain `http` only on a localhost host. `http://localhost`, `http://127.0.0.1`, `http://*.localhost` are always allowed already.","example":"https://checkout-test.acme.travel"}},"required":["origin"],"additionalProperties":false},"ApiKeyList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"},"description":"Your API keys, newest first, revoked ones included","example":[{"createdAt":"2026-10-22T09:30:00.000Z","id":"key_034k4ttIQ8IuYWaMbWx2ox","lastUsedAt":"2026-10-22T10:15:00.000Z","mode":"test","name":"Production server","object":"api_key","prefix":"sk_test_4fQ9","revokedAt":null}]},"object":{"type":"string","enum":["list"],"description":"Always `list`","example":"list"}},"required":["data","object"],"additionalProperties":false},"ApiKey":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time","description":"When the key was created","example":"2026-10-22T09:30:00.000Z"},"id":{"type":"string","pattern":"^key_[0-9A-Za-z]{22}$","description":"The API key id","example":"key_034k4ttIQ8IuYWaMbWx2ox"},"lastUsedAt":{"type":"string","nullable":true,"format":"date-time","description":"When a request last authenticated with the key, or null when it never has or we no longer know","example":"2026-10-22T10:15:00.000Z"},"mode":{"type":"string","enum":["test","live"],"description":"Test keys never book at a hotel or charge a card","example":"test"},"name":{"type":"string","description":"What the key is for","example":"Production server"},"object":{"type":"string","enum":["api_key"],"description":"Always `api_key`","example":"api_key"},"prefix":{"type":"string","description":"The first characters of the key, to recognize it","example":"sk_test_4fQ9"},"revokedAt":{"type":"string","nullable":true,"format":"date-time","description":"When the key was revoked, or null while it works","example":null}},"required":["createdAt","id","lastUsedAt","mode","name","object","prefix","revokedAt"],"additionalProperties":false},"CreatedApiKey":{"allOf":[{"$ref":"#/components/schemas/ApiKey"},{"type":"object","properties":{"secret":{"type":"string","description":"The key itself. This is the only time you see it: store it now.","example":"sk_test_4fQ9xK2mWbT7rLp0VzN8aC3eY6uHdJ1sGqR5oFiM9Bk"}},"required":["secret"],"additionalProperties":false}]},"CreateApiKey":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60,"description":"What the key is for, so you can tell your keys apart","example":"Production server"}},"required":["name"],"additionalProperties":false},"WebhookList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"},"description":"Your registrations in this mode, newest first.","example":[]},"object":{"type":"string","enum":["list"],"description":"Always list.","example":"list"}},"required":["data","object"],"additionalProperties":false},"Webhook":{"type":"object","properties":{"eventTypes":{"type":"array","items":{"type":"string","enum":["booking.created","booking.confirmed","booking.failed","booking.cancelling","booking.cancelled","booking.refund.updated","booking.hotel_confirmation_code.updated"],"description":"The booking event to subscribe to.","example":"booking.created"},"minItems":1,"maxItems":7,"description":"Events delivered to this endpoint.","example":["booking.created"]},"name":{"type":"string","minLength":1,"maxLength":100,"description":"A name for this endpoint.","example":"Booking notifications"},"url":{"type":"string","maxLength":2048,"format":"uri","description":"Public HTTPS destination. Private addresses and redirects are rejected.","example":"https://example.com/webhooks"},"active":{"type":"boolean","description":"Whether delivery is enabled.","example":true},"createdAt":{"type":"string","format":"date-time","description":"When the endpoint was registered.","example":"2026-10-27T12:00:00.000Z"},"id":{"type":"string","pattern":"^wh_[0-9A-Za-z]{22}$","description":"Endpoint identifier.","example":"wh_031OeqUcl4UtGlNOdBpZCN"},"mode":{"type":"string","enum":["test","live"],"description":"The mode this registration receives events from.","example":"test"},"object":{"type":"string","enum":["webhook"],"description":"Always webhook.","example":"webhook"},"updatedAt":{"type":"string","format":"date-time","description":"When the endpoint last changed.","example":"2026-10-27T12:00:00.000Z"}},"required":["eventTypes","name","url","active","createdAt","id","mode","object","updatedAt"],"additionalProperties":false},"CreatedWebhook":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string","description":"Signing secret, returned only on creation. Store it securely.","example":"whsec_example"}},"required":["secret"],"additionalProperties":false}]},"CreateWebhook":{"type":"object","properties":{"eventTypes":{"type":"array","items":{"type":"string","enum":["booking.created","booking.confirmed","booking.failed","booking.cancelling","booking.cancelled","booking.refund.updated","booking.hotel_confirmation_code.updated"],"description":"The booking event to subscribe to.","example":"booking.created"},"minItems":1,"maxItems":7,"description":"Events delivered to this endpoint.","example":["booking.created"]},"name":{"type":"string","minLength":1,"maxLength":100,"description":"A name for this endpoint.","example":"Booking notifications"},"url":{"type":"string","maxLength":2048,"format":"uri","description":"Public HTTPS destination. Private addresses and redirects are rejected.","example":"https://example.com/webhooks"}},"required":["eventTypes","name","url"],"additionalProperties":false},"UpdateWebhook":{"type":"object","properties":{"eventTypes":{"type":"array","items":{"type":"string","enum":["booking.created","booking.confirmed","booking.failed","booking.cancelling","booking.cancelled","booking.refund.updated","booking.hotel_confirmation_code.updated"],"description":"The booking event to subscribe to.","example":"booking.created"},"minItems":1,"maxItems":7,"description":"Events delivered to this endpoint.","example":["booking.created"]},"name":{"type":"string","minLength":1,"maxLength":100,"description":"A name for this endpoint.","example":"Booking notifications"},"url":{"type":"string","maxLength":2048,"format":"uri","description":"Public HTTPS destination. Private addresses and redirects are rejected.","example":"https://example.com/webhooks"},"active":{"type":"boolean","description":"Whether delivery is enabled.","example":true}},"additionalProperties":false},"WebhookDelivery":{"type":"object","properties":{"attemptCount":{"type":"integer","minimum":0,"description":"Total attempts, including manual replays.","example":0},"createdAt":{"type":"string","format":"date-time","description":"When this delivery was queued.","example":"2026-10-27T12:00:00.000Z"},"error":{"type":"string","nullable":true,"description":"Latest delivery failure, if any.","example":null},"eventId":{"type":"string","pattern":"^evt_[0-9A-Za-z]{22}$","description":"The stable event identifier shared by retries and replay.","example":"evt_031OeqUcl4UtGlNOdBpZCN"},"eventType":{"type":"string","enum":["booking.created","booking.confirmed","booking.failed","booking.cancelling","booking.cancelled","booking.refund.updated","booking.hotel_confirmation_code.updated"],"description":"The booking event to subscribe to.","example":"booking.created"},"id":{"type":"string","pattern":"^whd_[0-9A-Za-z]{22}$","description":"Delivery identifier.","example":"whd_031OeqUcl4UtGlNOdBpZCN"},"nextAttemptAt":{"type":"string","nullable":true,"format":"date-time","description":"Next scheduled attempt, or null after delivery stops.","example":null},"object":{"type":"string","enum":["webhook_delivery"],"description":"Always webhook_delivery.","example":"webhook_delivery"},"responseStatus":{"type":"integer","nullable":true,"description":"Latest HTTP response status, or null on a network failure.","example":null},"sentAt":{"type":"string","nullable":true,"format":"date-time","description":"When the receiver last accepted the event.","example":null},"status":{"type":"string","enum":["pending","sent","failed","abandoned"],"description":"Pending delivery, accepted, awaiting retry, or stopped after exhausting retries or disabling the endpoint.","example":"pending"},"synthetic":{"type":"boolean","description":"Whether this is a synthetic test event.","example":true}},"required":["attemptCount","createdAt","error","eventId","eventType","id","nextAttemptAt","object","responseStatus","sentAt","status","synthetic"],"additionalProperties":false},"SendWebhookTest":{"type":"object","properties":{"eventType":{"type":"string","enum":["booking.created","booking.confirmed","booking.failed","booking.cancelling","booking.cancelled","booking.refund.updated","booking.hotel_confirmation_code.updated"],"description":"The booking event to subscribe to.","example":"booking.created"}},"required":["eventType"],"additionalProperties":false},"WebhookDeliveryList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"},"description":"Deliveries, newest first.","example":[]},"hasMore":{"type":"boolean","description":"Whether older deliveries remain.","example":false},"object":{"type":"string","enum":["list"],"description":"Always list.","example":"list"}},"required":["data","hasMore","object"],"additionalProperties":false},"WebhookDeliveryDetail":{"allOf":[{"$ref":"#/components/schemas/WebhookDelivery"},{"type":"object","properties":{"payload":{"type":"object","additionalProperties":{"nullable":true},"description":"The immutable JSON sent to the receiver, preserved across schema changes."}},"required":["payload"],"additionalProperties":false}]},"EventList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEvent"},"description":"Committed booking events, oldest first in transaction order.","example":[]},"hasMore":{"type":"boolean","description":"Whether another committed page is available.","example":false},"nextCursor":{"type":"string","description":"Pass as after, including when this page is empty. Keep polling to recover later changes.","example":"eyJ0eGlkIjoiMCIsImNoYW5nZUlkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIn0"},"object":{"type":"string","enum":["list"],"description":"Always list.","example":"list"}},"required":["data","hasMore","nextCursor","object"],"additionalProperties":false},"WebhookEvent":{"type":"object","properties":{"createdAt":{"type":"string","format":"date-time","description":"When Mavio recorded the change.","example":"2026-10-27T12:00:00.000Z"},"data":{"type":"object","properties":{"bookingId":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"Retrieve GET /v1/bookings/{id} for the current booking.","example":"bk_031OeqUcl4UtGlNOdBpZCN"}},"required":["bookingId"],"additionalProperties":false,"description":"Reference to the changed resource. No booking snapshot or private payment information."},"id":{"type":"string","pattern":"^evt_[0-9A-Za-z]{22}$","description":"Stable event id, shared by the feed, webhook retries and replay, and sent as the webhook-id header.","example":"evt_031OeqUcl4UtGlNOdBpZCN"},"mode":{"type":"string","enum":["test","live"],"description":"The booking mode.","example":"test"},"object":{"type":"string","enum":["event"],"description":"Always event.","example":"event"},"synthetic":{"type":"boolean","description":"True only for a test send, which represents no actual booking and is excluded from the events feed.","example":false},"type":{"type":"string","enum":["booking.created","booking.confirmed","booking.failed","booking.cancelling","booking.cancelled","booking.refund.updated","booking.hotel_confirmation_code.updated"],"description":"The booking event to subscribe to.","example":"booking.created"}},"required":["createdAt","data","id","mode","object","synthetic","type"],"additionalProperties":false}},"parameters":{}},"paths":{"/v1/chains":{"get":{"description":"Lists every hotel chain with its brands, and the codes a listing’s `chain` and `brand` carry. Pass any of them as `chains[]` to `GET /v1/listings`: a chain’s code matches its brands’ listings too.","operationId":"listChains","security":[{"bearerAuth":[]}],"summary":"List chains","tags":["Listings"],"responses":{"200":{"description":"Every chain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChainList"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid request"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/changes":{"get":{"description":"Lists the changes to the listings you can see, so you can keep your own copy. Leave out `after` to read from the first change, which gives you every listing, then pass each `nextCursor` as `after`. When `hasMore` is false you have caught up: keep `nextCursor` and call again later. Each change carries the listing as it is now: store it, or delete your copy when it is null.","operationId":"listListingChanges","security":[{"bearerAuth":[]}],"summary":"List listing changes","tags":["Listings"],"parameters":[{"schema":{"type":"string","description":"The nextCursor of the previous response, to get the changes after it. Leave it out to read from the first change.","example":"WyI3NDUxIiwiMDE5YTBmM2MtN2IyZS03YzQxLTlhNmQtM2Y1ZThiMmMxZDQwIl0"},"required":false,"description":"The nextCursor of the previous response, to get the changes after it. Leave it out to read from the first change.","name":"after","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":100,"description":"How many changes to return, from 1 to 100.","example":100},"required":false,"description":"How many changes to return, from 1 to 100.","name":"limit","in":"query"},{"schema":{"type":"string","default":"en","description":"The language to read text in, as a BCP 47 tag. A tag we have no text for reads its parent language, so fr-CA reads fr. Each text field we lack in that language reads in English, the default.","example":"fr"},"required":false,"description":"The language to read text in, as a BCP 47 tag. A tag we have no text for reads its parent language, so fr-CA reads fr. Each text field we lack in that language reads in English, the default.","name":"language","in":"query"}],"responses":{"200":{"description":"A page of changes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingChangeList"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be the nextCursor of an earlier response","param":"after"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/{id}":{"get":{"description":"Retrieves the listing with the given id.","operationId":"getListing","security":[{"bearerAuth":[]}],"summary":"Retrieve a listing","tags":["Listings"],"parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The id of the listing to retrieve.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"required":true,"description":"The id of the listing to retrieve.","name":"id","in":"path"},{"schema":{"type":"string","default":"en","description":"The language to read text in, as a BCP 47 tag. A tag we have no text for reads its parent language, so fr-CA reads fr. Each text field we lack in that language reads in English, the default.","example":"fr"},"required":false,"description":"The language to read text in, as a BCP 47 tag. A tag we have no text for reads its parent language, so fr-CA reads fr. Each text field we lack in that language reads in English, the default.","name":"language","in":"query"}],"responses":{"200":{"description":"The listing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Listing"}}}},"400":{"description":"The id is not a listing id, or the language is not a language tag","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a lst_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No listing has this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such listing","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/{id}/reviews":{"get":{"description":"Lists what guests wrote about their stay at the listing, newest first, one page at a time, each in the language the guest wrote it in. Pass `language[]` to keep the languages your guests read. A review some suppliers both carry shows once.","operationId":"listListingReviews","security":[{"bearerAuth":[]}],"summary":"List listing reviews","tags":["Listings"],"parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The id of the listing to retrieve.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"required":true,"description":"The id of the listing to retrieve.","name":"id","in":"path"},{"schema":{"type":"string","description":"The nextCursor of the previous response, to get the reviews after it. Keep the other parameters the same.","example":"WyIyMDI2LTEwLTE2VDAwOjAwOjAwLjAwMFoiLCIwMTlhMGYzYy03YjJlLTdjNDEtOWE2ZC0zZjVlOGIyYzFkNDAiXQ"},"required":false,"description":"The nextCursor of the previous response, to get the reviews after it. Keep the other parameters the same.","name":"after","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2,3}(?:-[A-Z][a-z]{3})?(?:-(?:[A-Z]{2}|[0-9]{3}))?$"},"default":[],"description":"Only reviews written in one of these languages. A tag also matches the tags under it, so `en` matches `en-US` and `en-GB`. Repeat the parameter for each tag.","example":["en","fr"]},"required":false,"description":"Only reviews written in one of these languages. A tag also matches the tags under it, so `en` matches `en-US` and `en-GB`. Repeat the parameter for each tag.","name":"language[]","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":30,"description":"How many reviews to return, from 1 to 100.","example":30},"required":false,"description":"How many reviews to return, from 1 to 100.","name":"limit","in":"query"}],"responses":{"200":{"description":"A page of reviews","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewList"}}}},"400":{"description":"The id is not a listing id, or a parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a lst_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No listing has this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such listing","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings":{"get":{"description":"Searches the active listings in a box or a country, best score first, one page at a time. Without stay or pricing parameters, each partner has a separate allowance of 100 searches a second in each mode and key kind. Send a stay (checkIn, checkOut, guestNationality, currency and occupancy[]) to price each listing on the page as a quote for that stay would: its `availability` says whether it sells the stay and from what price. Prices never change the order, so a page can hold listings that are sold out. Quote the listing your guest picks before booking. With test keys, your partner can make a set number of searches with a stay a minute, and their `RateLimit-*` headers count those searches rather than requests.","operationId":"searchListings","security":[{"bearerAuth":[]}],"summary":"Search listings","tags":["Listings"],"parameters":[{"schema":{"type":"array","items":{"type":"string","enum":["accessible_bath_shower","accessible_by_elevator","accessible_by_lift","accessible_by_stairs_only","accessible_parking","accessible_property","accessible_rooms_available","additional_bathroom","air_conditioning","airport_transportation_available","all_inclusive","balcony_or_terrace","bar","bath","bath_or_shower","bathroom","bathtub","beach_access","beach_front","body_soap","breakfast_available","business_facilities","carbon_monoxide_detector","childcare_services","childrens_high_chair","city_view","cleaning_products","coffee_tea_maker","computer","concierge_services","conditioner","connecting_room_available","courtyard_view","cribs_or_cots_available","desk","dining_area","dining_table","dishwasher","dressing_room","dryer","electric_vehicle_charging_station","emergency_cord_in_bathroom","extra_long_bed","family_friendly","fan","fire_alarm","fire_extinguisher","fireplace","foldup_bed_available","free_airport_transportation","free_breakfast","free_laundry_services","free_parking","free_shuttle_available","free_toiletries","free_wifi_internet","front_desk_24_hour","garden","garden_view","golf_course_within_2_mi","ground_floor_unit","gym","hairdryer","heating","hot_tub_jacuzzi","housekeeping_available","internet","ironing_facilities","kettle","key_access","key_card_access","kitchen","kitchenette","kitchenware","lake_view","large_vehicle_parking","laundry_services","linens","microwave","minibar","mountain_view","no_pets_allowed","non_smoking","ocean_front","outdoor_bathroom","outdoor_cooking","outdoor_dining_area","oven","parking","patio","pets_allowed","pool","private_bathroom","private_beach_access","private_entrance","private_hot_tub_jacuzzi","private_pool_access","private_unit_in_building","refrigerator","restaurant","river_view","rollin_shower","room_service","safe","satellite_cable_channels","sauna","sea_ocean_view","self_check_in","shampoo","shared_bathroom","shared_kitchen","shared_living_spaces","shower","shuttle_available","ski_in_ski_out","smoking_allowed","sofa","sofa_bed","spa","spa_bath","stove","streaming_service","street_or_offsite_parking","telephone","tennis_court","toilet","toilet_paper","toilet_with_grab_rails","towels","towels_sheets_extra_fee","tv","view","wardrobe_or_closet","washer_dryer","washing_machine","water_view","waterfront","wheelchair_accessible","wine_glasses"]},"description":"Only listings with every one of these amenities. Repeat the parameter for each code.","example":["pool","spa"]},"required":false,"description":"Only listings with every one of these amenities. Repeat the parameter for each code.","name":"amenities[]","in":"query"},{"schema":{"type":"array","items":{"type":"string"},"description":"Only listings of any one of these chains or brands, by the codes `GET /v1/chains` lists. A chain matches its brands’ listings too. Repeat the parameter for each code.","example":["hilton","westin"]},"required":false,"description":"Only listings of any one of these chains or brands, by the codes `GET /v1/chains` lists. A chain matches its brands’ listings too. Repeat the parameter for each code.","name":"chains[]","in":"query"},{"schema":{"type":"string","pattern":"^[A-Z]{2}$","description":"Two-letter code of the country to search, in place of a box.","example":"FR"},"required":false,"description":"Two-letter code of the country to search, in place of a box.","name":"countryCode","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":30,"description":"How many listings to return, from 1 to 100.","example":30},"required":false,"description":"How many listings to return, from 1 to 100.","name":"limit","in":"query"},{"schema":{"type":"number","minimum":0,"maximum":10,"description":"Only listings with at least this guest rating, from 0 to 10 in steps of 0.1. Leaves out listings without one.","example":8},"required":false,"description":"Only listings with at least this guest rating, from 0 to 10 in steps of 0.1. Leaves out listings without one.","name":"minGuestRating","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"Only listings whose guest rating has at least this many reviews behind it. Leaves out listings without one.","example":50},"required":false,"description":"Only listings whose guest rating has at least this many reviews behind it. Leaves out listings without one.","name":"minReviewCount","in":"query"},{"schema":{"type":"number","minimum":0.5,"maximum":5,"description":"Only listings with at least this star rating, in half steps. Leaves out listings without one.","example":4},"required":false,"description":"Only listings with at least this star rating, in half steps. Leaves out listings without one.","name":"minStars","in":"query"},{"schema":{"type":"number","minimum":-90,"maximum":90,"description":"Latitude of the box's north-east corner, in decimal degrees. Send all four corners, or countryCode.","example":48.9},"required":false,"description":"Latitude of the box's north-east corner, in decimal degrees. Send all four corners, or countryCode.","name":"neLat","in":"query"},{"schema":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude of the box's north-east corner, in decimal degrees. Send all four corners, or countryCode.","example":2.42},"required":false,"description":"Longitude of the box's north-east corner, in decimal degrees. Send all four corners, or countryCode.","name":"neLng","in":"query"},{"schema":{"type":"string","description":"The nextPage of the previous response, to get the page after it. Keep the other parameters the same.","example":"WzM5LjgsIjAxOWEwZjNjLTdiMmUtN2M0MS05YTZkLTNmNWU4YjJjMWQ0MCJd"},"required":false,"description":"The nextPage of the previous response, to get the page after it. Keep the other parameters the same.","name":"page","in":"query"},{"schema":{"type":"number","minimum":-90,"maximum":90,"description":"Latitude of the box's south-west corner, in decimal degrees. Send all four corners, or countryCode.","example":48.81},"required":false,"description":"Latitude of the box's south-west corner, in decimal degrees. Send all four corners, or countryCode.","name":"swLat","in":"query"},{"schema":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude of the box's south-west corner, in decimal degrees. Send all four corners, or countryCode.","example":2.25},"required":false,"description":"Longitude of the box's south-west corner, in decimal degrees. Send all four corners, or countryCode.","name":"swLng","in":"query"},{"schema":{"type":"string","format":"date","description":"The first night of the stay, as YYYY-MM-DD.","example":"2026-12-04"},"required":false,"description":"The first night of the stay, as YYYY-MM-DD.","name":"checkIn","in":"query"},{"schema":{"type":"string","format":"date","description":"The day the guests leave, as YYYY-MM-DD: 1 to 30 nights after checkIn.","example":"2026-12-06"},"required":false,"description":"The day the guests leave, as YYYY-MM-DD: 1 to 30 nights after checkIn.","name":"checkOut","in":"query"},{"schema":{"type":"string","pattern":"^[A-Z]{3}$","description":"The currency to price in, as an ISO 4217 code. Any other answers `currency_not_supported`.","enum":["AED","AUD","BDT","BHD","BRL","CAD","CHF","CNY","COP","CZK","DKK","EGP","EUR","FJD","GBP","HKD","HUF","IDR","ILS","INR","JOD","JPY","KHR","KRW","KWD","KZT","LAK","LKR","MVR","MXN","MYR","NGN","NOK","NZD","OMR","PHP","PKR","PLN","QAR","RON","RUB","SAR","SEK","SGD","THB","TRY","TWD","UAH","USD","VND","XPF","ZAR"],"example":"EUR"},"required":false,"description":"The currency to price in, as an ISO 4217 code. Any other answers `currency_not_supported`.","name":"currency","in":"query"},{"schema":{"type":"string","pattern":"^[A-Z]{2}$","description":"The lead guest's nationality, as an ISO 3166-1 alpha-2 code. Suppliers price for it.","example":"FR"},"required":false,"description":"The lead guest's nationality, as an ISO 3166-1 alpha-2 code. Suppliers price for it.","name":"guestNationality","in":"query"},{"schema":{"type":"number","minimum":0,"maximum":100,"description":"Your markup on these prices, as a percent of the supplier price from 0 to 100 with at most 2 decimals, overriding listing and chain rules and your default.","example":12.5},"required":false,"description":"Your markup on these prices, as a percent of the supplier price from 0 to 100 with at most 2 decimals, overriding listing and chain rules and your default.","name":"markupPercent","in":"query"},{"schema":{"type":"array","items":{"type":"string"},"maxItems":8,"description":"Who sleeps in each room, from 1 to 8 rooms, repeated once per room: the adults, then a hyphen and each child's age. 2-9,4 is two adults with children aged 9 and 4.","example":["2-9,4","1"]},"required":false,"description":"Who sleeps in each room, from 1 to 8 rooms, repeated once per room: the adults, then a hyphen and each child's age. 2-9,4 is two adults with children aged 9 and 4.","name":"occupancy[]","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"`true` prices each listing at its cheapest offer the guest can cancel for a refund.","example":"true"},"required":false,"description":"`true` prices each listing at its cheapest offer the guest can cancel for a refund.","name":"refundable","in":"query"},{"schema":{"type":"string","default":"en","description":"The language to read text in, as a BCP 47 tag. A tag we have no text for reads its parent language, so fr-CA reads fr. Each text field we lack in that language reads in English, the default.","example":"fr"},"required":false,"description":"The language to read text in, as a BCP 47 tag. A tag we have no text for reads its parent language, so fr-CA reads fr. Each text field we lack in that language reads in English, the default.","name":"language","in":"query"}],"responses":{"200":{"description":"A page of listings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSearchResult"}}}},"400":{"description":"A parameter is missing or invalid, or the stay is in a currency we don’t price in (`currency_not_supported`)","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Pass a box (neLat, neLng, swLat, swLng) or countryCode"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A live key prices a stay before you have a contract with Mavio","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Live quotes start once you have a contract with Mavio. Contact Mavio to sign one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner made too many searches with a stay with its test keys this minute or sent too many requests in this mode this second, or your network sent too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Searches with a stay your partner can make a minute with its test keys, or, when the request limit refused, requests it can make a second","schema":{"example":60,"type":"integer"}},"RateLimit-Remaining":{"description":"What is left of that limit","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until that count starts over","schema":{"example":42,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":42,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner has used its test mode limit on searches with a stay for this minute. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/quotes":{"post":{"security":[{"bearerAuth":[]}],"tags":["Quotes"],"description":"Prices one listing for one stay. The quote holds every bookable offer, each covering all the rooms you asked for, until its `expiresAt`. A sold-out stay is a quote without offers. Your partner can create a set number of quotes a minute in each mode, the same for test and live keys. This operation's `RateLimit-*` headers count those quotes rather than requests.","operationId":"createQuote","summary":"Create a quote","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","example":"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14"},"required":false,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}}},"responses":{"201":{"description":"The quote","headers":{"Location":{"schema":{"type":"string","description":"Where to retrieve the quote.","example":"/v1/quotes/qt_031OeqUcl4UtGlNOdBpZCM"},"required":true,"description":"Where to retrieve the quote."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"A field is invalid, or `currency_not_supported` for a currency we don't price in","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be 1 to 30 nights after checkIn","param":"checkOut"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A live key, before you have a contract with Mavio","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Live quotes start once you have a contract with Mavio. Contact Mavio to sign one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No active listing has this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such listing","param":"listingId"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with the same Idempotency-Key is still running, or was cut off before it answered","content":{"application/json":{"example":{"error":{"code":"idempotency_key_in_use","message":"A request with Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" is still running. Retry once it has answered, or, if this lasts longer than the request takes, send a new key.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The Idempotency-Key was first sent with a different request","content":{"application/json":{"example":{"error":{"code":"idempotency_key_reused","message":"Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" was first sent with a different request. Use a new key for a new request.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner created too many quotes in this mode this minute or sent too many requests this second, or your network sent too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Quotes your partner can create a minute in this mode, or, when the request limit refused, requests it can make a second","schema":{"example":60,"type":"integer"}},"RateLimit-Remaining":{"description":"What is left of that limit","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until that count starts over","schema":{"example":42,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":42,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner has used its quote limit for this minute in this mode. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"No supplier could answer. Try again after Retry-After","headers":{"Retry-After":{"schema":{"type":"string","description":"How many seconds to wait before trying again.","example":"30"},"required":true,"description":"How many seconds to wait before trying again."}},"content":{"application/json":{"example":{"error":{"code":"supplier_unavailable","message":"No supplier could price this stay. Try again shortly."}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/quotes/{id}":{"get":{"security":[{"bearerAuth":[]}],"tags":["Quotes"],"description":"Retrieves a quote as it was created, also after it expires.","operationId":"getQuote","summary":"Retrieve a quote","parameters":[{"schema":{"type":"string","pattern":"^qt_[0-9A-Za-z]{22}$","description":"The id of the quote to retrieve.","example":"qt_031OeqUcl4UtGlNOdBpZCM"},"required":true,"description":"The id of the quote to retrieve.","in":"path","name":"id"}],"responses":{"200":{"description":"The quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"The id is not a quote id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a qt_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no quote with this id in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such quote","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/payments":{"post":{"security":[{"bearerAuth":[]}],"tags":["Payments"],"description":"Starts the shopper's payment for an offer. Mavio re-checks the offer with its supplier and holds the shopper's card for the re-checked price, so you never send a price. The payment carries what Adyen's Drop-in or Card Component needs to take the card on your page or in your app, 3DS included, so the card never reaches your servers or Mavio's. Book with the payment once Adyen's component tells you the shopper paid, before its `expiresAt`.","operationId":"createPayment","summary":"Start a payment","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","example":"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14"},"required":false,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequest"}}}},"responses":{"201":{"description":"The payment","headers":{"Location":{"schema":{"type":"string","description":"Where to retrieve the payment.","example":"/v1/payments/pay_031OeqUcl4UtGlNOdBpZCP"},"required":true,"description":"Where to retrieve the payment."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"description":"A field is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid email address","param":"shopper.email"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A live key: live payments open later","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Live payments haven't opened yet. Start payments with a test key."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no offer with this id in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such offer","param":"offerId"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`offer_changed` when the re-check found the offer's price, board, cancellation policy or rooms different from what you were shown, a lower price included: the error's `quote` holds the offer at its new terms, so show them to the shopper and start a payment for its offer. `quote_expired` for an offer of an expired quote, which no supplier was asked about: quote again. `offer_unavailable` when the re-check found the room gone: let the shopper pick another offer. `idempotency_key_in_use` while a request with the same Idempotency-Key is still running.","content":{"application/json":{"example":{"error":{"code":"quote_expired","message":"The offer's quote has expired","param":"offerId"}},"schema":{"$ref":"#/components/schemas/PaymentConflict"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The Idempotency-Key was first sent with a different request","content":{"application/json":{"example":{"error":{"code":"idempotency_key_reused","message":"Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" was first sent with a different request. Use a new key for a new request.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The offer's supplier couldn't answer the re-check. Try again after Retry-After","headers":{"Retry-After":{"schema":{"type":"string","description":"How many seconds to wait before trying again.","example":"30"},"required":true,"description":"How many seconds to wait before trying again."}},"content":{"application/json":{"example":{"error":{"code":"supplier_unavailable","message":"The offer's supplier couldn't re-check it. Try again shortly."}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/payments/{id}":{"get":{"security":[{"bearerAuth":[]}],"tags":["Payments"],"description":"Retrieves a payment as it stands now: its `status` says where the shopper's money is.","operationId":"getPayment","summary":"Retrieve a payment","parameters":[{"schema":{"type":"string","pattern":"^pay_[0-9A-Za-z]{22}$","description":"The id of the payment to retrieve.","example":"pay_031OeqUcl4UtGlNOdBpZCP"},"required":true,"description":"The id of the payment to retrieve.","in":"path","name":"id"}],"responses":{"200":{"description":"The payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"description":"The id is not a payment id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a pay_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no payment with this id in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such payment","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/bookings/{id}/cancel":{"post":{"description":"Cancels the whole confirmed booking with no body, before cancellationPolicy.cancellableUntil. The penalty and refund are frozen from the policy when the call arrives. Mavio waits up to 25 seconds and answers with the booking as it stands. While it is `cancelling`, retrieve it at the pace in `Retry-After`. Set your client timeout to at least 30 seconds. Cancellation carries on if your connection drops. Retry a lost answer with the same Idempotency-Key to replay the first response. In test mode, refundable cancellations are refunded to the original card after capture. Refund completion is separate from cancellation: retrieve the booking and follow `cancellation.refund.status` and `failureReason`. Live payments and bookings are not available yet.","operationId":"cancelBooking","security":[{"bearerAuth":[]}],"summary":"Cancel a booking","tags":["Bookings"],"parameters":[{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"The id of the booking to retrieve.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The id of the booking to retrieve.","in":"path","name":"id"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","example":"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14"},"required":false,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","name":"Idempotency-Key","in":"header"}],"responses":{"200":{"description":"The booking, cancelled or still cancelling","headers":{"Retry-After":{"schema":{"type":"string","description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again.","example":"5"},"required":false,"description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"The id is not a booking id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a bk_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no booking with this id in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such booking","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`cancellation_deadline_passed` at or past the cut-off, `booking_already_cancelled` when already cancelled, `cancellation_in_progress` while cancelling, or `booking_status_unexpected` for processing or failed. `idempotency_key_in_use` while a request with the same key is running.","content":{"application/json":{"example":{"error":{"code":"cancellation_deadline_passed","message":"The booking has passed its cancellation cut-off","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The Idempotency-Key was first sent with a different request","content":{"application/json":{"example":{"error":{"code":"idempotency_key_reused","message":"Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" was first sent with a different request. Use a new key for a new request.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/bookings":{"post":{"security":[{"bearerAuth":[]}],"tags":["Bookings"],"description":"Books the offer the shopper paid for, in the holder's name, with a guest per room. Mavio waits up to 25 seconds for the outcome and answers `201` with the booking as it stands, whatever its `status`. An error doesn't always mean nothing was booked: after a `500` or a lost answer, retry with the same `Idempotency-Key` and payment before starting another purchase. Set your client's timeout to at least 30 seconds. A booking still `processing` carries `Retry-After`: retrieve it then, and keep polling until it's `confirmed` or `failed`. It carries on if your connection drops.","operationId":"createBooking","summary":"Create a booking","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","example":"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14"},"required":false,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingRequest"}}}},"responses":{"201":{"description":"The booking, whatever its status","headers":{"Location":{"schema":{"type":"string","description":"Where to retrieve the booking.","example":"/v1/bookings/bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"Where to retrieve the booking."},"Retry-After":{"schema":{"type":"string","description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again.","example":"5"},"required":false,"description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"A field is invalid, or the guests are not one per quoted room. The payment stays unused, so send the fixed body with it","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Name one guest for each of the quote's 2 rooms, in the quote's order","param":"rooms"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no payment with this id in this mode","content":{"application/json":{"example":{"error":{"code":"payment_not_found","message":"No such payment","param":"paymentId"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`payment_unavailable` for a payment that was already used, which names the booking it made, or one that expired or was canceled: start a new payment. `idempotency_key_in_use` while a request with the same Idempotency-Key is still running.","content":{"application/json":{"example":{"error":{"code":"payment_unavailable","message":"The payment was already used by booking bk_031OeqUcl4UtGlNOdBpZCN. Retrieve that booking, or start a new payment to book again.","param":"paymentId"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The Idempotency-Key was first sent with a different request","content":{"application/json":{"example":{"error":{"code":"idempotency_key_reused","message":"Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" was first sent with a different request. Use a new key for a new request.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"security":[{"bearerAuth":[]}],"tags":["Bookings"],"description":"Lists your bookings in this mode, newest first, each as it is now. Page with `startingAfter` the last id of a page, or `endingBefore` the first. To catch every change, a hotel cancelling included, filter with `updated[gte]` and read every page.","operationId":"listBookings","summary":"List bookings","parameters":[{"schema":{"type":"string","format":"date-time","description":"Only bookings created at or after this time, in UTC.","example":"2026-11-01T00:00:00Z"},"required":false,"description":"Only bookings created at or after this time, in UTC.","name":"created[gte]","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Only bookings created before this time, in UTC.","example":"2026-12-01T00:00:00Z"},"required":false,"description":"Only bookings created before this time, in UTC.","name":"created[lt]","in":"query"},{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"A booking id from a page: returns the newer bookings just before it.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":false,"description":"A booking id from a page: returns the newer bookings just before it.","name":"endingBefore","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":10,"description":"How many bookings to return, from 1 to 100.","example":10},"required":false,"description":"How many bookings to return, from 1 to 100.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Only bookings you gave exactly this reference, matching case.","example":"ord_1234"},"required":false,"description":"Only bookings you gave exactly this reference, matching case.","name":"reference","in":"query"},{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"A booking id from a page: returns the older bookings just after it.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":false,"description":"A booking id from a page: returns the older bookings just after it.","name":"startingAfter","in":"query"},{"schema":{"type":"string","enum":["processing","confirmed","failed","cancelling","cancelled"],"description":"Only bookings in this status.","example":"confirmed"},"required":false,"description":"Only bookings in this status.","name":"status","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Only bookings that last changed at or after this time, in UTC, whatever their status or when they were created.","example":"2026-11-20T09:30:00Z"},"required":false,"description":"Only bookings that last changed at or after this time, in UTC, whatever their status or when they were created.","name":"updated[gte]","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Only bookings that last changed before this time, in UTC.","example":"2026-11-20T10:30:00Z"},"required":false,"description":"Only bookings that last changed before this time, in UTC.","name":"updated[lt]","in":"query"}],"responses":{"200":{"description":"A page of bookings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingList"}}}},"400":{"description":"A parameter is invalid, or a cursor names no booking of yours in this mode","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"No such booking","param":"startingAfter"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/bookings/{id}":{"get":{"security":[{"bearerAuth":[]}],"tags":["Bookings"],"description":"Retrieves a booking with what was sold and where it stands.","operationId":"getBooking","summary":"Retrieve a booking","parameters":[{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"The id of the booking to retrieve.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The id of the booking to retrieve.","in":"path","name":"id"}],"responses":{"200":{"description":"The booking","headers":{"Retry-After":{"schema":{"type":"string","description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again.","example":"5"},"required":false,"description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"The id is not a booking id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a bk_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no booking with this id in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such booking","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/balance":{"get":{"description":"Retrieves what Mavio owes you in this mode: your markup on confirmed bookings and your penalty share on cancelling and cancelled bookings, per currency. Amounts are upcoming through check-out and owed from the following day in UTC. Cancellations count only when their penalty share is positive; refund status does not affect the balance.","operationId":"getBalance","security":[{"bearerAuth":[]}],"summary":"Retrieve your balance","tags":["Balance"],"responses":{"200":{"description":"Your balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Balance"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid request"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/usage":{"get":{"description":"Retrieves how your partner used the API in this mode, one UTC day at a time: the requests its standard keys sent, per endpoint, with their errors, rate-limited requests and latency, and the bookings it created, along with the rate limits that apply.","operationId":"getUsage","security":[{"bearerAuth":[]}],"summary":"Retrieve your usage","tags":["Usage"],"parameters":[{"schema":{"type":"string","format":"date","description":"The first UTC day to count, as YYYY-MM-DD, at most 90 days before `to` counting both. 30 days up to `to` by default.","example":"2026-09-25"},"required":false,"description":"The first UTC day to count, as YYYY-MM-DD, at most 90 days before `to` counting both. 30 days up to `to` by default.","name":"from","in":"query"},{"schema":{"type":"string","format":"date","description":"The last UTC day to count, as YYYY-MM-DD, up to today. Today by default.","example":"2026-10-24"},"required":false,"description":"The last UTC day to count, as YYYY-MM-DD, up to today. Today by default.","name":"to","in":"query"}],"responses":{"200":{"description":"Your usage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be at most 90 days before to, counting both","param":"from"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"We couldn’t read your requests from our monitoring. Try again after Retry-After","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":30,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"usage_unavailable","message":"Your usage can’t be read right now. Try again after Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/bookings/{id}/fail_refund":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Fails a cancelled test booking’s pending or succeeded refund through the same notification intake as Adyen. `card_unavailable` and `refund_window_expired` make it `requires_action`; `disputed` makes it `failed`. Waits up to 25 seconds for the outcome and answers the booking as it stands. Set your client timeout to at least 30 seconds.","operationId":"failBookingRefund","summary":"Fail a booking’s refund","parameters":[{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"The test booking to change. It has to be in the status the helper names.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test booking to change. It has to be in the status the helper names.","in":"path","name":"id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailBookingRefundRequest"}}}},"responses":{"200":{"description":"The booking as it stands","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"The booking id or reason is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid refund failure reason","param":"reason"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test booking with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such booking","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The refund cannot be failed in its current status","content":{"application/json":{"example":{"error":{"code":"refund_status_unexpected","message":"This operation needs a cancelled booking with a pending or succeeded refund","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/listings/{id}/sell_out":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Makes your next test quotes for the listing answer `201` with no offers, as a sold-out stay does. It lasts an hour, or until you reset the listing, and only your test keys see it. Calling a helper again starts the hour over.","operationId":"sellOutListing","summary":"Sell out a listing","parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The listing whose test quotes to change. It has to be active.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"required":true,"description":"The listing whose test quotes to change. It has to be active.","in":"path","name":"id"}],"responses":{"200":{"description":"The listing's test state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTestState"}}}},"400":{"description":"The id is not a listing id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a lst_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No active listing has this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such listing","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/listings/{id}/outage":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Makes your next test quotes for the listing answer `503 supplier_unavailable` with `Retry-After`, as when no supplier can answer. It lasts an hour, or until you reset the listing, and only your test keys see it. Calling a helper again starts the hour over.","operationId":"startListingOutage","summary":"Start an outage on a listing","parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The listing whose test quotes to change. It has to be active.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"required":true,"description":"The listing whose test quotes to change. It has to be active.","in":"path","name":"id"}],"responses":{"200":{"description":"The listing's test state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTestState"}}}},"400":{"description":"The id is not a listing id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a lst_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No active listing has this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such listing","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/listings/{id}/reset":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Ends the scenario a listing helper set, so your test quotes for the listing price normally again.","operationId":"resetListing","summary":"Reset a listing","parameters":[{"schema":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The listing whose test quotes to change. It has to be active.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"required":true,"description":"The listing whose test quotes to change. It has to be active.","in":"path","name":"id"}],"responses":{"200":{"description":"The listing's test state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTestState"}}}},"400":{"description":"The id is not a listing id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a lst_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No active listing has this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such listing","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/quotes/{id}/expire":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Makes a test quote expire now, as its `expiresAt` passing would. Answers the quote, with `expiresAt` now.","operationId":"expireQuote","summary":"Expire a quote","parameters":[{"schema":{"type":"string","pattern":"^qt_[0-9A-Za-z]{22}$","description":"The test quote to change.","example":"qt_031OeqUcl4UtGlNOdBpZCM"},"required":true,"description":"The test quote to change.","in":"path","name":"id"}],"responses":{"200":{"description":"The quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"The id is not a quote id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a qt_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test quote with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such quote","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The quote has already expired","content":{"application/json":{"example":{"error":{"code":"quote_expired","message":"The quote has already expired","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/offers/{id}/change_price":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"operationId":"changeOfferPrice","summary":"Change an offer's price","description":"Makes the offer's price move by `percent` of the supplier's price when it's re-checked, so `POST /v1/payments` answers `409 offer_changed` with a new quote. With `at: \"booking\"`, the payment goes through and the shopper pays, then the booking ends `failed` with `offer_changed`, telling you to start a new payment for the offer, and the hold on the card is released. A new payment for it then answers `409 offer_changed` with the new quote. An offer holds one scenario, which another offer helper replaces, and only your test keys see it. Answers the offer's quote, which is unchanged.","parameters":[{"schema":{"type":"string","pattern":"^off_[0-9A-Za-z]{22}$","description":"The test offer to change. Its quote has to be open.","example":"off_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test offer to change. Its quote has to be open.","in":"path","name":"id"}],"requestBody":{"description":"Optional. Leave it out with no `Content-Type`, or send `{}`: a JSON `Content-Type` with an empty body is malformed JSON and gets `400 invalid_request`.","required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePriceRequest"}}}},"responses":{"200":{"description":"The quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"The id is not an offer id, or `percent` is out of range","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Too big: expected number to be <=50","param":"percent"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test offer with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such offer","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The offer's quote has expired","content":{"application/json":{"example":{"error":{"code":"quote_expired","message":"The offer's quote has expired","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/offers/{id}/sell_out":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"operationId":"sellOutOffer","summary":"Sell out an offer","description":"Makes the offer's room gone when it's re-checked, as when the stay sells out after the quote, so `POST /v1/payments` answers `409 offer_unavailable`. With `at: \"booking\"`, the payment goes through and the shopper pays, then the booking ends `failed` with `offer_unavailable`, and the hold on the card is released. An offer holds one scenario, which another offer helper replaces, and only your test keys see it. Answers the offer's quote, which is unchanged.","parameters":[{"schema":{"type":"string","pattern":"^off_[0-9A-Za-z]{22}$","description":"The test offer to change. Its quote has to be open.","example":"off_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test offer to change. Its quote has to be open.","in":"path","name":"id"}],"requestBody":{"description":"Optional. Leave it out with no `Content-Type`, or send `{}`: a JSON `Content-Type` with an empty body is malformed JSON and gets `400 invalid_request`.","required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellOutOfferRequest"}}}},"responses":{"200":{"description":"The quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"The id is not an offer id, or `at` is neither `payment` nor `booking`","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid option: expected one of \"payment\"|\"booking\"","param":"at"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test offer with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such offer","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The offer's quote has expired","content":{"application/json":{"example":{"error":{"code":"quote_expired","message":"The offer's quote has expired","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/offers/{id}/delay_confirmation":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"operationId":"delayOfferConfirmation","summary":"Delay an offer's confirmation","description":"Makes a booking of the offer stay `processing`, as when the hotel is slow to confirm it, until you end it with `bookings/{id}/confirm` or `bookings/{id}/fail`. Otherwise Mavio keeps checking with the supplier for 30 minutes, then, as when the hotel never confirms it, fails it with `confirmation_timeout` where the supplier shows no booking, or leaves it `processing` for Mavio staff to settle where the supplier still shows it on its way. An offer holds one scenario, which another offer helper replaces, and only your test keys see it. Answers the offer's quote, which is unchanged.","parameters":[{"schema":{"type":"string","pattern":"^off_[0-9A-Za-z]{22}$","description":"The test offer to change. Its quote has to be open.","example":"off_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test offer to change. Its quote has to be open.","in":"path","name":"id"}],"responses":{"200":{"description":"The quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"The id is not an offer id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a off_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test offer with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such offer","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The offer's quote has expired","content":{"application/json":{"example":{"error":{"code":"quote_expired","message":"The offer's quote has expired","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/offers/{id}/fail_booking":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"operationId":"failOfferBooking","summary":"Fail an offer's booking","description":"Makes a booking of the offer fail with `supplier_refused`, as when the hotel refuses it, and releases the hold on the card. An offer holds one scenario, which another offer helper replaces, and only your test keys see it. Answers the offer's quote, which is unchanged.","parameters":[{"schema":{"type":"string","pattern":"^off_[0-9A-Za-z]{22}$","description":"The test offer to change. Its quote has to be open.","example":"off_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test offer to change. Its quote has to be open.","in":"path","name":"id"}],"responses":{"200":{"description":"The quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"The id is not an offer id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a off_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test offer with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such offer","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The offer's quote has expired","content":{"application/json":{"example":{"error":{"code":"quote_expired","message":"The offer's quote has expired","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/payments/{id}/authorize":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Pays for a pending test payment with Adyen's test card, as your shopper paying in Adyen's component would, so your backend tests and CI can pay without a browser. `outcome: \"authorized\"`, the default, has the card held. `declined` has it refused, which leaves the payment `pending`, so you can try again, while a booking made with it fails `payment_declined` once Mavio has waited 30 minutes for the payment. Answers the payment as it stands: it turns `authorized` moments later, once Adyen confirms the hold to Mavio, as a shopper's payment does, so poll `GET /v1/payments/{id}`, or just book with it.","operationId":"authorizePayment","summary":"Authorize a payment","parameters":[{"schema":{"type":"string","pattern":"^pay_[0-9A-Za-z]{22}$","description":"The test payment to change. It has to be in the status the helper names.","example":"pay_031OeqUcl4UtGlNOdBpZCP"},"required":true,"description":"The test payment to change. It has to be in the status the helper names.","in":"path","name":"id"}],"requestBody":{"description":"Optional. Leave it out with no `Content-Type`, or send `{}`: a JSON `Content-Type` with an empty body is malformed JSON and gets `400 invalid_request`.","required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizePaymentRequest"}}}},"responses":{"200":{"description":"The payment, as it stands","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"description":"The id is not a payment id, or `outcome` is neither `authorized` nor `declined`","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a pay_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test payment with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such payment","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The payment is no longer `pending`","content":{"application/json":{"example":{"error":{"code":"payment_status_unexpected","message":"The payment is authorized, and this helper needs it pending","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/payments/{id}/fail_capture":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Makes a captured test payment fail for good. Answers the payment as it stands; poll `GET /v1/payments/{id}` until it shows `capture_failed`. A cancelled booking’s unsent refund ends `canceled` with `not_charged`. A confirmed booking stays confirmed.","operationId":"failPaymentCapture","summary":"Fail a payment capture","parameters":[{"schema":{"type":"string","pattern":"^pay_[0-9A-Za-z]{22}$","description":"The test payment to change. It has to be in the status the helper names.","example":"pay_031OeqUcl4UtGlNOdBpZCP"},"required":true,"description":"The test payment to change. It has to be in the status the helper names.","in":"path","name":"id"}],"responses":{"200":{"description":"The payment, as it stands","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"description":"The id is not a payment id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a pay_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test payment with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such payment","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The payment is not `captured`","content":{"application/json":{"example":{"error":{"code":"payment_status_unexpected","message":"The payment is authorized, and this helper needs it captured","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/bookings/{id}/confirm":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Has the hotel confirm a `processing` test booking, as one slow to confirm finally does, such as after `delay_confirmation`. The booking turns `confirmed`, and Mavio captures the hold on the card. Mavio checks with the supplier at once, as it would in live, then waits up to 25 seconds for the outcome, as `POST /v1/bookings` does, and answers the booking as it stands: set your client's timeout to at least 30 seconds. A booking still `processing` carries `Retry-After`.","operationId":"confirmBooking","summary":"Confirm a booking","parameters":[{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"The test booking to change. It has to be in the status the helper names.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test booking to change. It has to be in the status the helper names.","in":"path","name":"id"}],"responses":{"200":{"description":"The booking, as it stands","headers":{"Retry-After":{"schema":{"type":"string","description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again.","example":"5"},"required":false,"description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"The id is not a booking id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a bk_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test booking with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such booking","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`booking_not_at_supplier` when the booking is `processing` but its supplier holds no pending booking to end, such as before the payment is authorized, or after `fail`. `booking_status_unexpected` when the booking is no longer `processing`, naming both statuses, such as `The booking is confirmed, and this operation needs it processing`","content":{"application/json":{"example":{"error":{"code":"booking_not_at_supplier","message":"The booking is processing, but its supplier holds no pending booking for this helper to end","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/bookings/{id}/fail":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Has the hotel fail a `processing` test booking, which ends as its supplier shows a failure, so handle both codes as you must in live. Where the supplier refuses it, the booking fails `supplier_refused`. Where the supplier just holds no booking, it stays `processing` until Mavio has checked for 30 minutes since booking it, then fails `confirmation_timeout`, at once when they've passed. Either way Mavio releases the hold on the card. Mavio checks with the supplier at once, as it would in live, then waits up to 25 seconds for the outcome, as `POST /v1/bookings` does, and answers the booking as it stands: set your client's timeout to at least 30 seconds. A booking still `processing` carries `Retry-After`.","operationId":"failBooking","summary":"Fail a booking","parameters":[{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"The test booking to change. It has to be in the status the helper names.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test booking to change. It has to be in the status the helper names.","in":"path","name":"id"}],"responses":{"200":{"description":"The booking, as it stands","headers":{"Retry-After":{"schema":{"type":"string","description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again.","example":"5"},"required":false,"description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"The id is not a booking id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a bk_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test booking with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such booking","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`booking_not_at_supplier` when the booking is `processing` but its supplier holds no pending booking to end, such as before the payment is authorized, or after `fail`. `booking_status_unexpected` when the booking is no longer `processing`, naming both statuses, such as `The booking is confirmed, and this operation needs it processing`","content":{"application/json":{"example":{"error":{"code":"booking_not_at_supplier","message":"The booking is processing, but its supplier holds no pending booking for this helper to end","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/bookings/{id}/cancel_by_supplier":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Has the hotel cancel a `confirmed` test booking, as when it can't honour it. The booking turns `cancelled`, with `cancellation.cancelledBy` `supplier`, no penalty and a full refund. With `at: \"cancel\"`, it stays confirmed until your next cancel or the hourly look-up discovers the supplier's cancellation. Mavio checks with the supplier at once, then waits up to 25 seconds for the booking to show it, as `POST /v1/bookings` waits for an outcome, and answers the booking as it stands: set your client's timeout to at least 30 seconds. In live, Mavio finds a hotel's cancellation or code when it checks a confirmed booking with its supplier, every hour until check-in day has ended everywhere, so notice it by listing bookings with `updated[gte]`.","operationId":"cancelBookingBySupplier","summary":"Cancel a booking as its hotel","parameters":[{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"The test booking to change. It has to be in the status the helper names.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test booking to change. It has to be in the status the helper names.","in":"path","name":"id"}],"requestBody":{"description":"Optional. Leave it out with no `Content-Type`, or send `{}`: a JSON `Content-Type` with an empty body is malformed JSON and gets `400 invalid_request`.","required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBookingBySupplierRequest"}}}},"responses":{"200":{"description":"The booking, as it stands","headers":{"Retry-After":{"schema":{"type":"string","description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again.","example":"5"},"required":false,"description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"The id is not a booking id, or `at` is neither `now` nor `cancel`","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid option: expected one of \"now\"|\"cancel\"","param":"at"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test booking with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such booking","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The booking is not `confirmed`, naming both statuses","content":{"application/json":{"example":{"error":{"code":"booking_status_unexpected","message":"The booking is cancelled, and this operation needs it confirmed","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/bookings/{id}/delay_cancellation":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Makes the supplier hold cancellation for at least 30 seconds after the first cancel attempt. Your next cancel waits normally for up to 25 seconds and answers `cancelling` with `Retry-After`; another cancel while it is unfinished answers `409 cancellation_in_progress`. Mavio retries automatically, and the first retry after the hold ends the booking `cancelled` with the policy’s penalty and refund. Answers the unchanged confirmed booking.","operationId":"delayBookingCancellation","summary":"Delay a booking cancellation","parameters":[{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"The test booking to change. It has to be in the status the helper names.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test booking to change. It has to be in the status the helper names.","in":"path","name":"id"}],"responses":{"200":{"description":"The booking, as it stands","headers":{"Retry-After":{"schema":{"type":"string","description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again.","example":"5"},"required":false,"description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"The id is not a booking id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a bk_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test booking with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such booking","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The booking is not `confirmed`, naming both statuses","content":{"application/json":{"example":{"error":{"code":"booking_status_unexpected","message":"The booking is cancelled, and this operation needs it confirmed","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test_helpers/bookings/{id}/update_hotel_confirmation_code":{"post":{"security":[{"bearerAuth":[]}],"tags":["Test helpers"],"description":"Has the hotel send its confirmation code for a `confirmed` test booking now, or a new one in place of the last. It shows on every room as `hotelConfirmationCode`. Without this helper, a test booking gets a code by itself about an hour after it's confirmed, as a hotel sends one. Mavio checks with the supplier at once, then waits up to 25 seconds for the booking to show it, as `POST /v1/bookings` waits for an outcome, and answers the booking as it stands: set your client's timeout to at least 30 seconds. In live, Mavio finds a hotel's cancellation or code when it checks a confirmed booking with its supplier, every hour until check-in day has ended everywhere, so notice it by listing bookings with `updated[gte]`.","operationId":"updateBookingHotelConfirmationCode","summary":"Update a booking's hotel confirmation code","parameters":[{"schema":{"type":"string","pattern":"^bk_[0-9A-Za-z]{22}$","description":"The test booking to change. It has to be in the status the helper names.","example":"bk_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The test booking to change. It has to be in the status the helper names.","in":"path","name":"id"}],"requestBody":{"description":"Optional. Leave it out with no `Content-Type`, or send `{}`: a JSON `Content-Type` with an empty body is malformed JSON and gets `400 invalid_request`.","required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateHotelConfirmationCodeRequest"}}}},"responses":{"200":{"description":"The booking, as it stands","headers":{"Retry-After":{"schema":{"type":"string","description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again.","example":"5"},"required":false,"description":"While the booking is `processing` or `cancelling`: how many seconds to wait before retrieving it again."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"The id is not a booking id, or `code` is empty or too long","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Too big: expected string to have <=100 characters","param":"code"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a live key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Test helpers only work with test keys"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test booking with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such booking","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The booking is not `confirmed`, naming both statuses","content":{"application/json":{"example":{"error":{"code":"booking_status_unexpected","message":"The booking is cancelled, and this operation needs it confirmed","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/partner":{"get":{"security":[{"bearerAuth":[]}],"tags":["Partner"],"description":"Retrieves the partner your API key belongs to.","operationId":"getPartner","summary":"Retrieve your partner","responses":{"200":{"description":"Your partner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid request"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["Partner"],"description":"Updates your partner. A new default markup applies from your next quote, in test and live mode alike, and never changes a quote you already have.","operationId":"updatePartner","summary":"Update your partner","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","example":"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14"},"required":false,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePartner"}}}},"responses":{"200":{"description":"Your partner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"400":{"description":"The default markup is missing, out of range or has more than 2 decimals","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Too big: expected number to be <=100","param":"defaultMarkupPercent"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with the same Idempotency-Key is still running, or was cut off before it answered","content":{"application/json":{"example":{"error":{"code":"idempotency_key_in_use","message":"A request with Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" is still running. Retry once it has answered, or, if this lasts longer than the request takes, send a new key.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The Idempotency-Key was first sent with a different request","content":{"application/json":{"example":{"error":{"code":"idempotency_key_reused","message":"Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" was first sent with a different request. Use a new key for a new request.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pricing_rules":{"get":{"security":[{"bearerAuth":[]}],"tags":["Pricing rules"],"description":"Lists the current listing and chain markup rules for your partner, across test and live mode. Removed targets are omitted.","operationId":"listPricingRules","summary":"List pricing rules","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":30,"description":"Rules per page, from 1 to 100.","example":30},"required":false,"description":"Rules per page, from 1 to 100.","name":"limit","in":"query"},{"schema":{"type":"string","pattern":"^prl_[0-9A-Za-z]{22}$","description":"The previous response’s nextPage. Leave out for the first page.","example":"prl_031OeqUcl4UtGlNOdBpZCM"},"required":false,"description":"The previous response’s nextPage. Leave out for the first page.","name":"page","in":"query"}],"responses":{"200":{"description":"Your pricing rules","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingRuleList"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid request"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["Pricing rules"],"description":"Sets a fixed markup for one listing or chain, replacing the previous rule for that target. Send null to remove it. Precedence across every supplier: request override, listing rule, chain rule, default. Applies to new quotes and dated searches in both modes; saved quotes keep their pricing.","operationId":"savePricingRule","summary":"Set or remove a pricing rule","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","example":"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14"},"required":false,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"markupPercent":{"type":"number","nullable":true,"minimum":0,"maximum":100,"description":"A fixed markup from 0 to 100 with at most 2 decimals. Null removes this target’s rule, restoring the next matching layer.","example":12.5},"target":{"oneOf":[{"type":"object","properties":{"listingId":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The merged Mavio listing, across all its suppliers.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"type":{"type":"string","enum":["listing"],"description":"One listing.","example":"listing"}},"required":["listingId","type"],"additionalProperties":false},{"type":"object","properties":{"chainCode":{"type":"string","minLength":1,"maxLength":100,"description":"A chain code from GET /v1/chains; brand codes are not accepted.","example":"hilton"},"type":{"type":"string","enum":["chain"],"description":"All listings with this normalized chain code.","example":"chain"}},"required":["chainCode","type"],"additionalProperties":false}],"description":"The listing or chain this rule applies to.","example":{"chainCode":"hilton","type":"chain"}}},"required":["markupPercent","target"],"additionalProperties":false}}}},"responses":{"200":{"description":"The saved rule version, including a removal with null markup","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingRule"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid request"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The listing is missing or unavailable","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such listing","param":"listingId"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with the same Idempotency-Key is still running, or was cut off before it answered","content":{"application/json":{"example":{"error":{"code":"idempotency_key_in_use","message":"A request with Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" is still running. Retry once it has answered, or, if this lasts longer than the request takes, send a new key.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The Idempotency-Key was first sent with a different request","content":{"application/json":{"example":{"error":{"code":"idempotency_key_reused","message":"Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" was first sent with a different request. Use a new key for a new request.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pricing_rules/batch":{"post":{"security":[{"bearerAuth":[]}],"tags":["Pricing rules"],"description":"Sets one fixed markup for 1 to 100 distinct listings or chains at once, replacing each target's previous rule. Send null to remove them. Every target is checked first, so the whole batch is saved or, on any error, none of it.","operationId":"savePricingRules","summary":"Set or remove pricing rules in bulk","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","example":"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14"},"required":false,"description":"Makes the request safe to retry. Send a new value of up to 255 characters, such as a UUID, for each request you mean, and the same value with each of its retries. For at least 24 hours, a retry with the same body answers with the first response, status and body alike, and does nothing again. Only a success is kept: after an error, a retry runs again. Keys are per mode, so a test key and a live key never share one.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"markupPercent":{"type":"number","nullable":true,"minimum":0,"maximum":100,"description":"One fixed markup for every target, from 0 to 100 with at most 2 decimals. Null removes their rules.","example":12.5},"targets":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"listingId":{"type":"string","pattern":"^lst_[0-9A-Za-z]{22}$","description":"The merged Mavio listing, across all its suppliers.","example":"lst_031OeqUcl4UtGlNOdBpZCK"},"type":{"type":"string","enum":["listing"],"description":"One listing.","example":"listing"}},"required":["listingId","type"],"additionalProperties":false},{"type":"object","properties":{"chainCode":{"type":"string","minLength":1,"maxLength":100,"description":"A chain code from GET /v1/chains; brand codes are not accepted.","example":"hilton"},"type":{"type":"string","enum":["chain"],"description":"All listings with this normalized chain code.","example":"chain"}},"required":["chainCode","type"],"additionalProperties":false}],"description":"The listing or chain this rule applies to.","example":{"chainCode":"hilton","type":"chain"}},"minItems":1,"maxItems":100,"description":"From 1 to 100 distinct listings or chains.","example":[{"chainCode":"hilton","type":"chain"}]}},"required":["markupPercent","targets"],"additionalProperties":false}}}},"responses":{"200":{"description":"The saved rule versions, in the order of the targets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedPricingRules"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid request"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"A listing is missing or unavailable","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such listing","param":"targets.0.listingId"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with the same Idempotency-Key is still running, or was cut off before it answered","content":{"application/json":{"example":{"error":{"code":"idempotency_key_in_use","message":"A request with Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" is still running. Retry once it has answered, or, if this lasts longer than the request takes, send a new key.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The Idempotency-Key was first sent with a different request","content":{"application/json":{"example":{"error":{"code":"idempotency_key_reused","message":"Idempotency-Key \"0b8f1c52-4a3e-4d1b-9f6e-2c7d5a9e3b14\" was first sent with a different request. Use a new key for a new request.","param":"Idempotency-Key"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/partner/test_origins":{"get":{"security":[{"bearerAuth":[]}],"tags":["Partner"],"description":"Lists the origins you added, from which Adyen's component takes test payments. `http://localhost`, `http://127.0.0.1`, `http://*.localhost` are always allowed for every partner, so they aren't listed.","operationId":"listTestOrigins","summary":"List test origins","responses":{"200":{"description":"Your test origins","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestOriginList"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid request"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["Partner"],"description":"Lets Adyen's component take test payments on one more of your sites, such as the checkout your team tests on. Only test payments: Mavio adds live origins with you when you go live. Every change is recorded with who made it. You can add 20.","operationId":"createTestOrigin","summary":"Add a test origin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestOrigin"}}}},"responses":{"201":{"description":"The origin you added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestOrigin"}}}},"400":{"description":"The origin isn't one Adyen takes for test payments, or is always allowed already","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"http://localhost is always allowed in test mode, for every partner","param":"origin"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`test_origin_exists` when you already added the origin. `test_origin_limit_reached` when you already have 20: remove one first.","content":{"application/json":{"example":{"error":{"code":"test_origin_exists","message":"You already added this origin","param":"origin"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/partner/test_origins/{id}":{"delete":{"security":[{"bearerAuth":[]}],"tags":["Partner"],"description":"Stops Adyen's component taking test payments on one of the origins you added. The always-allowed localhost origins can't be removed.","operationId":"deleteTestOrigin","summary":"Remove a test origin","parameters":[{"schema":{"type":"string","pattern":"^tor_[0-9A-Za-z]{22}$","description":"The test origin id","example":"tor_034k4ttIQ8IuYWaMbWx2ox"},"required":true,"description":"The test origin id","in":"path","name":"id"}],"responses":{"200":{"description":"The origin you removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestOrigin"}}}},"400":{"description":"The id is not a test origin id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a tor_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no test origin with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such test origin","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/api_keys":{"get":{"security":[{"bearerAuth":[]}],"tags":["API keys"],"description":"Lists your standard API keys, newest first, with the revoked ones. A key's secret is never listed: only its prefix.","operationId":"listApiKeys","summary":"List API keys","responses":{"200":{"description":"Your API keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyList"}}}},"400":{"description":"A parameter is invalid","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Invalid request"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["API keys"],"description":"Creates a standard test key. The response is the only time you see its secret: store it before you leave the page.","operationId":"createApiKey","summary":"Create an API key","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKey"}}}},"responses":{"201":{"description":"The new key, with its secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedApiKey"}}}},"400":{"description":"The name is missing or too long","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Too big: expected string to have <=60 characters","param":"name"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"You already have the most active keys a partner can have","content":{"application/json":{"example":{"error":{"code":"api_key_limit_reached","message":"Revoke a key first: a partner can have 20 active keys per mode"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/api_keys/{id}":{"delete":{"security":[{"bearerAuth":[]}],"tags":["API keys"],"description":"Revokes a key: requests made with it fail from now on. The key stays in your list, so you can see when it was revoked.","operationId":"revokeApiKey","summary":"Revoke an API key","parameters":[{"schema":{"type":"string","pattern":"^key_[0-9A-Za-z]{22}$","description":"The API key id","example":"key_034k4ttIQ8IuYWaMbWx2ox"},"required":true,"description":"The API key id","in":"path","name":"id"}],"responses":{"200":{"description":"The revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKey"}}}},"400":{"description":"The id is not an API key id","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Must be a key_ id followed by 22 letters or digits","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"You have no API key with this id","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such API key","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks":{"get":{"security":[{"bearerAuth":[]}],"tags":["Webhooks"],"description":"Lists your partner’s registrations in the key’s mode. Signing secrets are never returned.","operationId":"listWebhooks","summary":"List webhook endpoints","responses":{"200":{"description":"Your endpoints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookList"}}}},"400":{"description":"Invalid endpoint, event or delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use a reachable public HTTPS URL","param":"url"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The webhook or delivery does not belong to you in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such webhook or delivery","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A send currently owns this delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"This delivery is being sent. Retry once its current attempt finishes."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["Webhooks"],"description":"Registers a public HTTPS destination for selected events. Save the signing secret: it is only returned here. Booking changes are delivered automatically; synthetic tests are available for receiver setup.","operationId":"createWebhook","summary":"Register a webhook endpoint","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhook"}}}},"responses":{"201":{"description":"Endpoint and one-time signing secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedWebhook"}}}},"400":{"description":"Invalid endpoint, event or delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use a reachable public HTTPS URL","param":"url"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The webhook or delivery does not belong to you in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such webhook or delivery","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A send currently owns this delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"This delivery is being sent. Retry once its current attempt finishes."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}":{"get":{"security":[{"bearerAuth":[]}],"tags":["Webhooks"],"description":"Reads a registration in your partner and mode, without its signing secret.","operationId":"getWebhook","summary":"Get a webhook endpoint","parameters":[{"schema":{"type":"string","pattern":"^wh_[0-9A-Za-z]{22}$","description":"The webhook endpoint id.","example":"wh_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The webhook endpoint id.","in":"path","name":"id"}],"responses":{"200":{"description":"Endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Invalid endpoint, event or delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use a reachable public HTTPS URL","param":"url"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The webhook or delivery does not belong to you in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such webhook or delivery","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A send currently owns this delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"This delivery is being sent. Retry once its current attempt finishes."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["Webhooks"],"description":"Edits the destination, name, subscriptions or active state. Pending deliveries use the current URL and secret. Disabling an endpoint stops future deliveries; queued deliveries are abandoned when claimed.","operationId":"updateWebhook","summary":"Update a webhook endpoint","parameters":[{"schema":{"type":"string","pattern":"^wh_[0-9A-Za-z]{22}$","description":"The webhook endpoint id.","example":"wh_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The webhook endpoint id.","in":"path","name":"id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhook"}}}},"responses":{"200":{"description":"Updated endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Invalid endpoint, event or delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use a reachable public HTTPS URL","param":"url"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The webhook or delivery does not belong to you in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such webhook or delivery","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A send currently owns this delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"This delivery is being sent. Retry once its current attempt finishes."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/test":{"post":{"security":[{"bearerAuth":[]}],"tags":["Webhooks"],"description":"Queues clearly marked synthetic data through the real signing and retry path. The endpoint must be enabled and subscribed to the selected event.","operationId":"sendWebhookTest","summary":"Send a test event","parameters":[{"schema":{"type":"string","pattern":"^wh_[0-9A-Za-z]{22}$","description":"The webhook endpoint id.","example":"wh_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The webhook endpoint id.","in":"path","name":"id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendWebhookTest"}}}},"responses":{"202":{"description":"Queued test delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"400":{"description":"Invalid endpoint, event or delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use a reachable public HTTPS URL","param":"url"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The webhook or delivery does not belong to you in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such webhook or delivery","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A send currently owns this delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"This delivery is being sent. Retry once its current attempt finishes."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Test sends and replays share six requests per minute per partner and mode, including admin keys. Retry after Retry-After.","content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Test sends and replays are rate limited."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"security":[{"bearerAuth":[]}],"tags":["Webhooks"],"description":"Lists up to 50 deliveries, newest first, with the latest response and total attempt count.","operationId":"listWebhookDeliveries","summary":"List webhook deliveries","parameters":[{"schema":{"type":"string","pattern":"^wh_[0-9A-Za-z]{22}$","description":"The webhook endpoint id.","example":"wh_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The webhook endpoint id.","in":"path","name":"id"},{"schema":{"type":"string","pattern":"^whd_[0-9A-Za-z]{22}$","description":"Return deliveries older than this id. Pages contain up to 50 deliveries.","example":"whd_031OeqUcl4UtGlNOdBpZCN"},"required":false,"description":"Return deliveries older than this id. Pages contain up to 50 deliveries.","in":"query","name":"before"}],"responses":{"200":{"description":"Delivery history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryList"}}}},"400":{"description":"Invalid endpoint, event or delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use a reachable public HTTPS URL","param":"url"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The webhook or delivery does not belong to you in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such webhook or delivery","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A send currently owns this delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"This delivery is being sent. Retry once its current attempt finishes."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/deliveries/{deliveryId}":{"get":{"security":[{"bearerAuth":[]}],"tags":["Webhooks"],"description":"Returns the immutable event payload and latest delivery result.","operationId":"getWebhookDelivery","summary":"Inspect a webhook delivery","parameters":[{"schema":{"type":"string","pattern":"^wh_[0-9A-Za-z]{22}$","description":"The webhook endpoint id.","example":"wh_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The webhook endpoint id.","in":"path","name":"id"},{"schema":{"type":"string","pattern":"^whd_[0-9A-Za-z]{22}$","description":"The delivery id.","example":"whd_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The delivery id.","in":"path","name":"deliveryId"}],"responses":{"200":{"description":"Delivery and payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryDetail"}}}},"400":{"description":"Invalid endpoint, event or delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use a reachable public HTTPS URL","param":"url"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The webhook or delivery does not belong to you in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such webhook or delivery","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A send currently owns this delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"This delivery is being sent. Retry once its current attempt finishes."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/deliveries/{deliveryId}/replay":{"post":{"security":[{"bearerAuth":[]}],"tags":["Webhooks"],"description":"Queues the same event id and payload with a fresh signature on the next attempt. Attempt counts are retained. Receivers must deduplicate by event id; delivery order is not guaranteed.","operationId":"replayWebhookDelivery","summary":"Replay a webhook delivery","parameters":[{"schema":{"type":"string","pattern":"^wh_[0-9A-Za-z]{22}$","description":"The webhook endpoint id.","example":"wh_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The webhook endpoint id.","in":"path","name":"id"},{"schema":{"type":"string","pattern":"^whd_[0-9A-Za-z]{22}$","description":"The delivery id.","example":"whd_031OeqUcl4UtGlNOdBpZCN"},"required":true,"description":"The delivery id.","in":"path","name":"deliveryId"}],"responses":{"202":{"description":"Queued replay","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"400":{"description":"Invalid endpoint, event or delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use a reachable public HTTPS URL","param":"url"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key is a standard key","content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"Only an admin key can do this. Sign in to the app to get one."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The webhook or delivery does not belong to you in this mode","content":{"application/json":{"example":{"error":{"code":"resource_missing","message":"No such webhook or delivery","param":"id"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A send currently owns this delivery","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"This delivery is being sent. Retry once its current attempt finishes."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The body is in another media type than JSON","content":{"application/json":{"example":{"error":{"code":"unsupported_media_type","message":"Send the request body as JSON, with Content-Type: application/json"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Test sends and replays share six requests per minute per partner and mode, including admin keys. Retry after Retry-After.","content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Test sends and replays are rate limited."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/events":{"get":{"description":"Recovers committed booking changes for your partner and key mode, oldest first in transaction order. Pass nextCursor as after until caught up, then poll with that cursor. A long-running transaction may delay visibility. Synthetic sends are excluded. Retrieve GET /v1/bookings/{id} for the current booking; events contain only its reference. Events are retained without automatic deletion in v1.","operationId":"listEvents","security":[{"bearerAuth":[]}],"summary":"List booking events","tags":["Events"],"parameters":[{"schema":{"type":"string","description":"Resume after the previous page, including an empty page.","example":"WyIwIiwiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIl0"},"required":false,"description":"Resume after the previous page, including an empty page.","name":"after","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":50,"description":"Maximum events per page.","example":50},"required":false,"description":"Maximum events per page.","name":"limit","in":"query"}],"responses":{"200":{"description":"Committed events and recovery cursor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"}}}},"400":{"description":"Invalid cursor or page size","content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"Use the nextCursor returned by the events feed","param":"after"}},"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, unknown, revoked or expired","content":{"application/json":{"example":{"error":{"code":"api_key_missing","message":"Send your API key in the Authorization header: Bearer sk_test_..."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Your partner sent too many requests in this mode this second, or your network too many keys that match none this minute","headers":{"RateLimit-Limit":{"description":"Requests your partner can make per second in this mode","schema":{"example":20,"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left this second","schema":{"example":0,"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the count starts over","schema":{"example":1,"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"example":1,"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Your partner can make 20 requests a second in each mode with its standard keys, and as many with its admin keys. Retry after the seconds in Retry-After."}},"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something went wrong on our side","content":{"application/json":{"example":{"error":{"code":"internal_error","message":"Something went wrong on our side"}},"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}