Skip to content
All Skills

Bilt

Search Bilt Rewards travel portal for cash and Bilt Points pricing on hotels and flights. Public REST API, no auth required. Includes Home Away From Home (HaFH) properties with $300+ benefits.

Personal Productivity|v1|Updated 7/14/2026|GitHub source
MCP get_skill({ skillId: "bilt-67f64f9b" })

Use this skill with your agent

Create a free account and connect via MCP

Get Started Free
# Bilt Travel Portal Search

Search [Bilt Rewards](https://www.bilt.com) travel portal via the public REST API. No authentication required for search. Returns both cash prices in USD and Bilt Points cost for hotels and flights.

## Important: Bilt is Whitelabel Duffel

Bilt's travel search is built directly on top of [Duffel](https://duffel.com). All evidence points to a complete white-label arrangement, not a partial integration:

- Flight offer IDs are `off_XXX`, slices `sli_XXX`, segments `seg_XXX`, aircraft `arc_XXX`, airlines `arl_XXX`. All Duffel ID patterns.
- Carrier and aircraft logos served from `assets.duffel.com`.
- Hotel loyalty program logos served from `assets.duffel.com/img/stays/loyalty-programmes`. So hotels are Duffel Stays.
- JWT `organisation_id: org_0000AaALZyFQ...` is a Duffel auth pattern.
- Field names match Duffel exactly: `marketingCarrier`, `operatingCarrier`, `cabinClassMarketingName`, `fareBasisCode`, `isNDC`, `ndcRedirectUrl`, `totalEmissionsKg`, `slices[].segments[].passengers[].baggages[]`.

**What Bilt adds on top of Duffel:**
- `totalPointsRequired` (Bilt Points cost at the fixed 1.25 cpp portal rate)
- `isHafh` (Home Away From Home flag on hotels)
- `loyaltyProgram.reference` (brand affiliation surfacing for hotels)
- A few Bilt-specific filter fields

**What this means for the toolkit:**
- For **cash-only flight searches**, prefer the [duffel skill](../duffel/SKILL.md). It uses an authenticated Duffel API key, returns the same data faster, and supports more parameters (multi-city, time windows, max connections, supplier_timeout tuning).
- For **Bilt Points context** (CPP, comparing portal cost to award alternatives, Bilt redemption math), use this skill. The points pricing is exclusive to Bilt's endpoint.
- For **Home Away From Home property research**, use this skill. The `isHafh` flag is Bilt-specific and surfaces the $300+ benefits properties.

## Why It Matters

- **1.25 cpp** standard redemption rate on Bilt Points (1 USD = 80 points). One of the better fixed portal rates.
- **Home Away From Home (HaFH)** is Bilt's premium hotel program. Gold and Platinum members get $300+ in benefits per stay (daily breakfast for two, $100 property credit, room upgrades on arrival, early check-in / late check-out, dedicated Virtuoso Travel Advisor).
- **Bilt Points transfer 1:1** to Hyatt, Marriott, Hilton, IHG, United, AA, Air Canada Aeroplan, Air France/KLM, Virgin Atlantic, Cathay, Turkish, and more — so this portal is a 1.25 cpp "bottom-of-the-barrel" comparison point for transfer-partner award searches.
- **Flights are Duffel-backed.** Same response shape as the [duffel skill](../duffel/SKILL.md). Same airlines, same fare classes, same segment structure.
- **No auth needed for search.** Browser automation, login, 2FA all unnecessary. Just curl.

## When to Use

- Comparing Bilt portal pricing to seats.aero awards
- Computing CPP for Bilt Points redemptions
- Finding HaFH properties for Bilt Gold/Platinum benefit stacking
- Sanity-checking cash vs points decision when Bilt Points are involved
- As a "redemption floor" reference: if award flights cost more than the portal price, the portal wins

## When NOT to Use

- **Cash-only flight searches without Bilt Points context.** Use [duffel](../duffel/SKILL.md) instead. Bilt is whitelabel-Duffel, so Duffel returns the same cash prices and offer shape, faster, with more parameters supported.
- **Booking flights or hotels.** This skill finds offers only. Booking requires login + Bilt Mastercard. Out of scope.
- **Award flight search.** Use [seats-aero](../seats-aero/SKILL.md) for award availability across loyalty programs.
- **Hotel research outside Bilt's program.** Use [premium-hotels](../premium-hotels/SKILL.md) for Amex FHR/THC + Chase Edit, [serpapi](../serpapi/SKILL.md) for general Google Hotels metasearch.

## Bilt Points Valuation

| Metric | Value | Notes |
|--------|-------|-------|
| Portal redemption rate | 1.25 cpp | $1 = 80 points (standard, fixed) |
| Cash → points formula | `points = round(usd / 0.0125)` | Reverse-derived from observed responses |
| TPG valuation (transfers) | 2.05 cpp | When transferred to optimal partners |

**Decision rule:** If transferring Bilt Points to a partner program would yield more than 1.25 cpp, transfer. If not, use the portal.

## API Base

```
https://api.biltrewards.com/public/travel
```

All endpoints are public, no API key required. Standard JSON responses.

## Hotel Search

### Step 1: Look up location searchId

```bash
curl -s "https://api.biltrewards.com/public/travel/hotels/auto-complete?query=New+York" \
  | jq '.searchResults[0].locationSuggestion'
```

Returns:
```json
{
  "name": "New York",
  "country": {"name": "USA", "code": "US"},
  "region": {"name": "NY", "code": null},
  "searchId": "ChIJOwg_06VPwokRYv534QaPC8g"
}
```

The `searchId` is a Google Places ID. You can also pass `searchType: HOTEL_SEARCH` results to search a specific property.

### Step 2: Search hotels

```bash
curl -s "https://api.biltrewards.com/public/travel/hotels/search" \
  --get \
  --data-urlencode "checkInDate=2026-08-15" \
  --data-urlencode "checkOutDate=2026-08-18" \
  --data-urlencode "numGuestAdults=2" \
  --data-urlencode "numRooms=1" \
  --data-urlencode "searchId=ChIJOwg_06VPwokRYv534QaPC8g" \
  | jq '.hotelResults | length'
```

Returns 100 to 200 hotels typically. Synchronous, no polling needed.

### Required parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `checkInDate` | YYYY-MM-DD | Required |
| `checkOutDate` | YYYY-MM-DD | Required |
| `numGuestAdults` | int | Required, 1+ |
| `numRooms` | int | Required, 1+ |
| `searchId` | string | Google Places ID from auto-complete |

### Optional parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `childrenAges` | csv ints | E.g. `5,8` for two children aged 5 and 8 |
| `hotelId` | string | Search a specific `acc_XXX` property |

### Hotel response shape

```
{
  stayDetails: { checkInDate, checkOutDate, numRooms, numGuestAdults, childrenAges },
  hotelResults: [
    {
      id: "acc_XXX",
      name: "Park Hyatt New York",
      rating: 5,                      // star rating
      description: "...",
      isHafh: true,                   // Home Away From Home flag
      loyaltyProgram: {               // brand affiliation, if any
        name: "World of Hyatt",
        reference: "world_of_hyatt",
        logoUrl: "..."
      },
      address: { street, city, stateProvince, countryCode, postalCode },
      geolocation: { latitude, longitude },
      amenities: [{ description, category }, ...],
      images: [{ url }, ...],
      lowestRateDetails: {
        usdAmounts: { total },        // cash total in USD
        points: 319681,               // Bilt Points cost
        dueAtHotelAmount, dueAtHotelCurrency,
        ...
      }
    }
  ],
  filterDetails: { ... }
}
```

### Hotel detail (room rates)

```bash
curl -s "https://api.biltrewards.com/public/travel/hotels/acc_0000AWPt2s3aNc1GpC5bmU?checkInDate=2026-08-15&checkOutDate=2026-08-18&numGuestAdults=2&numRooms=1" \
  | jq '.hotelDetails | {name, isHafh, rates: .roomTypes[0]}'
```

Returns `hotelDetails` with full property info plus `roomTypes` containing each available rate.

### Useful jq filters

```bash
# Top 10 cheapest hotels with HaFH flag and CPP rounded to 2 decimals
curl -s "$URL" | jq '
  [.hotelResults[]
   | select(.lowestRateDetails.usdAmounts.total != null)
   | {name, isHafh, rating,
      cash: .lowestRateDetails.usdAmounts.total,
      points: .lowestRateDetails.points,
      cpp: (((.lowestRateDetails.usdAmounts.total / .lowestRateDetails.points) * 100) * 100 | round / 100),
      brand: .loyaltyProgram.name}]
  | sort_by(.cash) | .[0:10]'

# Only HaFH properties (worth $300+ benefits if Gold/Platinum)
curl -s "$URL" | jq '
  [.hotelResults[]
   | select(.isHafh == true)
   | {name, rating, cash: .lowestRateDetails.usdAmounts.total, points: .lowestRateDetails.points}]
  | sort_by(.cash)'
```

## Flight Search

### Step 1: Submit search

```bash
curl -s "https://api.biltrewards.com/public/travel/flights/search" \
  --get \
  --data-urlencode "departureDate=2026-08-15" \
  --data-urlencode "returnDate=2026-08-22" \
  --data-urlencode "origin=SFO" \
  --data-urlencode "destination=NRT" \
  --data-urlencode "adults=1" \
  --data-urlencode "cabinClass=business"
```

Returns:
```json
{
  "data": {
    "id": "orq_0000B5mQkPhO7VxuWClhZI",
    "totalBatches": 35,
    "remainingBatches": 35,
    "createdAt": "...",
    "clientKey": "..."
  }
}
```

### Step 2: Poll for results

```bash
curl -s "https://api.biltrewards.com/public/travel/flights/search/$ID"
```

`remainingBatches` ticks down to 0 over 5 to 15 seconds. The response includes the `offers` array as soon as the first batch returns. Poll every 3 to 5 seconds until `remainingBatches == 0` for the complete result set.

```bash
# Polling loop
for i in 1 2 3 4 5; do
  RESP=$(curl -s "https://api.biltrewards.com/public/travel/flights/search/$ID")
  REMAINING=$(echo "$RESP" | jq -r '.data.remainingBatches')
  echo "Poll $i: $REMAINING batches remaining"
  [ "$REMAINING" = "0" ] && break
  sleep 4
done
echo "$RESP" | jq '.data.offers | length'
```

### Required parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `departureDate` | YYYY-MM-DD | Required |
| `origin` | IATA airport code | Required |
| `destination` | IATA airport code | Required |
| `adults` | int | Required, 1+ |

### Optional parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `returnDate` | YYYY-MM-DD | Round-trip, omit for one-way |
| `cabinClass` | string | `economy`, `premium_economy`, `business`, `first` |
| `children` | int | Number of children (with `childrenAges`) |
| `infants` | int | Lap infants |

### Flight response shape

Same as Duffel (Bilt is whitelabel-Duffel). Each offer:

```
{
  id: "off_XXX",
  totalAmount: 1606.60,        // cash total
  totalCurrency: "USD",
  baseAmount: 1132.00,
  taxAmount: 474.60,
  totalPointsRequired: 128528,  // Bilt Points cost
  totalPointsRequiredWithCredits: null,  // applicable airline credits, if any
  expiresAt: "2026-04-29T08:51:40Z",
  owner: {
    name: "KLM", iataCode: "KL", logoSymbolUrl, conditionsOfCarriageUrl
  },
  isNDC: false,
  passengers: [{ type, loyaltyProgrammeAccounts, id }],
  conditions: { refundBeforeDeparture, changeBeforeDeparture },
  slices: [
    {
      id: "sli_XXX",
      duration: "P1DT4H40M",   // ISO 8601 duration
      fareBrandName: "Standard",
      origin: { iataCode, name, cityName, timeZone },
      destination: { iataCode, name, cityName, timeZone },
      segments: [
        {
          id, duration, departingAt, arrivingAt,
          origin: {...}, destination: {...},
          marketingCarrier: { name, iataCode, ... },
          operatingCarrier: { name, iataCode, ... },
          marketingCarrierFlightNumber: "0606",
          aircraft: { name: "Boeing 787-10", iataCode: "781" },
          stops: [],
          passengers: [
            {
              passengerId,
              fareBasisCode: "THA79NMP",
              cabinClassMarketingName: "ECONOMY",
              baggages: [{ type: "checked"|"carry_on", quantity }]
            }
          ]
        }
      ]
    }
  ]
}
```

### Useful jq filters

```bash
# Top 5 cheapest offers with CPP calculation (rounded to 2 decimals)
echo "$RESP" | jq '
  [.data.offers[]
   | {airline: .owner.name,
      cash: .totalAmount,
      points: .totalPointsRequired,
      cpp: (((.totalAmount / .totalPointsRequired) * 100) * 100 | round / 100),
      stops: ([.slices[].segments | length] | map(. - 1)),
      route: ([.slices[] | (.origin.iataCode + " -> " + .destination.iataCode)])}]
  | sort_by(.cash) | .[0:5]'

# Group by airline, show cheapest per carrier
echo "$RESP" | jq '
  [.data.offers[]
   | {airline: .owner.name, cash: .totalAmount, points: .totalPointsRequired}]
  | group_by(.airline)
  | map({airline: .[0].airline, cheapest: (min_by(.cash))})'

# Filter to nonstop only
echo "$RESP" | jq '
  [.data.offers[]
   | select(([.slices[].segments | length] | add) == ([.slices | length]))
   | {airline: .owner.name, cash: .totalAmount, points: .totalPointsRequired}]'
```

## Output Format

**Always use markdown tables.** When showing both flights and hotels, separate tables.

### Hotels

| Hotel | Stars | HaFH | Brand | Cash | Points | CPP |
|-------|-------|------|-------|------|--------|-----|
| Park Hyatt New York | 5 | yes | Hyatt | $3,996 | 319,681 | 1.25 |
| The St. Regis NY | 5 | no | Marriott | $4,210 | 336,800 | 1.25 |

### Flights (one-way SFO to NRT)

| Airline | Stops | Duration | Cash | Points | CPP |
|---------|-------|----------|------|--------|-----|
| Air Canada | 1 (YVR) | 14h 5m | $871 | 69,720 | 1.25 |
| KLM | 1 (AMS) | 28h 40m | $1,607 | 128,528 | 1.25 |

After tables: highlight the cheapest, flag any HaFH stays the user qualifies for (Bilt Gold or Platinum status required), and call out anything where CPP is wildly off (would indicate a special promo or a points-only "boost" rate).

## Comparison Workflow

For a complete trip cost analysis:

1. **Bilt Points balance** via [awardwallet](../awardwallet/SKILL.md). Note: Bilt is in AwardWallet.
2. **Award alternatives** via [seats-aero](../seats-aero/SKILL.md). Compare to portal price at 1.25 cpp.
3. **Transfer partners** via [transfer-partners](../transfer-partners/SKILL.md). If a partner program redeems Bilt Points at >1.25 cpp, transfer instead of using portal.
4. **Other portals** via [chase-travel](../chase-travel/SKILL.md) (dynamic Points Boost on CSR/CSP, ~1.5-2.0 cpp on select bookings, not a guaranteed floor) and [amex-travel](../amex-travel/SKILL.md) (~1.0 cpp on flights). Pull actual portal quotes, not assumed rates.
5. **HaFH benefits** add ~$300+ in value per stay if the user has Bilt Gold or Platinum status. Apply this when computing effective rate.

## Important Notes

- **`isHafh: true`** identifies Home Away From Home properties. Roughly 200 to 300 luxury hotels worldwide. Always flag when present.
- **Bilt has no transfer fees.** Unlike some portal-points conversions, Bilt → partner transfers are 1:1 instant.
- **Booking requires the Bilt card.** Most premium benefits (HaFH, Rent Day points multipliers, status) are gated by holding the Bilt Mastercard.
- **API responses don't include the agent's user context.** This is the public unauthenticated path. Authenticated calls would return personalized data (your saved searches, points balance), but those require login. Out of scope for this skill.
- **Stellate (`bilt-rewards.stellate.sh`)** is Bilt's CMS endpoint, not a search backend. It serves marketing copy and benefit descriptions. The actual hotel/flight search data comes from `api.biltrewards.com/public/travel` and is fully covered above.
#travel#flights#hotels#points-miles#award-travel#portal#searchcurljqbashbilt