Loyalty
Predict guest loyalty for a reservation
POST /loyalty/guest-loyalty
Predict guest rebooking probability and lifetime value for short-term rentals. Returns rebooking probability score (0-100) with loyalty tier, and predicted Guest Lifetime Value (USD) with value tier.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| x-api-key | header | string | false | API Authentication Key |
| body | body | GuestLoyaltyFeatures | false | Guest loyalty features for prediction |
Body parameter
{
"lead_time_days": 7,
"nights": 3,
"number_of_guests": 2,
"total_price": 450
}
Example responses
Successful loyalty prediction with rebooking score and GLV
{
"rebooking_score": 75.5,
"rebooking_tier": "high_loyalty",
"rebooking_tier_description": "Top prospects for re-engagement",
"predicted_glv": 2500,
"glv_tier": "high_value",
"glv_tier_description": "VIP treatment candidates",
"threshold_info": {
"rebooking_high_min": 70,
"rebooking_medium_min": 40,
"glv_high_min": 2000,
"glv_medium_min": 500
}
}
{
"rebooking_score": 20.3,
"rebooking_tier": "low_loyalty",
"rebooking_tier_description": "Unlikely to rebook",
"predicted_glv": 150,
"glv_tier": "low_value",
"glv_tier_description": "Standard service",
"threshold_info": {
"rebooking_high_min": 70,
"rebooking_medium_min": 40,
"glv_high_min": 2000,
"glv_medium_min": 500
}
}
Invalid input - validation errors
{
"error": "Invalid input",
"details": [
{
"loc": [
"nights"
],
"msg": "Input should be greater than or equal to 0",
"type": "greater_than_equal"
}
]
}
500 Response
{
"error": "string"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Successful loyalty prediction with rebooking score and GLV | LoyaltyPredictionResult |
| 400 | Bad Request | Invalid input - validation errors | ValidationErrorResponse |
| 500 | Internal Server Error | Internal server error | ErrorResponse |
Code samples
"""
Python Code Snippet
"""
import requests
input_body = {
"lead_time_days": 7,
"nights": 3,
"number_of_guests": 2,
"total_price": 450
}
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'x-api-key': 'string'
}
r = requests.post('https://data.autohost.ai/v1/loyalty/guest-loyalty', json=input_body, headers=headers)
print(r.json())
/*
TypeScript Code Snippet
*/
import fetch from 'node-fetch';
const inputBody = {
"lead_time_days": 7,
"nights": 3,
"number_of_guests": 2,
"total_price": 450
};
const headers = {
'Content-Type':'application/json',
'Accept':'application/json',
'x-api-key':'string'
};
const response = await fetch('https://data.autohost.ai/v1/loyalty/guest-loyalty', {
method: 'post',
body: JSON.stringify(inputBody),
headers,
});
const responseJson = await response.json();
console.log(responseJson);
Look up RFM segment for a guest
GET /loyalty/guest-segmentation/{segment}
Look up RFM segment for a guest. The segment path parameter accepts a guest ID (email address or phone number). Optionally filter by property manager.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| segment | path | string | true | Guest ID (email address or phone number) |
| property_manager_id | query | string | false | Optional filter for specific property manager |
| x-api-key | header | string | false | API Authentication Key |
Example responses
RFM segmentation result
{
"guest_id": "guest@example.com",
"property_manager_id": "pm_12345",
"timestamp": "2026-01-15T10:30:00Z",
"segment": {
"name": "Champions",
"tier": 1,
"description": "Best customers who book frequently and spend the most",
"recommended_action": "Offer exclusive perks and early access",
"offer_type": "VIP",
"priority": "CRITICAL"
},
"rfm_scores": {
"recency": 5,
"frequency": 5,
"monetary": 4,
"composite": "554"
},
"metrics": {
"days_since_last_stay": 15,
"last_stay_date": "2026-01-01",
"first_stay_date": "2024-06-15",
"total_stays": 8,
"total_revenue": 4200,
"total_nights": 24,
"avg_booking_value": 525,
"nights_equivalent": 3,
"customer_tenure_days": 549
},
"data_quality": {
"confidence": "HIGH",
"has_email": true,
"has_phone": true,
"is_ota_masked": false,
"identifier_type": "email"
},
"top_factors": [
{
"factor": "total_stays",
"value": "8",
"impact": "positive",
"description": "Frequent repeat guest"
},
{
"factor": "total_revenue",
"value": "4200",
"impact": "positive",
"description": "High lifetime spending"
}
],
"flags": {
"is_corporate_account": false,
"is_ota_guest": false,
"has_future_booking": true,
"is_seasonal_guest": false
}
}
Guest not found
{
"error": "GUEST_NOT_FOUND",
"message": "No RFM data found for guest: unknown@example.com",
"suggestions": [
"Verify the guest ID (email or phone) is correct",
"Guest may not have enough booking history",
"Try searching with a different identifier"
]
}
503 Response
{
"error": "string"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | RFM segmentation result | RFMSegmentResult |
| 404 | Not Found | Guest not found | RFMNotFoundError |
| 503 | Service Unavailable | Service unavailable | ErrorResponse |
Code samples
"""
Python Code Snippet
"""
import requests
headers = {
'Accept': 'application/json',
'x-api-key': 'string'
}
r = requests.get('https://data.autohost.ai/v1/loyalty/guest-segmentation/{segment}', headers=headers)
print(r.json())
/*
TypeScript Code Snippet
*/
import fetch from 'node-fetch';
const headers = {
'Accept':'application/json',
'x-api-key':'string'
};
const response = await fetch('https://data.autohost.ai/v1/loyalty/guest-segmentation/{segment}', {
method: 'get',
headers,
});
const responseJson = await response.json();
console.log(responseJson);
Schemas
GuestLoyaltyFeatures
{
"booking_month": 6,
"booking_dow": 3,
"booking_hour": 12,
"checkin_dow": 4,
"checkin_month": 6,
"email_domain_rank": 0,
"risk_color_encoded": 0,
"city_rank": 0,
"lead_time_days": 14,
"nights": 2,
"total_price": 300,
"average_daily_rate": 150,
"number_of_guests": 2,
"price_tier": 2,
"revenue_per_guest_night": 75,
"bedrooms": 1,
"guest_density": 2,
"prior_bookings_30d": 0,
"prior_bookings_90d": 0,
"prior_bookings_365d": 0,
"prior_revenue_total": 0,
"prior_bookings_same_pm": 0,
"days_since_last_booking": 0,
"booking_intensity": 0,
"max_guests": 4,
"capacity_utilization": 0.5,
"payment_success_count": 0,
"payment_failure_count": 0,
"distinct_cards": 0,
"payment_success_ratio": 0,
"idv_attempt_count": 0,
"idv_success_count": 0,
"idv_success_ratio": 0,
"portal_started": 0,
"portal_completed": 0,
"screens_count": 0,
"total_activity_events": 0,
"portal_completion_rate": 0,
"distinct_fingerprints": 0,
"distinct_ips": 0,
"total_fingerprint_events": 0,
"avg_confidence": 0,
"incident_count": 0,
"is_direct_booking": 0,
"is_ota_booking": 0,
"is_free_email": 0,
"is_booking_guest": 1,
"is_long_stay": 0,
"has_prior_booking": 0,
"has_idv_enabled": 0,
"has_payment_data": 0,
"has_payment_issues": 0,
"has_idv_data": 0,
"idv_completed": 0,
"has_payment_failure": 0,
"has_activity_data": 0,
"has_multiple_devices": 0,
"has_fingerprint_data": 0,
"has_chargeback_incident": 0,
"has_fraud_warning": 0,
"has_creditcard_incident": 0,
"has_any_incident": 0,
"is_verified": 0,
"guestportal_completed_flag": 0
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| booking_month | number | false | none | Month of booking (1-12) |
| booking_dow | number | false | none | Day of week for booking (0=Mon, 6=Sun) |
| booking_hour | number | false | none | Hour of day booking was made (0-23) |
| checkin_dow | number | false | none | Day of week for check-in (0=Mon, 6=Sun) |
| checkin_month | number | false | none | Month of check-in (1-12) |
| email_domain_rank | number | false | none | Email domain frequency rank (lower = more common) |
| risk_color_encoded | number | false | none | Risk color encoding (0=green, 1=yellow, 2=orange, 3=red, 4=black) |
| city_rank | number | false | none | City frequency rank (lower = more common) |
| lead_time_days | number | false | none | Days between booking and check-in |
| nights | number | false | none | Length of stay in nights |
| total_price | number | false | none | Total booking price in USD |
| average_daily_rate | number | false | none | Average price per night |
| number_of_guests | number | false | none | Number of guests |
| price_tier | number | false | none | Price tier category (0-5, higher = more expensive) |
| revenue_per_guest_night | number | false | none | Revenue per guest per night |
| bedrooms | number | false | none | Number of bedrooms in listing |
| guest_density | number | false | none | Guests per bedroom |
| prior_bookings_30d | number | false | none | Prior bookings by this guest in last 30 days |
| prior_bookings_90d | number | false | none | Prior bookings by this guest in last 90 days |
| prior_bookings_365d | number | false | none | Prior bookings by this guest in last 365 days |
| prior_revenue_total | number | false | none | Total revenue from prior bookings |
| prior_bookings_same_pm | number | false | none | Prior bookings with the same property manager |
| days_since_last_booking | number | false | none | Days since guest's last booking (0 if first booking) |
| booking_intensity | number | false | none | Booking frequency score |
| max_guests | number | false | none | Maximum guests allowed at listing |
| capacity_utilization | number | false | none | Ratio of guests to max capacity |
| payment_success_count | number | false | none | Successful payment count |
| payment_failure_count | number | false | none | Failed payment count |
| distinct_cards | number | false | none | Number of distinct payment cards used |
| payment_success_ratio | number | false | none | Ratio of successful to total payment attempts |
| idv_attempt_count | number | false | none | ID verification attempt count |
| idv_success_count | number | false | none | Successful ID verification count |
| idv_success_ratio | number | false | none | ID verification success rate |
| portal_started | number | false | none | Guest portal started count |
| portal_completed | number | false | none | Guest portal completed count |
| screens_count | number | false | none | Number of portal screens viewed |
| total_activity_events | number | false | none | Total activity log events |
| portal_completion_rate | number | false | none | Portal completion rate |
| distinct_fingerprints | number | false | none | Number of distinct device fingerprints |
| distinct_ips | number | false | none | Number of distinct IP addresses |
| total_fingerprint_events | number | false | none | Total fingerprint events |
| avg_confidence | number | false | none | Average fingerprint confidence score |
| incident_count | number | false | none | Total incident count for guest |
| is_direct_booking | number | false | none | 1 if direct booking, 0 otherwise |
| is_ota_booking | number | false | none | 1 if OTA booking (Airbnb, VRBO, etc.) |
| is_free_email | number | false | none | 1 if using free email provider (gmail, yahoo, etc.) |
| is_booking_guest | number | false | none | 1 if guest made the booking themselves |
| is_long_stay | number | false | none | 1 if stay is 7+ nights |
| has_prior_booking | number | false | none | 1 if guest has prior bookings |
| has_idv_enabled | number | false | none | 1 if ID verification was enabled for this booking |
| has_payment_data | number | false | none | 1 if payment data available |
| has_payment_issues | number | false | none | 1 if any payment issues occurred |
| has_idv_data | number | false | none | 1 if ID verification data available |
| idv_completed | number | false | none | 1 if ID verification was completed |
| has_payment_failure | number | false | none | 1 if any payment failures |
| has_activity_data | number | false | none | 1 if activity log data available |
| has_multiple_devices | number | false | none | 1 if multiple devices detected |
| has_fingerprint_data | number | false | none | 1 if fingerprint data available |
| has_chargeback_incident | number | false | none | 1 if guest has chargeback history |
| has_fraud_warning | number | false | none | 1 if fraud warning on record |
| has_creditcard_incident | number | false | none | 1 if credit card incident on record |
| has_any_incident | number | false | none | 1 if any incident on record |
| is_verified | number | false | none | 1 if guest identity is verified |
| guestportal_completed_flag | number | false | none | 1 if guest portal was completed |
LoyaltyPredictionResult
{
"rebooking_score": 100,
"rebooking_tier": "high_loyalty",
"rebooking_tier_description": "string",
"predicted_glv": 0,
"glv_tier": "high_value",
"glv_tier_description": "string",
"threshold_info": {
"rebooking_high_min": 70,
"rebooking_medium_min": 40,
"glv_high_min": 2000,
"glv_medium_min": 500
}
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| rebooking_score | number | true | none | Rebooking probability score (0-100) |
| rebooking_tier | string | true | none | Loyalty classification tier |
| rebooking_tier_description | string | true | none | Description of the loyalty tier |
| predicted_glv | number | true | none | Predicted Guest Lifetime Value in USD |
| glv_tier | string | true | none | GLV classification tier |
| glv_tier_description | string | true | none | Description of the GLV tier |
| threshold_info | object | true | none | Threshold configuration used for classification |
| » rebooking_high_min | number | false | none | none |
| » rebooking_medium_min | number | false | none | none |
| » glv_high_min | number | false | none | none |
| » glv_medium_min | number | false | none | none |
Enumerated Values
| Property | Value |
|---|---|
| rebooking_tier | high_loyalty |
| rebooking_tier | medium_loyalty |
| rebooking_tier | low_loyalty |
| glv_tier | high_value |
| glv_tier | medium_value |
| glv_tier | low_value |
ValidationErrorResponse
{
"error": "Invalid input",
"details": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string"
}
]
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| error | string | false | none | Error type |
| details | [object] | true | none | Validation error details |
| » loc | [string] | false | none | none |
| » msg | string | false | none | none |
| » type | string | false | none | none |
ErrorResponse
{
"error": "string"
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| error | string | false | none | none |
RFMBatchRequest
{
"guest_ids": [
"string"
],
"property_manager_id": "string"
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| guest_ids | [string] | true | none | Max 100 guest IDs per request |
| property_manager_id | string | false | none | none |
RFMBatchResult
{
"results": [
{
"guest_id": "string",
"property_manager_id": "string",
"timestamp": "string",
"segment": {},
"rfm_scores": {},
"metrics": {},
"data_quality": {},
"top_factors": [],
"flags": {}
}
],
"not_found": [
"string"
],
"total_requested": 0,
"total_found": 0
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| results | [object] | true | none | none |
| » guest_id | string | false | none | none |
| » property_manager_id | string | false | none | none |
| » timestamp | string | false | none | none |
| » segment | object | false | none | none |
| » rfm_scores | object | false | none | none |
| » metrics | object | false | none | none |
| » data_quality | object | false | none | none |
| » top_factors | array | false | none | none |
| » flags | object | false | none | none |
| not_found | [string] | true | none | none |
| total_requested | number | true | none | none |
| total_found | number | true | none | none |
RFMSegmentResult
{
"guest_id": "string",
"property_manager_id": "string",
"timestamp": "string",
"segment": {
"name": "Champions",
"tier": 1,
"description": "string",
"recommended_action": "string",
"offer_type": "string",
"priority": "CRITICAL"
},
"rfm_scores": {
"recency": 1,
"frequency": 2,
"monetary": 1,
"composite": "string"
},
"metrics": {
"days_since_last_stay": 0,
"last_stay_date": "string",
"first_stay_date": "string",
"total_stays": 0,
"total_revenue": 0,
"total_nights": 0,
"avg_booking_value": 0,
"nights_equivalent": 0,
"customer_tenure_days": 0
},
"data_quality": {
"confidence": "HIGH",
"has_email": true,
"has_phone": true,
"is_ota_masked": true,
"identifier_type": "string"
},
"top_factors": [
{
"factor": "string",
"value": "string",
"impact": "string",
"description": "string"
}
],
"flags": {
"is_corporate_account": false,
"is_ota_guest": true,
"has_future_booking": false,
"is_seasonal_guest": false
}
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| guest_id | string | true | none | none |
| property_manager_id | string | true | none | none |
| timestamp | string | true | none | none |
| segment | object | true | none | Segment classification with actionable guidance |
| » name | string | true | none | Segment name |
| » tier | number | true | none | Priority tier (1=highest) |
| » description | string | true | none | none |
| » recommended_action | string | true | none | none |
| » offer_type | string | true | none | none |
| » priority | string | true | none | none |
| rfm_scores | object | true | none | RFM score breakdown |
| » recency | number | true | none | none |
| » frequency | number | true | none | none |
| » monetary | number | true | none | none |
| » composite | string | true | none | Combined RFM score (e.g. '554') |
| metrics | object | true | none | Guest behavioral metrics |
| » days_since_last_stay | number | true | none | none |
| » last_stay_date | string | true | none | none |
| » first_stay_date | string | true | none | none |
| » total_stays | number | true | none | none |
| » total_revenue | number | true | none | none |
| » total_nights | number | true | none | none |
| » avg_booking_value | number | true | none | none |
| » nights_equivalent | number | true | none | none |
| » customer_tenure_days | number | true | none | none |
| data_quality | object | true | none | Data quality indicators |
| » confidence | string | true | none | none |
| » has_email | boolean | true | none | none |
| » has_phone | boolean | true | none | none |
| » is_ota_masked | boolean | true | none | none |
| » identifier_type | string | true | none | 'email' or 'phone' |
| top_factors | [object] | true | none | Explanation factors for segment assignment |
| » factor | string | true | none | none |
| » value | string | true | none | none |
| » impact | string | true | none | 'positive' or 'negative' |
| » description | string | true | none | none |
| flags | object | true | none | Guest classification flags |
| » is_corporate_account | boolean | false | none | none |
| » is_ota_guest | boolean | false | none | none |
| » has_future_booking | boolean | false | none | none |
| » is_seasonal_guest | boolean | false | none | none |
Enumerated Values
| Property | Value |
|---|---|
| name | Champions |
| name | High Value Active |
| name | High Value At Risk |
| name | High Value Slipping |
| name | Loyal Active |
| name | Loyal At Risk |
| name | Potential Loyalists |
| name | Repeat At Risk |
| name | Promising First-Timers |
| name | Recent First-Timers |
| name | First-Timers Need Attention |
| name | Hibernating |
| name | Other |
| priority | CRITICAL |
| priority | HIGH |
| priority | MEDIUM |
| priority | LOW |
| confidence | HIGH |
| confidence | MEDIUM |
| confidence | LOW |
| confidence | UNKNOWN |
RFMNotFoundError
{
"error": "GUEST_NOT_FOUND",
"message": "string",
"suggestions": [
"string"
]
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| error | string | false | none | none |
| message | string | true | none | none |
| suggestions | [string] | true | none | none |