Lookup Reservation
Find reservation using confirmation details or reservation ID
/public/reservations/lookupOverview
Allows guests to find their reservation using confirmation code or reservation ID, guest last name, and either check-in or check-out date. Returns the external reservation ID needed to claim the reservation in the Journey loyalty program.
Authentication
No authentication required. This is a public endpoint with rate limiting.
Rate Limiting
- Limit: 10 requests per minute per IP address
- Window: 60 seconds
- Headers: Rate limit information included in response headers
Request Body
At least one of confirmationCode or reservationId is required.
confirmationCodebodystringHotel confirmation code (required if reservationId not provided)
Maximum length: 100 characters
reservationIdbodystringProperty management system reservation ID (required if confirmationCode not provided)
Maximum length: 100 characters
checkOutDatebodystringCheck-out date in YYYY-MM-DD format. Required if checkInDate is not provided.
checkInDatebodystringCheck-in date in YYYY-MM-DD format. Required if checkOutDate is not provided.
lastNamebodystringrequiredGuest's last name (case insensitive)
Maximum length: 200 characters
Request
curl -X POST "https://api.journey.com/v1/public/reservations/lookup" \
-H "Content-Type: application/json" \
-d '{
"confirmationCode": "ABC123DEF",
"checkInDate": "2026-05-28",
"lastName": "Johnson"
}'Response
externalReservationIdstringrequiredExternal reservation identifier used for claiming reservation and other operations
Response
{
"externalReservationId": "12345678-1234-5678-9012-123456789012"
}Use Cases
Reservation Lookup Form
const ReservationLookupForm = ({ onSuccess }) => {
const [formData, setFormData] = useState({
confirmationCode: '',
reservationId: '',
checkOutDate: '',
lastName: ''
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
// Ensure at least one identifier is provided
if (!formData.confirmationCode && !formData.reservationId) {
throw new Error('Please provide either a confirmation code or reservation ID');
}
const result = await lookupReservation({
confirmationCode: formData.confirmationCode || undefined,
reservationId: formData.reservationId || undefined,
checkOutDate: formData.checkOutDate,
lastName: formData.lastName.trim()
});
onSuccess(result.externalReservationId);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit} className="reservation-lookup">
<div className="form-group">
<label>Confirmation Code</label>
<input
type="text"
value={formData.confirmationCode}
onChange={(e) => setFormData(prev => ({
...prev,
confirmationCode: e.target.value.toUpperCase()
}))}
placeholder="ABC123DEF"
maxLength={100}
/>
</div>
<div className="form-divider">OR</div>
<div className="form-group">
<label>Reservation ID</label>
<input
type="text"
value={formData.reservationId}
onChange={(e) => setFormData(prev => ({
...prev,
reservationId: e.target.value
}))}
placeholder="RES-2026-001234"
maxLength={100}
/>
</div>
<div className="form-group">
<label>Check-out Date *</label>
<input
type="date"
value={formData.checkOutDate}
onChange={(e) => setFormData(prev => ({
...prev,
checkOutDate: e.target.value
}))}
required
/>
</div>
<div className="form-group">
<label>Last Name *</label>
<input
type="text"
value={formData.lastName}
onChange={(e) => setFormData(prev => ({
...prev,
lastName: e.target.value
}))}
placeholder="Johnson"
maxLength={200}
required
/>
</div>
{error && (
<div className="error-message">{error}</div>
)}
<button type="submit" disabled={loading}>
{loading ? 'Looking up...' : 'Find Reservation'}
</button>
</form>
);
};Multi-Step Reservation Flow
const ReservationClaimFlow = () => {
const [step, setStep] = useState('lookup'); // 'lookup', 'preview', 'claim'
const [externalId, setExternalId] = useState(null);
const [reservation, setReservation] = useState(null);
const handleLookupSuccess = async (foundExternalId) => {
setExternalId(foundExternalId);
// Fetch reservation preview
try {
const preview = await getReservationPreview(foundExternalId);
setReservation(preview);
setStep('preview');
} catch (error) {
console.error('Failed to load reservation preview:', error);
}
};
const handleClaimReservation = () => {
// Redirect to authentication/claim flow
window.location.href = `/claim/${externalId}`;
};
return (
<div className="reservation-flow">
{step === 'lookup' && (
<ReservationLookupForm onSuccess={handleLookupSuccess} />
)}
{step === 'preview' && reservation && (
<div className="reservation-preview">
<h2>Reservation Found!</h2>
<div className="property-info">
<h3>{reservation.property.name}</h3>
<p>{reservation.property.address.city}, {reservation.property.address.state}</p>
</div>
<div className="guest-info">
<h4>Guest: {reservation.guest.firstName}</h4>
<p>Points to earn: {reservation.totalAwardedPoints.toLocaleString()}</p>
</div>
{reservation.isClaimed ? (
<p>This reservation has already been claimed.</p>
) : (
<button onClick={handleClaimReservation}>
Claim Reservation & Earn Points
</button>
)}
<button onClick={() => setStep('lookup')}>
Look up different reservation
</button>
</div>
)}
</div>
);
};Form Validation
const validateLookupForm = (formData) => {
const errors = [];
// Check for at least one identifier
if (!formData.confirmationCode && !formData.reservationId) {
errors.push('Please provide either a confirmation code or reservation ID');
}
// Validate date format
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
if (!dateRegex.test(formData.checkOutDate)) {
errors.push('Check-out date must be in YYYY-MM-DD format');
}
// Validate date is not in future (reasonable booking window)
const checkOutDate = new Date(formData.checkOutDate);
const maxFutureDate = new Date();
maxFutureDate.setFullYear(maxFutureDate.getFullYear() + 2);
if (checkOutDate > maxFutureDate) {
errors.push('Check-out date seems too far in the future');
}
// Validate last name
if (!formData.lastName.trim()) {
errors.push('Last name is required');
}
if (formData.lastName.length > 200) {
errors.push('Last name is too long');
}
return errors;
};Lookup Strategies
Search Priority
- Exact Match: Direct lookup by confirmation code or reservation ID
- Fuzzy Matching: Handle common typos in names (implementation dependent)
- Case Insensitive: Last name matching ignores case differences
Data Sources
- Hotel PMS Systems: Primary reservation data source
- Booking Platforms: OTA and direct booking confirmations
- Legacy Systems: Historical reservation data
Matching Criteria
- Confirmation Code/Reservation ID: Exact match required
- Check-out Date: Must match exactly
- Last Name: Case-insensitive match
- Additional Validation: May include room type, dates, etc.
Error Handling
Common Issues
- Multiple Identifiers: Don't provide both confirmationCode and reservationId
- Date Format: Use YYYY-MM-DD format only
- Name Variations: Try exact name as on reservation
- Recent Bookings: May take time to sync from PMS
Troubleshooting Tips
const troubleshootingMessages = {
notFound: {
title: "Reservation not found",
suggestions: [
"Double-check your confirmation code or reservation ID",
"Verify the check-out date is correct",
"Ensure the last name matches the reservation exactly",
"Try using the other identifier (confirmation code vs reservation ID)",
"Recent bookings may take up to 24 hours to sync"
]
},
validation: {
title: "Invalid information provided",
suggestions: [
"Use YYYY-MM-DD format for dates (e.g., 2026-06-03)",
"Provide either confirmation code OR reservation ID",
"Enter the full last name as shown on the reservation"
]
}
};Security Considerations
Rate Limiting
- Prevents brute force attempts
- IP-based tracking across all public endpoints
- Exponential backoff recommended for retries
Data Privacy
- Only returns external reservation ID
- No sensitive guest information exposed
- Lookup requires multiple verification points
Input Sanitization
- All inputs validated and sanitized
- SQL injection prevention
- XSS protection for all text fields
Related Endpoints
- Get Reservation Preview - View reservation details
- Resolve Legacy Booking - Convert legacy bookings