Структура ответа#

Детальное описание структуры ответа от /api/avia/pnr_reprice.

Основная структура#

Ответ содержит актуальную тарификацию бронирования.

ПолеТипОписание
pricingsarrayМассив тарификаций по типам пассажиров
ticketingFeeobjectСервисный сбор за выписку из тарифного пресета, загруженный вместе с бронированием (см. структуру ниже); может отсутствовать

Структура Pricing#

ПолеТипОписание
paxTypestringТип пассажира (adt, chd, inf)
priceobjectЦеновая информация
segmentsarrayДетали по сегментам
fareTypestringТип тарифа: public — публичный, corporate — корпоративный/контрактный
validatingCarrierstringВалидирующий перевозчик

Структура Price#

ПолеТипОписание
totalobjectПолная стоимость
baseFareobjectБазовый тариф
equivFareobjectЭквивалент тарифа (в валюте оплаты, если отличается)
taxesobjectТаксы и сборы

Структура Amount#

ПолеТипОписание
currencyCodestringКод валюты (ISO 4217)
valuenumberСумма

Структура Taxes#

ПолеТипОписание
totalobjectОбщая сумма такс
breakdownarrayДетализация по кодам такс

Структура TaxBreakdown#

ПолеТипОписание
codestringКод таксы/сбора
amountobjectСумма

Структура Segment#

ПолеТипОписание
segmentIdstringИдентификатор сегмента из бронирования
flightobjectИнформация о рейсе
originobjectПункт отправления
destinationobjectПункт прибытия
fareBasisstringКод базового тарифа
cabinstringКласс обслуживания
rbdstringКод бронирования (RBD, booking class)
ticketDesignatorstringТикет-дезигнатор (см. IATA ticket designator); может отсутствовать
baggageAllowanceobjectНорма багажа

Структура Flight#

ПолеТипОписание
carrierCodestringКод перевозчика
flightNumberstringНомер рейса

Структура Location (Origin/Destination)#

ПолеТипОписание
locationobjectИнформация о локации
dateTimestringДата и время (ISO 8601)

Структура Location.location#

ПолеТипОписание
codestringКод аэропорта
codeTypestringТип кода (iata, icao)
typestringТип локации (airport, city)

Структура BaggageAllowance#

ПолеТипОписание
typestringТип багажа (carryOn, checked)
pieceAllowanceobjectНорма по количеству мест
weightAllowanceobjectНорма по весу

Структура TicketingFee#

Сервисный сбор за выписку билета, рассчитанный тарифным пресетом и загруженный вместе с бронированием (структура идентична ticketingFee в pnr_retrieve).

ПолеТипОписание
amountMonetaryAmountИтоговая сумма сбора за весь offer item (baseFee × множитель allocation)
allocationFeeAllocationTypeСпособ распределения сбора
breakdownPerPtcmap<string, MonetaryAmount>Разбивка суммы по типу пассажира (ключ — код PTC, например ADT); присутствует только когда allocation = perTicket
presetInfoobjectИнформация о пресете, рассчитавшем сбор

FeeAllocationType — возможные значения:

  • perTicket — сбор за каждый билет
  • perSegment — сбор за каждый сегмент

Структура PresetInfo#

ПолеТипОписание
presetIdguidИдентификатор пресета
presetNamestringНазвание пресета

Примеры ответов#

Успешный ответ#

 1{
 2  "pricings": [
 3    {
 4      "paxType": "adt",
 5      "price": {
 6        "baseFare": {
 7          "currencyCode": "RUB",
 8          "value": 8950
 9        },
10        "equivFare": {
11          "currencyCode": "USD",
12          "value": 95.5
13        },
14        "taxes": {
15          "total": {
16            "currencyCode": "RUB",
17            "value": 537
18          },
19          "breakdown": [
20            {
21              "code": "YR",
22              "amount": {
23                "currencyCode": "RUB",
24                "value": 120
25              }
26            },
27            {
28              "code": "RI",
29              "amount": {
30                "currencyCode": "RUB",
31                "value": 417
32              }
33            }
34          ]
35        },
36        "total": {
37          "currencyCode": "RUB",
38          "value": 9487
39        }
40      },
41      "segments": [
42        {
43          "baggageAllowance": {
44            "type": "carryOn",
45            "pieceAllowance": {
46              "totalPieces": 1
47            }
48          },
49          "cabin": "economy",
50          "rbd": "R",
51          "destination": {
52            "location": {
53              "code": "KZN",
54              "codeType": "iata",
55              "type": "airport"
56            },
57            "dateTime": "2025-11-21T23:40:00"
58          },
59          "fareBasis": "RCOR",
60          "flight": {
61            "carrierCode": "SU",
62            "flightNumber": "1278"
63          },
64          "origin": {
65            "location": {
66              "code": "SVO",
67              "codeType": "iata",
68              "type": "airport"
69            },
70            "dateTime": "2025-11-21T21:55:00"
71          },
72          "segmentId": "2c2dbf78-da30-46bd-9e18-a1f9f8e7fec7",
73          "ticketDesignator": "IT"
74        }
75      ],
76      "fareType": "public",
77      "validatingCarrier": "SU"
78    }
79  ],
80  "ticketingFee": {
81    "amount": {
82      "currencyCode": "RUB",
83      "value": 500
84    },
85    "allocation": "perTicket",
86    "breakdownPerPtc": {
87      "ADT": {
88        "currencyCode": "RUB",
89        "value": 500
90      }
91    },
92    "presetInfo": {
93      "presetId": "018c5f2e-9b3a-7f4d-8e2c-1a2b3c4d5e6f",
94      "presetName": "Base fee preset"
95    }
96  }
97}

Бронирование с несколькими пассажирами#

 1{
 2  "pricings": [
 3    {
 4      "paxType": "adt",
 5      "price": {
 6        "total": {
 7          "currencyCode": "RUB",
 8          "value": 9487
 9        }
10      }
11    },
12    {
13      "paxType": "chd",
14      "price": {
15        "total": {
16          "currencyCode": "RUB",
17          "value": 7115
18        }
19      }
20    },
21    {
22      "paxType": "inf",
23      "price": {
24        "total": {
25          "currencyCode": "RUB",
26          "value": 949
27        }
28      }
29    }
30  ]
31}

Ответ с ошибкой#

1{
2  "error": {
3    "code": "BOOKING_NOT_FOUND",
4    "message": "Бронирование не найдено",
5    "description": "Бронирование с указанным ID не существует",
6    "errorId": "018c5f2e-9b3a-7f4d-8e2c-1a2b3c4d5e6f"
7  }
8}

Использование данных#

Расчет общей стоимости#

 1var repricing = await RepriceBooking(bookingId);
 2var booking = await RetrieveBooking(bookingId);
 3
 4var totalPrice = 0m;
 5
 6foreach (var pricing in repricing.Pricings)
 7{
 8    // Подсчитываем количество пассажиров этого типа
 9    var passengerCount = booking.Pnr.Passengers
10        .Count(p => p.Type == pricing.PaxType);
11
12    // Добавляем к общей сумме
13    totalPrice += pricing.Price.Total.Value * passengerCount;
14}
15
16Console.WriteLine($"Общая стоимость: {totalPrice} RUB");

Сравнение с исходной ценой#

 1var repricing = await RepriceBooking(bookingId);
 2var booking = await RetrieveBooking(bookingId);
 3
 4var originalPrice = booking.Pnr.FareInfo.Fares
 5    .Sum(f => f.Price.Total.Value);
 6
 7var actualPrice = repricing.Pricings
 8    .Sum(p => p.Price.Total.Value);
 9
10if (actualPrice > originalPrice)
11{
12    var increase = actualPrice - originalPrice;
13    Console.WriteLine($"Цена увеличилась на {increase} RUB");
14}
15else if (actualPrice < originalPrice)
16{
17    var decrease = originalPrice - actualPrice;
18    Console.WriteLine($"Цена уменьшилась на {decrease} RUB");
19}
20else
21{
22    Console.WriteLine("Цена не изменилась");
23}

детализация по таксам#

 1var pricing = repricing.Pricings[0];
 2
 3Console.WriteLine($"Базовый тариф: {pricing.Price.BaseFare.Value} {pricing.Price.BaseFare.CurrencyCode}");
 4Console.WriteLine("Таксы и сборы:");
 5
 6foreach (var tax in pricing.Price.Taxes.Breakdown)
 7{
 8    Console.WriteLine($"  {tax.Code}: {tax.Amount.Value} {tax.Amount.CurrencyCode}");
 9}
10
11Console.WriteLine($"Итого таксы: {pricing.Price.Taxes.Total.Value} {pricing.Price.Taxes.Total.CurrencyCode}");
12Console.WriteLine($"ВСЕГО: {pricing.Price.Total.Value} {pricing.Price.Total.CurrencyCode}");

Проверка изменения тарифа#

 1var repricing = await RepriceBooking(bookingId);
 2var booking = await RetrieveBooking(bookingId);
 3
 4foreach (var pricing in repricing.Pricings)
 5{
 6    var originalFare = booking.Pnr.FareInfo.Fares
 7        .FirstOrDefault(f => f.PaxType == pricing.PaxType);
 8
 9    if (originalFare == null) continue;
10
11    foreach (var segment in pricing.Segments)
12    {
13        var originalSegment = originalFare.Itinerary
14            .FirstOrDefault(s => s.SegRefId == segment.SegmentId);
15
16        if (originalSegment?.FareBasis != segment.FareBasis)
17        {
18            Console.WriteLine($"Изменился код тарифа для сегмента {segment.SegmentId}:");
19            Console.WriteLine($"  Было: {originalSegment?.FareBasis}");
20            Console.WriteLine($"  Стало: {segment.FareBasis}");
21        }
22    }
23}

Формирование отчета об изменениях#

 1public class PriceChangeReport
 2{
 3    public string BookingId { get; set; }
 4    public decimal OriginalPrice { get; set; }
 5    public decimal ActualPrice { get; set; }
 6    public decimal Difference { get; set; }
 7    public List<PriceChangeDetail> Details { get; set; }
 8}
 9
10public async Task<PriceChangeReport> GeneratePriceChangeReport(string bookingId)
11{
12    var repricing = await RepriceBooking(bookingId);
13    var booking = await RetrieveBooking(bookingId);
14
15    var report = new PriceChangeReport
16    {
17        BookingId = bookingId,
18        Details = new List<PriceChangeDetail>()
19    };
20
21    foreach (var pricing in repricing.Pricings)
22    {
23        var originalFare = booking.Pnr.FareInfo.Fares
24            .FirstOrDefault(f => f.PaxType == pricing.PaxType);
25
26        if (originalFare != null)
27        {
28            var originalPrice = originalFare.Price.Total.Value;
29            var actualPrice = pricing.Price.Total.Value;
30
31            report.Details.Add(new PriceChangeDetail
32            {
33                PassengerType = pricing.PaxType,
34                OriginalPrice = originalPrice,
35                ActualPrice = actualPrice,
36                Difference = actualPrice - originalPrice
37            });
38
39            report.OriginalPrice += originalPrice;
40            report.ActualPrice += actualPrice;
41        }
42    }
43
44    report.Difference = report.ActualPrice - report.OriginalPrice;
45
46    return report;
47}

Уведомление пользователя об изменении#

 1public async Task NotifyPriceChangeIfNeeded(string bookingId)
 2{
 3    var repricing = await RepriceBooking(bookingId);
 4    var booking = await RetrieveBooking(bookingId);
 5
 6    var originalPrice = GetTotalPrice(booking);
 7    var actualPrice = GetTotalPrice(repricing);
 8
 9    if (actualPrice != originalPrice)
10    {
11        var difference = actualPrice - originalPrice;
12        var percentChange = (difference / originalPrice) * 100;
13
14        var message = difference > 0
15            ? $"Цена вашего бронирования {booking.Pnr.PnrLocator} увеличилась на {difference:F2} ₽ ({percentChange:F1}%)"
16            : $"Цена вашего бронирования {booking.Pnr.PnrLocator} уменьшилась на {Math.Abs(difference):F2} ₽ ({Math.Abs(percentChange):F1}%)";
17
18        await SendNotification(booking.UserId, message);
19    }
20}

Типичные ошибки#

Код ошибкиПричинаРешение
BOOKING_NOT_FOUNDБронирование не найдено или не принадлежит клиентуПроверьте bookingId
CURRENCY_RATE_NOT_AVAILABLEНет курса для конвертации сумм в валюту отображенияПовторите запрос позже
VALIDATION_ERRORОшибка валидации запроса (HTTP 400)Проверьте обязательные поля и форматы значений
NO_TARGETSПод запрос не нашлось ни одного поставщика: ни один не настроен либо все отсеяны на этапе подготовки запросаПроверьте настройки офисов и пресетов в личном кабинете; при сохранении ошибки обратитесь в поддержку
SUPPLIER_ERRORПоставщик вернул ошибку. Причина — текстом поставщика в поле messageРазберите message; при необходимости повторите запрос позже
SYSTEM_ERRORВнутренняя ошибка Travel APIПовторите запрос позже; при повторении обратитесь в поддержку с errorId

Ошибки, пришедшие от GDS/NDC-поставщика, возвращаются под кодом SUPPLIER_ERROR: отдельного кода на каждую причину отказа Travel API не формирует, причина передаётся текстом поставщика в поле message. Не завязывайте логику на разбор message — его формат зависит от поставщика и не фиксирован.


Связанные операции#