ubtrippin

TotalClaw 作者 totalclaw v2.0.0

通过 UBTRIPPIN 管理用户的旅行 — 旅行、项目、忠诚度计划、家庭、城市指南、活动、音乐会、通知等。当用户询问他们的旅行、即将到来的旅行、航班、酒店、火车预订、音乐会门票、活动门票、忠诚度号码、家庭旅行或想要管理他们的旅行跟踪器时使用。需要 ubtrippin.xyz/settings 中的 UBTRIPPIN API 密钥。

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install totalclaw:totalclaw~fistfulayen-ubtrippin
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~fistfulayen-ubtrippin/file -o fistfulayen-ubtrippin.md
## 概述(中文)

通过 UBTRIPPIN 管理用户的旅行 — 旅行、项目、忠诚度计划、家庭、城市指南、活动、音乐会、通知等。当用户询问他们的旅行、即将到来的旅行、航班、酒店、火车预订、音乐会门票、活动门票、忠诚度号码、家庭旅行或想要管理他们的旅行跟踪器时使用。需要 ubtrippin.xyz/settings 中的 UBTRIPPIN API 密钥。

## 原文

# UBTRIPPIN Skill

**UBTRIPPIN** is a personal travel tracker that parses booking confirmation emails and organises them into trips. It also handles event tickets — concerts, theater, sports, festivals — from providers like Ticketmaster, AXS, Eventbrite, and more. As an agent, you can read and manage a user's trips, items (flights, hotels, trains, tickets/events, etc.), loyalty vault, family groups, city guides, and more via REST API.

---

## Setup (First Time)

1. Ask your user to visit **ubtrippin.xyz/settings** and generate an API key.
2. The key looks like: `ubt_k1_<40 hex chars>`. Store it securely.
3. Ask for their **registered sender email** — the email address they use to forward bookings (typically their personal inbox). This is their "allowed sender" in UBTRIPPIN.
4. You'll need both to operate: the API key for reads/writes, the email address for adding new bookings via forwarding.
5. After setup, call `GET /api/v1/me/profile` and offer to set the user's home airport, currency preference, and seat preference via `PATCH /api/v1/me/profile`.

---

## Authentication

All API calls use a Bearer token:

```
Authorization: Bearer ubt_k1_<your_key>
```

Base URL: `https://www.ubtrippin.xyz`

**Rate limit:** 100 requests/minute per API key. HTTP 429 if exceeded — back off 60 seconds.

---

## API Endpoints

### Trips

#### List All Trips
```
GET /api/v1/trips
```

Query params: `?status=upcoming` (optional filter)

Response:
```json
{
  "data": [
    {
      "id": "uuid",
      "title": "Tokyo Spring 2026",
      "start_date": "2026-04-01",
      "end_date": "2026-04-14",
      "primary_location": "Tokyo, Japan",
      "travelers": ["Ian Rogers"],
      "notes": null,
      "cover_image_url": "https://...",
      "share_enabled": false,
      "created_at": "2026-02-15T10:00:00Z",
      "updated_at": "2026-02-15T10:00:00Z"
    }
  ],
  "meta": { "count": 1 }
}
```

Ordered by start_date descending (soonest upcoming / most recent first).

#### Get Trip with All Items
```
GET /api/v1/trips/:id
```

Response includes full trip object with nested `items` array. Each item has: `id`, `trip_id`, `kind`, `provider`, `traveler_names`, `start_ts`, `end_ts`, `start_date`, `end_date`, `start_location`, `end_location`, `summary`, `details_json`, `status`, `confidence`, `needs_review`, timestamps.

**Item kinds:** `flight`, `hotel`, `train`, `car`, `ferry`, `activity`, `ticket`, `other`

#### Create Trip
```
POST /api/v1/trips
Content-Type: application/json

{ "title": "Summer in Provence", "start_date": "2026-07-01", "end_date": "2026-07-14" }
```

#### Update Trip
```
PATCH /api/v1/trips/:id
Content-Type: application/json

{ "title": "Updated Title", "notes": "Remember sunscreen" }
```

#### Delete Trip
```
DELETE /api/v1/trips/:id
```

#### Rename Trip
```
POST /api/v1/trips/:id/rename
Content-Type: application/json

{ "title": "New Trip Name" }
```

#### Merge Trips
```
POST /api/v1/trips/:id/merge
Content-Type: application/json

{ "source_trip_id": "uuid-of-trip-to-merge-in" }
```

Merges items from the source trip into the target trip.

#### Trip Status
```
GET /api/v1/trips/:id/status
```

Returns processing status for the trip.

#### Demo Trip
```
GET /api/v1/trips/demo
```

Returns a sample trip for onboarding — no auth required.

---

### Items

#### Get Single Item
```
GET /api/v1/items/:id
```

Response: `{ "data": <item> }` — full Item shape with `details_json` containing confirmation numbers, seat assignments, etc.

#### Update Item
```
PATCH /api/v1/items/:id
Content-Type: application/json

{ "summary": "Updated summary", "start_location": "Paris CDG" }
```

#### Delete Item
```
DELETE /api/v1/items/:id
```

#### Add Item to Trip
```
POST /api/v1/trips/:id/items
Content-Type: application/json
```

**Required fields:** `kind`, `start_date`

**All fields:**

| Field | Type | Description |
|-------|------|-------------|
| `kind` | string | **Required.** One of: `flight`, `hotel`, `car_rental`, `train`, `activity`, `restaurant`, `ticket`, `other` |
| `start_date` | string | **Required.** ISO date: `YYYY-MM-DD` |
| `end_date` | string | ISO date. For hotels = checkout, flights = arrival date if different |
| `start_ts` | string | ISO 8601 datetime with timezone: `2026-04-01T08:30:00Z` |
| `end_ts` | string | ISO 8601 datetime with timezone |
| `start_location` | string | Departure/origin. City, airport code, or address (max 300 chars) |
| `end_location` | string | Arrival/destination (max 300 chars) |
| `summary` | string | One-line summary, e.g. "AF276 CDG→NRT" (max 1000 chars) |
| `provider` | string | Airline, hotel chain, etc. e.g. "Air France" (max 200 chars) |
| `confirmation_code` | string | Booking reference (max 200 chars) |
| `traveler_names` | string[] | Array of traveler names (max 20, each max 200 chars) |
| `details_json` | object | Freeform metadata — gate, seat, room type, etc. (max 10KB) |
| `notes` | string | User notes |
| `status` | string | Item status |

**Example — Flight:**
```json
{
  "kind": "flight",
  "start_date": "2026-04-01",
  "start_ts": "2026-04-01T08:30:00+01:00",
  "end_ts": "2026-04-01T15:45:00+09:00",
  "start_location": "Paris CDG",
  "end_location": "Tokyo NRT",
  "summary": "AF276 CDG→NRT",
  "provider": "Air France",
  "confirmation_code": "XK7J3M",
  "traveler_names": ["Ian Rogers"],
  "details_json": { "flight_number": "AF276", "seat": "14A", "class": "Economy" }
}
```

**Example — Hotel:**
```json
{
  "kind": "hotel",
  "start_date": "2026-04-01",
  "end_date": "2026-04-05",
  "start_location": "Tokyo, Japan",
  "summary": "Park Hyatt Tokyo",
  "provider": "Hyatt",
  "confirmation_code": "HY-889923",
  "traveler_names": ["Ian Rogers", "Hedvig Rogers"],
  "details_json": { "room_type": "King Deluxe", "check_in": "15:00", "check_out": "11:00" }
}
```

**Example — Train:**
```json
{
  "kind": "train",
  "start_date": "2026-04-05",
  "start_ts": "2026-04-05T09:00:00+09:00",
  "end_ts": "2026-04-05T11:30:00+09:00",
  "start_location": "Tokyo Station",
  "end_location": "Kyoto Station",
  "summary": "Shinkansen Nozomi 7",
  "provider": "JR Central",
  "confirmation_code": "JR-44521",
  "details_json": { "car": "7", "seat": "3A", "class": "Green Car" }
}
```

**Example — Restaurant:**
```json
{
  "kind": "restaurant",
  "start_date": "2026-04-03",
  "start_ts": "2026-04-03T19:00:00+09:00",
  "start_location": "Sukiyabashi Jiro, Ginza, Tokyo",
  "summary": "Dinner at Sukiyabashi Jiro",
  "details_json": { "party_size": 2, "reservation_name": "Rogers" }
}
```

**Example — Ticket/Event (concert, sports, theater, festival, etc.):**
```json
{
  "kind": "ticket",
  "summary": "David Byrne at Théâtre du Châtelet",
  "start_date": "2026-05-15",
  "start_ts": "2026-05-15T20:00:00+02:00",
  "start_location": "Paris",
  "provider": "Ticketmaster",
  "details_json": {
    "event_name": "David Byrne: American Utopia",
    "venue": "Théâtre du Châtelet",
    "venue_address": "1 Place du Châtelet, 75001 Paris",
    "performer": "David Byrne",
    "event_time": "20:00",
    "door_time": "19:00",
    "section": "Orchestre",
    "seat": "12",
    "row": "G",
    "ticket_count": 2,
    "ticket_type": "Reserved",
    "event_category": "concert"
  }
}
```

**Ticket detail fields:**
| Field | Type | Description |
|-------|------|-------------|
| event_name | string | Name of the event/show |
| venue | string | Venue name |
| venue_address | string? | Full address |
| event_time | HH:MM | Show start time |
| door_time | HH:MM? | Door opening time |
| section | string? | Seating section |
| seat | string? | Seat number |
| row | string? | Row identifier |
| ticket_count | number | Number of tickets |
| ticket_type | string? | GA, Reserved, VIP, etc. |
| performer | string? | Artist/performer/team |
| event_category | enum | concert, theater, sports, mu