ubtrippin
通过 UBTRIPPIN 管理用户的旅行 — 旅行、项目、忠诚度计划、家庭、城市指南、活动、音乐会、通知等。当用户询问他们的旅行、即将到来的旅行、航班、酒店、火车预订、音乐会门票、活动门票、忠诚度号码、家庭旅行或想要管理他们的旅行跟踪器时使用。需要 ubtrippin.xyz/settings 中的 UBTRIPPIN API 密钥。
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install totalclaw:totalclaw~fistfulayen-ubtrippincURL直接下载,无需登录
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