Frontend integration reference

Eficta API Guide

Authentication, flight search and booking, and hotel search and booking. This guide contains only the fields a frontend application needs.

Base URL: https://servicestest.api.eficta.com

Quick start

Available flight providers: only 1 and 2. Put the selected provider number in every flight endpoint.

Response examples show realistic frontend-facing data. Large arrays and deeply nested details are shortened to one representative item.

  1. Log in once and save access_token.
  2. Send it as the x-api-token header on all flight and hotel requests.
  3. Keep the IDs and keys returned by each step; the next request must use those exact values.
  4. Never decode, edit, or construct fare keys, session UUIDs, hotel IDs, package IDs, or room allocation IDs.

Authentication

Exchange the provided API account credentials for a short-lived access token.

POST/api/api-auth/loginNo token required

Request

{
  "username": "YOUR_API_USERNAME",
  "password": "YOUR_API_PASSWORD"
}

Response

{
  "access_token": "eyJ...",
  "token_type": "bearer",
  "expires_in": 3600
}

Save access_token and send it as x-api-token. When the API returns an expired-token response, log in again and retry the original request once.

Customer login for “My bookings”

Log the customer in directly through Gita. This login call does not use the services API token. The two “My bookings” requests then send both the services API token and the signed-in customer's token.

POSThttps://gita.sa/api/auth/loginCustomer login
{
  "email": "customer@example.com",
  "password": "CUSTOMER_PASSWORD"
}
{
  "access_token": "CUSTOMER_ACCESS_TOKEN",
  "token_type": "Bearer",
  "user": {
    "id": 123,
    "name": "John Smith",
    "email": "customer@example.com"
  }
}

Keep this access_token separate from the API token. Send it as Authorization: Bearer CUSTOMER_ACCESS_TOKEN.

Common headers

HeaderValuePurpose
Content-Typeapplication/jsonRequired for POST bodies.
x-api-tokenToken from loginRequired for flight and hotel calls.
AuthorizationBearer CUSTOMER_ACCESS_TOKENRequired only for customer-specific endpoints such as “My bookings.”
lngen or arResponse language. Defaults to English.
x-countryISO country code, e.g. EGCustomer country.
x-currencyCurrency code, e.g. EGPDisplay/payment currency.
const headers = {
  "Content-Type": "application/json",
  "x-api-token": accessToken,
  "lng": "en",
  "x-country": "EG",
  "x-currency": "EGP"
};

Flights

Use one provider for the complete flow. The frontend may show provider choices as Provider 1 and Provider 2; no supplier names are needed.

SearchChoose flight/fareRevalidate fareChoose offerBook
Provider rule: replace {provider} with 1 or 2 only. Use the response flight's endpoint if results from multiple providers are displayed together.

2. Revalidate the selected fare

POST/api/{endpoint}/fare

Use the passenger counts from the search without changing them.

{
  "departureFareKey": "FARE_KEY_FROM_SEARCH",
  "returnFareKey": "RETURN_FARE_KEY_FROM_SEARCH",
  "adults": 1,
  "children": 0,
  "infants": 0
}

Omit returnFareKey for one-way travel.

Example response

{
  "success": true,
  "message": "Success",
  "data": {
    "fare_detail": {
      "currency_code": "EGP",
      "price_info": { "total_fare": 14599 },
      "baggages_text": ["2 Bag"],
      "cabin_baggages_text": ["1 Bag (7 Kg)"]
    },
    "offers": [
      {
        "offer_details": [
          { "name": "ECOSAVER", "descriptions": ["ECOSAVER"] }
        ],
        "total_price": 14599,
        "currency_code": "EGP",
        "non_refundable": true,
        "refundability_text": "Non Refundable",
        "exchangeability_text": ["Exchangeable With Fees"],
        "baggages_text": ["2 Bag"],
        "cabin_baggages_text": ["1 Bag (7 Kg)"],
        "meal_text": ["Meal"]
      },
      {
        "offer_details": [
          { "name": "ECOFLEX", "descriptions": ["ECOFLEX"] }
        ],
        "total_price": 17548,
        "currency_code": "EGP",
        "non_refundable": false,
        "refundability_text": "Refundable With Fees"
      }
    ],
    "departure_flight": {
      "endpoint": "2",
      "provider_key": "2|ATPCO"
    }
  }
}

Offers

If data.offers is present, show every offer to the user. Display its price and rules, then build the selected offer value from its detail names:

const selectedOffer = offer.offer_details
  .map(detail => detail.name)
  .join("|");

// Example: "ECOSAVER"
// A return/multi-part offer can look like: "ECOSAVER|ECOFLEX"
Offer fieldFrontend use
offer_details[].nameValue used to build the booking offer.
offer_details[].descriptionsCustomer-facing offer label/details.
total_price, currency_codeOffer price.
refundability_text, exchangeability_textRules to display.
baggages_text, cabin_baggages_text, meal_textIncluded services.

If there is no offers array, continue with the base fare and omit offer from booking.

3. Create the flight booking

POST/api/{endpoint}/book
{
  "departureFareKey": "SAME_KEY_USED_FOR_FARE",
  "returnFareKey": "SAME_RETURN_KEY_USED_FOR_FARE",
  "offer": "ECOSAVER",
  "paymentGateway": "paymob",
  "redirectUrl": "https://your-app.example/payment-result",
  "contact_info": {
    "name": "John Smith",
    "email": "john@example.com",
    "country_code": "20",
    "phone": "1000000000"
  },
  "paxList": [
    {
      "name": "John",
      "lastName": "Smith",
      "type": "ADULT",
      "birthDate": "1990-01-01",
      "gender": "MALE",
      "identityInfo": {
        "passport": {
          "citizenshipCountry": "EG",
          "endDate": "2030-01-01",
          "no": "A12345678"
        },
        "notTurkishCitizen": true,
        "notPakistanCitizen": true
      }
    }
  ],
  "usePoints": false,
  "useBalance": false
}
  • Omit returnFareKey for one-way travel.
  • Omit offer when fare revalidation returned no offers.
  • paxList counts and types must exactly match the search.
  • Passenger type: ADULT, CHILD, or INFANT.
  • gender: MALE or FEMALE.
  • Names use English letters and spaces. Passport numbers must be unique.
  • country_code + phone must total 12 digits.

Successful response

{
  "success": true,
  "message": "Success",
  "bookingId": "FS-...",
  "redirectUrl": "https://payment-provider.example/...",
  "price": 4232
}

Save bookingId and send the browser to redirectUrl to continue payment.

Read flight bookings

Get one confirmed booking

GET/api/{provider}/bookings/{reference}

Send the common headers and replace {reference} with the bookingId returned by the book request. A successful response returns the booking in data, including itinerary, passengers, status, price, and voucher information when available.

{
  "success": true,
  "data": {
    "id": 178991,
    "booking_number": "FS-1789910205287",
    "booking_reference": "ABC123",
    "status": "ticketed",
    "finished": false,
    "fromLocation": "CAI",
    "toLocation": "DXB",
    "adult": 1,
    "child": 0,
    "infant": 0,
    "departure": "2026-10-20T00:00:00.000Z",
    "return_date": null,
    "type": "OneWay",
    "currency": "EGP",
    "price": 15340,
    "cabin_class": "Y",
    "chosen_offer": {
      "offer_name": "ECOSAVER",
      "baggages_text": ["2 Bag"],
      "cabin_baggages_text": ["1 Bag (7 Kg)"]
    },
    "voucher": "https://gita.sa/api/flights-services/v1/public/voucher/FS-1789910205287"
  }
}
This endpoint returns confirmed/paid bookings. Immediately after an unpaid book request, the booking may not be available here yet.

Get the signed-in customer's bookings

GET/api/{provider}/bookingsCustomer auth required

Send both authentication headers:

x-api-token: API_ACCOUNT_ACCESS_TOKEN
Authorization: Bearer CUSTOMER_ACCESS_TOKEN

The response contains confirmed bookings in data[]. Use each item's booking reference with the single-booking endpoint when a details screen needs a fresh copy.

{
  "success": true,
  "data": [
    {
      "id": 178991,
      "booking_number": "FS-1789910205287",
      "booking_reference": "ABC123",
      "status": "ticketed",
      "fromLocation": "CAI",
      "toLocation": "DXB",
      "departure": "2026-10-20T00:00:00.000Z",
      "type": "OneWay",
      "currency": "EGP",
      "price": 15340,
      "finished": false
    }
  ]
}

Hotels

Hotel searches create a temporary session. Keep the returned uuid unchanged through packages and booking.

Choose destinationSearchChoose hotelLoad packagesChoose room/packageBook
GET/api/hotels/destinations?q=cairo

Use this endpoint for destination autocomplete. Use one of the returned values to search:

  • cities[].latitude and cities[].longitude → search with location.
  • hotels[].hotelId → search with hotelIds: [hotelId].

For featured destinations use /api/hotels/destinations?top=1.

Example response

{
  "cities": [
    {
      "nameEn": "Cairo",
      "nameAr": "القاهرة",
      "countryEn": "Egypt",
      "countryAr": "مصر",
      "countryCode": "EG",
      "latitude": 30.0444,
      "longitude": 31.2357,
      "isTopCity": false
    }
  ],
  "hotels": [
    {
      "hotelId": 12345,
      "nameEn": "Cairo Marriott Hotel",
      "nameAr": "فندق ماريوت القاهرة",
      "cityName": "Cairo",
      "countryLabel": "Egypt",
      "starRating": 5
    }
  ],
  "landmarks": []
}

2. Load hotel details and packages

POST/api/hotels/b2c/packages
{
  "uuid": "UUID_FROM_HOTEL_SEARCH",
  "hotelID": 12345
}

Example response

{
  "errors": [],
  "uuid": "86cd0d97-4471-45bf-926e-217be17d7ef1",
  "packages": [
    {
      "hotelId": 12345,
      "packageId": "PKG-982731",
      "price": {
        "currency": "EGP",
        "finalPrice": 20550,
        "originalPrice": 19800,
        "taxesAndFees": 750
      },
      "refundability": 1,
      "refundabilityNew": true,
      "refundableUntil": "2026-10-17",
      "rooms": [
        {
          "id": "ROOM-1-DBL",
          "adultsCount": 2,
          "kidsAges": [7],
          "availability": 3,
          "roomBasisCode": "Bed and Breakfast BB",
          "roomBasis": "Bed and Breakfast BB",
          "roomName": "Deluxe Nile View Room"
        }
      ],
      "remarks": []
    }
  ],
  "hotelContent": {
    "descriptions": [
      { "title": "Hotel", "description": "Five-star hotel in central Cairo.", "language": "en" }
    ],
    "facilities": [
      { "facility": "Free WiFi", "facilityType": "General" }
    ],
    "images": ["https://gita.sa/storage/hotels/12345/1.jpg"]
  }
}

The response includes hotelContent and a packages array. For the booking form, save:

  • packages[].packageIdpackageID.
  • packages[].rooms[].id → each passenger's Allocation.
  • Room adult counts and child ages determine the exact passenger list required at booking.
  • Use package price, rooms, meal/board, and refundability fields for display.

If content is needed separately:

POST/api/hotels/b2c/hotel-content
{
  "uuid": "UUID_FROM_HOTEL_SEARCH",
  "hotelID": 12345
}

Example response

{
  "data": {
    "descriptions": [
      {
        "title": "Hotel",
        "description": "Five-star hotel in central Cairo.",
        "language": "en",
        "line": 1
      }
    ],
    "facilities": [
      {
        "facility": "Free WiFi",
        "facilityIcon": "https://gita.sa/storage/hotel-facilities/Free%20WiFi.svg",
        "facilityType": "General"
      }
    ],
    "images": ["https://gita.sa/storage/hotels/12345/1.jpg"]
  }
}

3. Create the hotel booking

POST/api/hotels/b2c/book
{
  "uuid": "UUID_FROM_HOTEL_SEARCH",
  "hotelID": 12345,
  "packageID": "PACKAGE_ID_FROM_PACKAGES",
  "leadPaxID": "guest-1",
  "leadPaxAllocation": "ROOM_ID_FROM_PACKAGE",
  "paymentGateway": "paymob",
  "redirectUrl": "https://your-app.example/payment-result",
  "passengers": [
    {
      "Id": "guest-1",
      "Allocation": "ROOM_ID_FROM_PACKAGE",
      "PersonDetails": {
        "Name": {
          "GivenName": "John",
          "Surname": "Smith",
          "NamePrefix": "Mr"
        },
        "Type": 0
      },
      "Email": { "Value": "john@example.com" },
      "Telephone": { "PhoneNumber": "201000000000" }
    },
    {
      "Id": "guest-2",
      "Allocation": "ROOM_ID_FROM_PACKAGE",
      "PersonDetails": {
        "Name": {
          "GivenName": "Jane",
          "Surname": "Smith",
          "NamePrefix": "Miss"
        },
        "Type": 1,
        "Age": 7
      }
    }
  ],
  "usePoints": false,
  "useBalance": false
}
RuleRequirement
Passenger IDsFrontend-generated unique strings. leadPaxID must match one passenger's Id.
AllocationMust be an actual room id from the selected package. Lead passenger allocation must equal leadPaxAllocation.
Type0 = adult, 1 = child. The lead passenger must be an adult.
Child ageRequired for children and must match an age requested for that room.
Adult contactAdults require a valid email and a 12-digit international phone number without +.
OccupancyPassenger count, types, ages, and room allocations must exactly match the selected package.

Successful response

{
  "success": true,
  "message": "Booking created and payment session initialized successfully",
  "bookingId": 123,
  "redirectUrl": "https://payment-provider.example/...",
  "paymentId": 456,
  "price": 2500
}

Read hotel bookings

Get one confirmed booking

GET/api/hotels/b2c/bookings/{reference}

Send the common headers and replace {reference} with the hotel bookingId or confirmed provider reference. The response returns the booking in data, including hotel, stay, package, guests, payment status, confirmation number, and voucher URL when available.

{
  "success": true,
  "data": {
    "id": 123,
    "hotel_id": 12345,
    "hotel_name": "Cairo Marriott Hotel",
    "amount": 20550,
    "amount_to_pay": 21578,
    "currency": "EGP",
    "status": "confirmed",
    "payment_status": "paid",
    "adults": 2,
    "children": 1,
    "customer_name": "John Smith",
    "provider_reference": "HTL-849271",
    "booking_status": "confirmed",
    "confirmation_number": "HTL-849271",
    "search_data": {
      "checkIn": "2026-10-20",
      "checkOut": "2026-10-23",
      "location": { "latitude": 30.0444, "longitude": 31.2357 }
    },
    "package": {
      "packageId": "PKG-982731",
      "nights": 3,
      "rooms": [
        { "id": "ROOM-1-DBL", "roomName": "Deluxe Nile View Room" }
      ]
    },
    "voucher": "https://gita.sa/api/booking-node/voucher?providerReference=HTL-849271"
  }
}
This endpoint returns confirmed/paid bookings. Immediately after an unpaid book request, the booking may not be available here yet.

Get the signed-in customer's bookings

GET/api/hotels/b2c/bookingsCustomer auth required

Send both authentication headers:

x-api-token: API_ACCOUNT_ACCESS_TOKEN
Authorization: Bearer CUSTOMER_ACCESS_TOKEN

The response contains paid hotel bookings in data[]. Useful list fields include id, hotel_name, search_data, package, amount_to_pay, currency, status, finished, and voucher.

{
  "success": true,
  "data": [
    {
      "id": 123,
      "hotel_id": 12345,
      "hotel_name": "Cairo Marriott Hotel",
      "amount_to_pay": 21578,
      "currency": "EGP",
      "status": "confirmed",
      "payment_status": "paid",
      "adults": 2,
      "children": 1,
      "finished": false,
      "search_data": {
        "checkIn": "2026-10-20",
        "checkOut": "2026-10-23"
      },
      "voucher": "https://gita.sa/api/booking-node/voucher?providerReference=HTL-849271"
    }
  ]
}

Error handling

Status / codeFrontend action
401 / 403Check the API token. If expired, log in again and retry once.
400Show message; the request or selected item is invalid.
422Use the errors object to display field validation messages.
EXPIRED_FLIGHTSRestart from flight search.
EXPIRED_HOTELSRestart from hotel search to obtain a new uuid.
EXPIRED_COUNTRY / EXPIRED_CURRENCYCorrect the corresponding request header.
Prices and availability are confirmed during fare/package selection and can change. Always display the latest price returned by the API before booking.