# 获取 Offer

{% hint style="info" %}
遇到 API 接入问题时，可登录 [Eva](https://www.atriptech.com/) 寻求帮助。
{% endhint %}

这页用于查看独立 Get Offer 流程的接口级细节。

{% hint style="info" %}
以 OpenAPI 命名为准。

实现和文档中统一使用 `getOffers.do`。
{% endhint %}

### 主要 API

* `getOffers.do`

### 适用场景

* 不走标准搜索的报价查询
* 下单前实时验价
* 出票前最低价校验

### 最佳实践

* 已知目标行程时使用 `getOffers.do`
* 保存返回的 `OfferId` 用于后续下单
* 当乘客组合、航班选择或预期票价变化时刷新 Offer
* 后续标准路径使用 `order.do` 和 `pay.do`
* 只有在下单前确实需要附加服务时，才查询 `getLuggage.do` 或 `seatAvailability.do`

### 相关页面

* [获取 Offer](https://resources.atriptech.com/api-wen-dang/ji-cheng-zhi-nan/yu-ding-liu-cheng-gai-lan/huo-qu-offer)
* [创建订单](https://resources.atriptech.com/api-wen-dang/ji-cheng-zhi-nan/yu-ding-liu-cheng-gai-lan/chuang-jian-ding-dan)
* [支付与出票](https://resources.atriptech.com/api-wen-dang/ji-cheng-zhi-nan/yu-ding-liu-cheng-gai-lan/zhi-fu-yu-chu-piao)
* [搜索与预订](https://resources.atriptech.com/api-wen-dang/pai-zhang-yu-zhi-chi/faqs/atlas-api-search-and-book)

## Get Offer

> \*\*Dependency:\*\*\
> No preceding function needs to be called before Get Offer.\
> \
> \> - Compared to the Verify API, the GetOffer API does not rely on Search results and improves the success rate of price verify. Since using our GetOffer real-time search increases the L2B Ratio of our requesting carrier API, not all carriers support price verification via the GetOffer.\
> \> - Please contact your Key Account Manager if you want to use the GetOffer API. Atlas will review your workflow and if deemed aplicable, Atlas will provide further information and support you with the implementation of this API.\
> \
> \*\*Endpoint:\*\*\
> <https://sandbox.atriptech.com/getOffers.do>

```json
{"openapi":"3.0.1","info":{"title":"Default module","version":"1.0.0"},"tags":[{"name":"Shopping and Ticketing"}],"security":[],"paths":{"/getOffers.do":{"post":{"summary":"Get Offer","deprecated":false,"description":"**Dependency:**\nNo preceding function needs to be called before Get Offer.\n\n> - Compared to the Verify API, the GetOffer API does not rely on Search results and improves the success rate of price verify. Since using our GetOffer real-time search increases the L2B Ratio of our requesting carrier API, not all carriers support price verification via the GetOffer.\n> - Please contact your Key Account Manager if you want to use the GetOffer API. Atlas will review your workflow and if deemed aplicable, Atlas will provide further information and support you with the implementation of this API.\n\n**Endpoint:**\nhttps://sandbox.atriptech.com/getOffers.do","tags":["Shopping and Ticketing"],"parameters":[{"name":"Accept","in":"header","description":"","required":true,"schema":{"type":"string"}},{"name":"Content-Type","in":"header","description":"","required":true,"schema":{"type":"string"}},{"name":"Accept-Encoding","in":"header","description":"","required":true,"schema":{"type":"string"}},{"name":"x-atlas-client-id","in":"header","description":"","required":true,"schema":{"type":"string"}},{"name":"x-atlas-client-secret","in":"header","description":"","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"adults":{"type":"integer","description":"Number of adults","minimum":1,"maximum":9,"default":0},"children":{"type":"integer","description":"Number of children","default":0,"minimum":0,"maximum":9,"nullable":true},"infants":{"type":"integer","description":"Number of infants","default":0,"minimum":0,"maximum":9,"nullable":true},"outboundSegments":{"type":"array","items":{"$ref":"#/components/schemas/UniqueSellingSegment"},"description":"Arrange the outbound flight segments in the order of flight.","minItems":1},"inboundSegments":{"type":"array","items":{"properties":{"departureAirport":{"type":"string","minLength":3,"maxLength":3,"description":"出发机场的IATA三字码"},"arrivalAirport":{"type":"string","minLength":3,"maxLength":3,"description":"达到机场的IATA三字码"},"carrier":{"type":"string","minLength":2,"maxLength":2,"description":"marketing carrier的IATA二字码"},"flightNumber":{"type":"string","minLength":1,"description":"marketing flight number，不带航司代码前缀"},"departureDate":{"type":"string","format":"date","minLength":8,"maxLength":8,"pattern":"^[\\d]{8}$","description":"出发日期"}},"required":["departureAirport","arrivalAirport","carrier","flightNumber","departureDate"],"$ref":"#/components/schemas/UniqueSellingSegment"},"description":"Return flight segments are arranged in the order of flight. Optional, null or [] indicates one-way.","minItems":0,"uniqueItems":true,"nullable":true},"currency":{"type":"string","description":"Quotation currency, optional, default will be determined based on a certain strategy, such as the currency of the customer's pre deposit account","nullable":true},"residentCode":{"type":"string","description":"Resident discount code","nullable":true}},"required":["adults","outboundSegments"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"integer","enum":[0,116,112,9999],"description":"- 0: success\n- 116: airline error\n- 112: timed out\n- 9999: system error"},"msg":{"type":"string","description":"As an additional description of the response result. Especially when the interface reports an error (status ≠ 0), it is usually a human-readable error message.\n<br>\n**Note:** Do not use this field in any programming scenarios, such as judging whether the interface response is successful based on this field. You should always judge solely based on whether the status is equal to 0.","nullable":true},"data":{"type":"array","items":{"type":"object","properties":{"offer":{"type":"object","properties":{"offerID":{"type":"string","description":"The unique ID for this offer, globally unique.","maxLength":64},"offerToken":{"$ref":"#/components/schemas/OfferToken","nullable":true},"paxFares":{"type":"array","items":{"$ref":"#/components/schemas/PaxFare"},"description":"Contains ticket prices and taxes corresponding to each passenger type. If there are no elements for certain passenger types in the list, it means that the ticket is not currently being sold for that passenger type.","maxItems":3,"minItems":1},"penalties":{"type":"array","items":{"type":"object","properties":{"journeyRefIDs":{"type":"array","items":{"type":"string"},"description":"The reference to the journey ID indicates the journey to which the rule applies, which may include references to multiple journey IDs (such as round trips), indicating that multiple journeys are applicable to the rule."},"amount":{"type":"number","minimum":0,"description":"Pennalty amount. Unit: Yuan. Keep up to 2 decimal places."},"currency":{"type":"string","description":"Currency code corresponding to the pennalty amount, in capital letters. This currency may be different from the fare currency, depending on the airline."},"rule":{"description":"Calculation rules for the penalty","type":"object","properties":{"type":{"type":"string","enum":["Refund","Change"],"description":"Rule type: Refund or Change rule"},"paxTypes":{"type":"array","items":{"$ref":"#/components/schemas/PaxTypeEnums"},"description":"There may be multiple types of passengers to which this rule applies"},"levelType":{"$ref":"#/components/schemas/FareRuleLevelEnums","description":"- Full: If it is a refund, it means a full refund; If it is a rescheduling, it means free rescheduling\n- Partial: If it is a refund, it means a partial refund; If it is a rescheduling, it means that there will be a fee for reschedulin\n- None: If it is a refund, it means it cannot be refunded; If it is a rescheduling, it means that rescheduling is not possible\n"},"effectiveMinutes":{"type":"integer","description":"Form a time interval together with expiratorMinutes to indicate the time range within which the rule applies. This value serves as the starting point of the interval, measured in minutes. >= 0 represents the number of minutes before takeoff, <0 represents the number of minutes after takeoff."},"expirationMinutes":{"type":"integer","description":"Form a time interval together with expirationMinutes to indicate the time range within which the rule applies. This value serves as the end point of the interval, measured in minutes. >=0 represents the number of minutes before takeoff, <0 represents the number of minutes after takeoff."},"fixedAmount":{"type":"number","description":"Fixed deduction penalty. Unit: Yuan, with a maximum of 2 decimal places retained.","minimum":0},"airlineFee":{"type":"number","description":"Fixed deduction of airline handling fees. Unit: Yuan, with a maximum of 2 decimal places retained.","minimum":0},"currency":{"type":"string","description":"Currency of penalty and airline handling fees. This currency may be different from the fare currency, depending on the airline."},"percent":{"type":"number","minimum":0,"maximum":1,"description":"Penalty percentage"},"percentBase":{"type":"string","description":"Penalty percentage base.\n- fare+tax: The base for calculating the percentage is the total price including tax\n- fare: It indicates that the penalty percentage is based on the base price, excluding tax","enum":["fare+tax","fare"]}},"required":["type","paxTypes","levelType","effectiveMinutes","expirationMinutes","fixedAmount","airlineFee","currency","percent","percentBase"]}},"required":["journeyRefIDs","amount","currency","rule"]}},"services":{"type":"array","items":{"$ref":"#/components/schemas/Service"},"description":"Includes various free and chargeable services, including but not limited to: baggages, seat selection, meals, etc","nullable":true},"outboundJourney":{"properties":{"journeyID":{"type":"string","description":"行程唯一ID，在当前Offer的上下文内唯一。"},"segments":{"type":"array","items":{"$ref":"#/components/schemas/Segment"},"description":"航段按照飞行顺序展示"}},"required":["journeyID","segments"],"$ref":"#/components/schemas/Journey"},"inboundJourney":{"$ref":"#/components/schemas/Journey","nullable":true,"description":"Inbound journey, null means one-way."},"terms":{"type":"array","items":{"$ref":"#/components/schemas/Term"},"minItems":0,"uniqueItems":true,"nullable":true}},"required":["offerID","paxFares","penalties","outboundJourney"]},"serviceFee":{"$ref":"#/components/schemas/ServiceFee"},"bookingRequirement":{"$ref":"#/components/schemas/BookingRequirementSchema"},"supportedPaymentMethods":{"type":"array","items":{"$ref":"#/components/schemas/PaymentMethodEnums"},"description":"Supported payment methods. `null`or`[]`indicates that no payment methods are available."}},"required":["offer","serviceFee","bookingRequirement"]},"nullable":true}},"required":["status"]}}},"headers":{}}}}}},"components":{"schemas":{"UniqueSellingSegment":{"type":"object","properties":{"carrier":{"type":"string","minLength":2,"maxLength":2,"description":"IATA two letter code of marketing carrier, case sensitive"},"departureAirport":{"type":"string","minLength":3,"maxLength":3,"description":"IATA three letter code of departure airport which is case sensitive. If the value is illegal, the system will prompt that the airport does not exist."},"arrivalAirport":{"type":"string","minLength":3,"maxLength":3,"description":"IATA three letter code of arrival airport which is case sensitive. If the value is illegal, the system will prompt that the airport does not exist."},"flightNumber":{"type":"string","minLength":1,"description":"Marketing flight number. Attention: Without airline code prefix. It should be noted that some users may enter flight numbers with or without zero padding, for example, you may enter 06 (or 6), but the airline may be 6 (or 06). Anyway, we will return to the user based on the actual flight number provided by the airline, and the user may need to handle the differences between request and response."},"departureDate":{"type":"string","description":"Departure date. Format: yyyyMMdd. We do not require users to specify departure times, nor do we want to return segments based on specific departure time. Considering that the externally transmitted time may not match the actual flight segment time on the supplier's (airline's) side, this can lead to search results being lost. Therefore, we will return the results of all flight segments that took off within the specified date, and it will be up to the user to decide how to use them.","format":"date","minLength":8,"maxLength":8,"pattern":"^[\\d]{8}$"}},"required":["departureAirport","arrivalAirport","carrier","flightNumber","departureDate"]},"OfferToken":{"type":"string","description":"A encrypted string containing complete flight information and related quotation information, which can be used to uniquely identify a complete itinerary. This content can be freely distributed and stored by users, but modification is not allowed. At the same time, this content has a certain validity period (generally not exceeding 6 hours). One use case of Offer Token is when users search for flight tickets and quotes through Atlas' caching system, and then use this information to perform real-time price verification in subsequent steps to confirm if there are any price changes. At this point, Atlas will directly query real-time quotes from the airline, rather than through caching.","nullable":true},"PaxFare":{"type":"object","properties":{"paxType":{"$ref":"#/components/schemas/PaxTypeEnums","description":"Passenger type.\n- ADT: Representing adults\n- CHD: Representing children\n- INF: Representing a baby"},"price":{"$ref":"#/components/schemas/Price"}},"required":["paxType","price"]},"PaxTypeEnums":{"type":"string","enum":["ADT","CHD","INF"]},"Price":{"type":"object","properties":{"baseAmount":{"type":"number","description":"Basic price, excluding taxes. Unit: Yuan, with a maximum of 2 decimal places retained","minimum":0},"taxes":{"type":"number","description":"Total taxes. Unit: Yuan, with a maximum of 2 decimal places retained","minimum":0},"currency":{"type":"string","description":"Currency code, capitalized"}},"required":["baseAmount","taxes","currency"]},"FareRuleLevelEnums":{"type":"string","enum":["Full","Partial","None"]},"Service":{"type":"object","properties":{"serviceID":{"type":"string","description":"The unique ID of this service. Note: this ID is unique within the context of the current offer."},"segmentRefIDs":{"type":"array","items":{"type":"string"},"description":"The flight segment ID reference applicable to this service"},"type":{"$ref":"#/components/schemas/ServiceTypeEnums","description":"Service Type.\n- Baggage: represent a package\n- Seat: represent seat selection\n- Meal: represent meals"},"level":{"$ref":"#/components/schemas/ServiceLevelEnums","description":"Service fee level.\n- Free: Free service\n- Partial: Partially Free\n- Chargeable: Chargeable"},"paxTypes":{"type":"array","items":{"$ref":"#/components/schemas/PaxTypeEnums"},"description":"There may be multiple types of passengers for which this service is applicable. The items are one of:\n- ADT: Representing adults\n- CHD: Representing children\n- INF: Representing a baby"},"metadata":{"oneOf":[{"$ref":"#/components/schemas/BaggageAllowance","description":"When `type`=`Baggage`, this node will be displayed, indicating the specification restrictions of the package."}],"description":"Metadata representing different services, such as package weight, quantity, size, and other restrictions. Note: The content of this node may vary depending on the type of service. Users should read the content of the node according to different service types."}},"required":["serviceID","segmentRefIDs","type","level","paxTypes"]},"ServiceTypeEnums":{"type":"string","enum":["Baggage","Seat","Meal"]},"ServiceLevelEnums":{"type":"string","enum":["Free","Partial","Chargeable"]},"BaggageAllowance":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/BaggageTypeEnums","description":"Type of baggage"},"maximumWeight":{"type":"integer","description":"Maximum weight limit.\n- `0`: No Free baggage\n- `-1`: No limitation on weight\n- `>0`: Maximum weight","minimum":0},"maximumPiece":{"type":"integer","description":"Maximum quantity limit.\n- `0`: No limitation\n- `>0`: Maximum pieces","minimum":0},"maximumDimension":{"type":"string","description":"Maximum size limit. Note: This content is currently not guaranteed to be structured (parsed)","nullable":true}},"required":["type","maximumWeight","maximumPiece"]},"BaggageTypeEnums":{"type":"string","enum":["StandardCheckInBaggage","CabinBaggage","CabinBaggageOverheadLocker","CabinBaggageUnderSeat"]},"Segment":{"type":"object","properties":{"segmentID":{"type":"string","description":"Unique ID for the flight segment. Note: This ID is unique within the context of the current offer."},"carrier":{"type":"string","description":"Marketing carrier IATA two letter code, capitalized."},"flightNumber":{"type":"string","description":"Marketing flight number. Attention: Do not include airline code prefix."},"operatingCarrier":{"type":"string","description":"Operating carrier IATA two letter code, capitalized.","nullable":true},"operatingFlightNumber":{"type":"string","description":"Operating flight number. Attention: Do not include airline code prefix.","nullable":true},"duration":{"type":"integer","description":"Representing the flight duration of the entire flight segment, in minutes","nullable":true},"legs":{"type":"array","items":{"$ref":"#/components/schemas/Leg"},"description":"The physical flight information that constitutes the flight segment and the stopover information can be obtained from this. The number of elements=1 indicates that there is no stopping point. Display in flight order.","minItems":1,"uniqueItems":true},"fareFamily":{"type":"string","nullable":true},"RBD":{"type":"string","nullable":true},"cabinClass":{"description":"仓等","$ref":"#/components/schemas/CabinClassEnums","nullable":true},"seatsLeft":{"type":"integer","description":"the number of remaining seats"}},"required":["segmentID","carrier","flightNumber","legs"]},"Leg":{"type":"object","properties":{"departureAirport":{"type":"string","description":"IATA two letter code for the departure airport, in capital letters"},"departureTime":{"type":"string","description":"Takeoff time, format: yyyyMMddHHmm. For those taking off from transit points, the departure time may not be available; For those taking off from the starting point, this time will definitely be available.","format":"date-time","nullable":true},"departureTerminal":{"type":"string","description":"Departure terminal.","nullable":true},"arrivalAirport":{"type":"string","description":"IATA two letter code upon arrival at the airport, in capital letters"},"arrivalTime":{"type":"string","description":"Arrival time, format: yyyyMMddHHmm. For those arriving as transit points, the arrival time may not be available; For those who arrive as the endpoint, there will definitely be an arrival time.","nullable":true},"arrivalTerminal":{"type":"string","description":"Arriving terminal.","nullable":true},"aircraftType":{"type":"string","description":"Aircraft type code. According to the actual display of the airline.","nullable":true}},"required":["departureAirport","arrivalAirport"]},"CabinClassEnums":{"type":"string","enum":["Economy","Business","First","PremiumEconomy"]},"Journey":{"type":"object","properties":{"journeyID":{"type":"string","description":"Unique ID for the itinerary. Note: the ID is unique within the context of the current offer."},"segments":{"type":"array","items":{"$ref":"#/components/schemas/Segment"},"description":"Display flight segments in flight order"}},"required":["journeyID","segments"]},"Term":{"type":"object","properties":{"carrier":{"type":"string","description":"Marketing carrier IATA two letter code, capitalize"},"URL":{"type":"string","description":"terms and condition link"}},"required":["carrier","URL"]},"ServiceFee":{"type":"object","properties":{"amountPerUnit":{"type":"number","description":"Unit amount, unit: yuan, with a maximum of 2 decimal places retained"},"unit":{"$ref":"#/components/schemas/ServiceFeeModeEnums","description":"Amount unit.\n- PER_SEGMENT: Calculated per flight segment\n- PER_PAX: Calculated per passenger\n- PER_BOOKING: Calculated per order"},"currency":{"type":"string","description":"Currency code for the amount, in capital letters"}},"required":["amountPerUnit","unit","currency"]},"ServiceFeeModeEnums":{"type":"string","enum":["PER_SEGMENT","PER_PAX","PER_BOOKING"]},"BookingRequirementSchema":{"type":"object","properties":{"passenger":{"$ref":"#/components/schemas/PaxConstraint","description":"Specific requirements for passenger information"}},"required":["passenger"]},"PaxConstraint":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/Constraint"},"passengerType":{"$ref":"#/components/schemas/Constraint"},"birthday":{"$ref":"#/components/schemas/Constraint"},"gender":{"$ref":"#/components/schemas/Constraint"},"nationality":{"$ref":"#/components/schemas/Constraint"},"cardType":{"$ref":"#/components/schemas/Constraint"},"cardNum":{"$ref":"#/components/schemas/Constraint"},"cardIssuePlace":{"$ref":"#/components/schemas/Constraint"},"cardExpired":{"$ref":"#/components/schemas/Constraint"}},"required":["name","passengerType","birthday","gender","cardType","nationality","cardNum","cardIssuePlace","cardExpired"]},"Constraint":{"type":"object","properties":{"type":{"type":"string","description":"Data type","enum":["string","int"]},"required":{"type":"boolean","description":"Required or not"},"description":{"type":"string"},"maxLength":{"type":"string"}},"required":["type","required"]},"PaymentMethodEnums":{"type":"string","enum":["Deposit","VCC_Passthrough","BYOA","MoR"]}}}}
```
