Getting Started with the Xeni Activities APIHow to Book an ActivityHow to Browse Activity Tags and CategoriesHow to Cancel an Activity BookingHow to Check Activity AvailabilityHow to Get Activity DetailsHow to Retrieve Activity Booking DetailsHow to Search for Activities with FiltersHow to Search for Activity DestinationsCar Rental API - Getting StartedCar Rental API - Understanding Response FieldsHow to Book a Car RentalHow to Get Rental Car Details and Equipment Add-OnsHow to Retrieve or Cancel a Car Rental BookingHow to Search for Available Rental CarsHow to Search for Pickup LocationsHow to Use Car Rental Search FiltersDeals API Best Practices for IntegrationDeals API Frequently Asked QuestionsGetting Started with the Xeni Deals APIDeals API Request Parameters and Headers ReferenceDeals API Supported Currencies and LocalizationHow to Display Deals in Your ApplicationHow to Fetch Hotel Deals by LocationFlights API Error Codes and TroubleshootingGetting Started with the Xeni Flights APIHow to Book a FlightHow to Check Flight Availability and PricingHow to Confirm or Cancel a Flight BookingHow to Retrieve Fare Rules for a FlightHow to Retrieve Flight Booking DetailsHow to Search for Airports Using AutocompleteHow to Search for FlightsHow to Use Flight Search Filters, Sorting, and PaginationHow to Check Room Availability and PricingHow to Filter Vacation Rental ResultsHow to Get Resort Property Details, Amenities, and AccessibilityHow to Hold and Confirm a Resort BookingHow to Release a Resort HoldHow to Retrieve Resort Booking DetailsHow to Search for Available ResortsHow to Search for Resort DestinationsHow to Search for Vacation Rental LocationsHow to Search for Vacation RentalsHow to Use Resort Search Filters and SortingGetting Started with the Xeni Resorts APIResorts API: Understanding Booking Statuses and PoliciesGetting Started with the Vacation Rentals APIVacation Rentals Frequently Asked QuestionsVacation Rentals Supported Property TypesUnderstanding Async Search for Vacation RentalsAuthentication & API SignaturesBooking Hotels — Direct API & SSO CheckoutError Handling, Rate Limits & Best PracticesGetting Started with the Xeni Hotels APIManaging Bookings: Status, Retrieval & CancellationPricing Confirmation & Token LifecycleRetrieving Hotel Details & Room AvailabilitySearching for Hotels: Locations, Filters & PaginationSearching for HotelsSession Management & Correlation IDsAPI authentication and getting your API keys

Authentication & API Signatures

Last updated: 2026-02-13

Authentication & API Signatures

Every request to the Xeni API must include a valid signature in the Authorization header. This applies to all API products — Hotels, Cars, Flights, Activities, Resorts, Deals, and Content. Signatures are generated using your API key and secret, and expire after 30 minutes. This article covers how to generate, use, and refresh signatures.

How Authentication Works

  1. You send your API key, secret, and a Unix timestamp to the signature generation endpoint.
  2. The API returns a signature (a signed JWT token).
  3. You include this signature in the Authorization header of all subsequent API calls.
  4. When the signature is about to expire, you generate a new one.

Generating a Signature

Endpoint

POST /identity/v2/auth/generate

Request Body

ParameterTypeRequiredDescription
api_keystringYesYour Xeni API key.
secretstringYesYour Xeni API secret.
timestampintegerYesCurrent Unix timestamp in seconds (not milliseconds).

Example Request

POST https://api.travelapi.ai/identity/v2/auth/generateContent-Type: application/json

{ "api_key": "eb8c1638-7fde-48f3-98fe-7ea8d06327d7", "secret": "your-secret-here", "timestamp": 1700000000}

Example Response

JSON
{
  "signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Using the Signature

Pass the signature as the value of the Authorization header on every API call:

GET /api/v2/{product}/endpoint
Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

Signature Expiration

Signatures are valid for 30 minutes from the time they are generated. After that, any API call using an expired signature will return an authentication error.

Recommended: Auto-Refresh Strategy

To avoid disruptions during active sessions, we recommend refreshing your signature proactively rather than waiting for it to expire. A common pattern:

  • Store the signature and the time it was generated.
  • Check the signature age before each API call (or on a recurring timer).
  • If the signature has fewer than 5 minutes remaining, generate a new one.

Example: Auto-Refresh Logic (JavaScript)

class SignatureManager {  constructor(apiKey, secret, baseUrl) {    this.apiKey = apiKey;    this.secret = secret;    this.baseUrl = baseUrl;    this.signature = null;    this.expiresAt = null;  }

async generateSignature() { const response = await fetch(${this.baseUrl}/identity/v2/auth/generate, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ api_key: this.apiKey, secret: this.secret, timestamp: Math.floor(Date.now() / 1000) }) });

const data = await response.json(); this.signature = data.signature; this.expiresAt = Date.now() + (30 60 1000); // 30 minutes return this.signature; }

needsRefresh() { if (!this.signature || !this.expiresAt) return true; // Refresh if less than 5 minutes remaining return (this.expiresAt - Date.now()) < (5 60 1000); }

async getSignature() { if (this.needsRefresh()) { await this.generateSignature(); } return this.signature; }}

Example: Auto-Refresh Logic (Python)

import timeimport requests

class SignatureManager: def init(self, apikey, secret, baseurl): self.apikey = apikey self.secret = secret self.baseurl = baseurl self.signature = None self.expires_at = 0

def generatesignature(self): response = requests.post( f"{self.baseurl}/identity/v2/auth/generate", json={ "apikey": self.apikey, "secret": self.secret, "timestamp": int(time.time()) } ) data = response.json() self.signature = data["signature"] self.expires_at = time.time() + (30 * 60) # 30 minutes return self.signature

def needsrefresh(self): if not self.signature: return True return (self.expiresat - time.time()) < (5 * 60) # 5-min threshold

def getsignature(self): if self.needsrefresh(): self.generate_signature() return self.signature

Common Authentication Errors

HTTP StatusCauseResolution
401Missing or invalid Authorization headerEnsure you're including the signature in the header.
401Expired signatureGenerate a new signature. Signatures expire after 30 minutes.
401Invalid API key or secretVerify your credentials are correct and active.
400Timestamp is too far from server timeEnsure your system clock is accurate. Use Math.floor(Date.now() / 1000) or equivalent.

Security Best Practices

  • Never expose your API secret in client-side code. All signature generation should happen server-side.
  • Store credentials securely. Use environment variables or a secrets manager — never hard-code credentials in source files.
  • Rotate secrets regularly. Contact your Xeni account representative to rotate your API secret.
  • Monitor for 401 errors. A spike in authentication failures may indicate compromised credentials.

Was this article helpful?