OTA XML gateway

Broker systems and channel managers that already speak OpenTravel 2003/05 can connect without touching JSON. One endpoint, dispatched on the message root, with the same key, the same live inventory and the same charge engine as the JSON Partner API. Nothing is a separate feed: a car the desk has just handed over is gone from the next response.

Endpoint and credentials

POST https://keynetic.online/api/ota/v1
Content-Type: application/xml

Send the key the operator issued you as POS/Source/RequestorID @MessagePassword. An X-Api-Key header works too, which is easier for a smoke test. Every response is HTTP 200 with the matching …RS root, except transport-level failures; business refusals come back as Errors/Error, which is what most broker stacks expect.

EchoToken is returned as sent. Rate limit: 240 requests per minute per key, shared with the JSON API, answering 429 with Retry-After.

MessageStepWhat it does
OTA_PingRQConnectivityEchoes your text back. Credentials are still checked.
OTA_VehAvailRateRQShopAvailability and full charges per class for one rental window.
OTA_VehResRQBookCreates a confirmed reservation and returns both confirmation numbers.
OTA_VehRetResRQRetrieveCurrent state of a reservation by either confirmation number.
OTA_VehModifyRQModifyReprices and applies a change, or quotes it without saving.
OTA_VehCancelRQCancelCancels, or quotes the cancellation, depending on CancelType.

Times, stations and classes

  • Datetimes without an offset are the station's local wall clock. Responses echo them the way you sent them, with your own CodeContext on the location codes.
  • Location codes are matched without regard to case, and the operator can register the codes you already use (IATA code, your station id) against each station.
  • Vehicle classes are accepted as the operator's class code or the ACRISS code. Responses carry VehType @VehicleCategory and VehClass @Size derived from the ACRISS code.
  • Bookings close a set time before pickup (2 hours unless the operator changes it), pickups and returns outside opening hours are refused, and one-way rentals can be switched off per station.

Charges

RentalRate/VehicleCharges carries the base (Purpose 1, one Calculation per day, week or month period) and the fuel policy (Purpose 116). PricedEquips carries equipment, Fees the mandatory fees (2 one-way, 5 airport, 13 young driver, 18 delivery) and VehAvailInfo/PricedCoverages the covers with their Deductible.

Every charge states IncludedInRate, IncludedInEstTotalInd and its TaxAmounts. TotalCharge @RateTotalAmount is the base alone; @EstimatedTotalAmount is everything included plus tax, and it is the amount the booking stores.

Sold-out classes are listed and priced with VehAvail @Status="Unavailable", so you can show them greyed out rather than dropping them from the results.

POSThttps://keynetic.online/api/ota/v1

Shop: availability and charges for one window.

curl -X POST -H "Content-Type: application/xml" \
  https://keynetic.online/api/ota/v1 -d '<?xml version="1.0"?>
<OTA_VehAvailRateRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="1.0">
  <POS><Source>
    <RequestorID Type="22" ID="your-agency" MessagePassword="kpk_live_…"/>
  </Source></POS>
  <VehAvailRQCore Status="Available">
    <VehRentalCore PickUpDateTime="2026-08-01T10:00:00"
                   ReturnDateTime="2026-08-05T10:00:00">
      <PickUpLocation LocationCode="AUA" CodeContext="IATA"/>
      <ReturnLocation LocationCode="AUA" CodeContext="IATA"/>
    </VehRentalCore>
    <DriverType Age="31"/>
    <SpecialEquipPrefs><SpecialEquipPref EquipType="8" Quantity="1"/></SpecialEquipPrefs>
  </VehAvailRQCore>
  <VehAvailRQInfo>
    <CoveragePrefs><CoveragePref Code="SCDW" PreferLevel="Preferred"/></CoveragePrefs>
  </VehAvailRQInfo>
</OTA_VehAvailRateRQ>'
POSThttps://keynetic.online/api/ota/v1 (OTA_VehResRQ)

Book. The customer goes under Customer/Primary (PersonName, Email, Telephone), the class under VehPref @Code, and optionally SpecialEquipPrefs, CoveragePrefs and DriverType @Age (or Primary @BirthDate). Your reference goes in VehResRQInfo/RentalPaymentPref/Voucher @Identifier or UniqueID Type="16", and it is also the idempotency key: the same reference twice returns the original reservation instead of a duplicate.

The response returns the Keynetic confirmation as ConfID Type="14" and yours as Type="16". Retrieve, modify and cancel accept either as UniqueID; OTA_VehRetResRQ returns the status in VehReservation @ReservationStatus.

POSThttps://keynetic.online/api/ota/v1 (OTA_VehModifyRQ)

Modify restates the reservation. ModifyType Modify, Book or Commit applies the change; Quote, VerifyPrice or Initiate prices it without saving (ModifyStatus="Pending"); Cancel cancels and Ignore ends the dialogue (ModifyStatus="Ignored").

The rental core and class are taken as sent. Equipment, covers and the customer are replaced only when their element is present, so an empty SpecialEquipPrefs removes the equipment and leaving it out keeps it. The response is the complete repriced VehReservation. When a change is refused the reservation is left exactly as it was.

POSThttps://keynetic.online/api/ota/v1 (OTA_VehCancelRQ)

CancelType Quote, Initiate or Hold returns CancelStatus="Pending" and leaves the reservation in place; Ignore returns Ignored; anything else cancels. Cancelling an already-cancelled reservation succeeds.

Errors

Refusals come back as Errors/Error @Type @Code @ShortText. Type 3 is a business rule, 4 is credentials, 1 is us. Refusals with no dedicated code in the OpenTravel list (a change cut-off that has passed, a rental that has already started) are Type 3 with no @Code and the reason in @ShortText.

CodeMeaning
214Return time is outside the station opening hours.
219Inside the booking cut-off for that pickup time.
224One-way rentals are not allowed from the pickup station.
225One-way rentals are not allowed to the return station.
227Pickup time is outside the station opening hours.
229Pickup location not recognised.
233Return location not recognised.
234The requested class is not available for that window.
245Unknown confirmation number, or one that is not yours.
322No availability at that time.

Sample payloads

A complete request per message, ready to post at the sandbox. Replace the key and the dates.

Certification checklist

What we run before we call a connection live, and what we are happy to run against your test harness:

  1. Ping with a valid key, then with a revoked one (Type 4).
  2. Shop a window with availability, and one with none (322), and a sold-out class (listed as Unavailable, still priced).
  3. Shop and book the same window, and confirm the quoted EstimatedTotalAmount is what the reservation stores.
  4. Book twice with one reference, and confirm one reservation.
  5. Retrieve by our confirmation number and by yours.
  6. Modify the dates, the class, the equipment and the station, each first as a quote and then applied, and check the reprice.
  7. Modify into a sold-out class, and confirm nothing changed (234).
  8. Cancel, then cancel again, then retrieve.
  9. One-way where it is allowed and where it is not (224, 225).
  10. A pickup outside opening hours (227) and inside the cut-off (219).

Need a dialect we do not speak yet, or a field your certification requires? Email [email protected] with the message samples and we will map them.