{
  "schemaVersion": "1.0",
  "item": {
    "slug": "ubtrippin",
    "name": "Skill",
    "source": "tencent",
    "type": "skill",
    "category": "通讯协作",
    "sourceUrl": "https://clawhub.ai/fistfulayen/ubtrippin",
    "canonicalUrl": "https://clawhub.ai/fistfulayen/ubtrippin",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/ubtrippin",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ubtrippin",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL-LITE.md",
      "SKILL.md",
      "_meta.json",
      "examples/add-booking-via-email.md",
      "examples/get-trip.sh"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/ubtrippin"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/ubtrippin",
    "agentPageUrl": "https://openagent3.xyz/skills/ubtrippin/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ubtrippin/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ubtrippin/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "UBTRIPPIN Skill",
        "body": "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."
      },
      {
        "title": "Setup (First Time)",
        "body": "Ask your user to visit ubtrippin.xyz/settings and generate an API key.\nThe key looks like: ubt_k1_<40 hex chars>. Store it securely.\nAsk for their registered sender email — the email address they use to forward bookings (typically their personal inbox). This is their \"allowed sender\" in UBTRIPPIN.\nYou'll need both to operate: the API key for reads/writes, the email address for adding new bookings via forwarding.\nAfter 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."
      },
      {
        "title": "Authentication",
        "body": "All API calls use a Bearer token:\n\nAuthorization: Bearer ubt_k1_<your_key>\n\nBase URL: https://www.ubtrippin.xyz\n\nRate limit: 100 requests/minute per API key. HTTP 429 if exceeded — back off 60 seconds."
      },
      {
        "title": "Trips",
        "body": "List All Trips\n\nGET /api/v1/trips\n\nQuery params: ?status=upcoming (optional filter)\n\nResponse:\n\n{\n  \"data\": [\n    {\n      \"id\": \"uuid\",\n      \"title\": \"Tokyo Spring 2026\",\n      \"start_date\": \"2026-04-01\",\n      \"end_date\": \"2026-04-14\",\n      \"primary_location\": \"Tokyo, Japan\",\n      \"travelers\": [\"Ian Rogers\"],\n      \"notes\": null,\n      \"cover_image_url\": \"https://...\",\n      \"share_enabled\": false,\n      \"created_at\": \"2026-02-15T10:00:00Z\",\n      \"updated_at\": \"2026-02-15T10:00:00Z\"\n    }\n  ],\n  \"meta\": { \"count\": 1 }\n}\n\nOrdered by start_date descending (soonest upcoming / most recent first).\n\nGet Trip with All Items\n\nGET /api/v1/trips/:id\n\nResponse 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.\n\nItem kinds: flight, hotel, train, car, ferry, activity, ticket, other\n\nCreate Trip\n\nPOST /api/v1/trips\nContent-Type: application/json\n\n{ \"title\": \"Summer in Provence\", \"start_date\": \"2026-07-01\", \"end_date\": \"2026-07-14\" }\n\nUpdate Trip\n\nPATCH /api/v1/trips/:id\nContent-Type: application/json\n\n{ \"title\": \"Updated Title\", \"notes\": \"Remember sunscreen\" }\n\nDelete Trip\n\nDELETE /api/v1/trips/:id\n\nRename Trip\n\nPOST /api/v1/trips/:id/rename\nContent-Type: application/json\n\n{ \"title\": \"New Trip Name\" }\n\nMerge Trips\n\nPOST /api/v1/trips/:id/merge\nContent-Type: application/json\n\n{ \"source_trip_id\": \"uuid-of-trip-to-merge-in\" }\n\nMerges items from the source trip into the target trip.\n\nTrip Status\n\nGET /api/v1/trips/:id/status\n\nReturns processing status for the trip.\n\nDemo Trip\n\nGET /api/v1/trips/demo\n\nReturns a sample trip for onboarding — no auth required."
      },
      {
        "title": "Items",
        "body": "Get Single Item\n\nGET /api/v1/items/:id\n\nResponse: { \"data\": <item> } — full Item shape with details_json containing confirmation numbers, seat assignments, etc.\n\nUpdate Item\n\nPATCH /api/v1/items/:id\nContent-Type: application/json\n\n{ \"summary\": \"Updated summary\", \"start_location\": \"Paris CDG\" }\n\nDelete Item\n\nDELETE /api/v1/items/:id\n\nAdd Item to Trip\n\nPOST /api/v1/trips/:id/items\nContent-Type: application/json\n\nRequired fields: kind, start_date\n\nAll fields:\n\nFieldTypeDescriptionkindstringRequired. One of: flight, hotel, car_rental, train, activity, restaurant, ticket, otherstart_datestringRequired. ISO date: YYYY-MM-DDend_datestringISO date. For hotels = checkout, flights = arrival date if differentstart_tsstringISO 8601 datetime with timezone: 2026-04-01T08:30:00Zend_tsstringISO 8601 datetime with timezonestart_locationstringDeparture/origin. City, airport code, or address (max 300 chars)end_locationstringArrival/destination (max 300 chars)summarystringOne-line summary, e.g. \"AF276 CDG→NRT\" (max 1000 chars)providerstringAirline, hotel chain, etc. e.g. \"Air France\" (max 200 chars)confirmation_codestringBooking reference (max 200 chars)traveler_namesstring[]Array of traveler names (max 20, each max 200 chars)details_jsonobjectFreeform metadata — gate, seat, room type, etc. (max 10KB)notesstringUser notesstatusstringItem status\n\nExample — Flight:\n\n{\n  \"kind\": \"flight\",\n  \"start_date\": \"2026-04-01\",\n  \"start_ts\": \"2026-04-01T08:30:00+01:00\",\n  \"end_ts\": \"2026-04-01T15:45:00+09:00\",\n  \"start_location\": \"Paris CDG\",\n  \"end_location\": \"Tokyo NRT\",\n  \"summary\": \"AF276 CDG→NRT\",\n  \"provider\": \"Air France\",\n  \"confirmation_code\": \"XK7J3M\",\n  \"traveler_names\": [\"Ian Rogers\"],\n  \"details_json\": { \"flight_number\": \"AF276\", \"seat\": \"14A\", \"class\": \"Economy\" }\n}\n\nExample — Hotel:\n\n{\n  \"kind\": \"hotel\",\n  \"start_date\": \"2026-04-01\",\n  \"end_date\": \"2026-04-05\",\n  \"start_location\": \"Tokyo, Japan\",\n  \"summary\": \"Park Hyatt Tokyo\",\n  \"provider\": \"Hyatt\",\n  \"confirmation_code\": \"HY-889923\",\n  \"traveler_names\": [\"Ian Rogers\", \"Hedvig Rogers\"],\n  \"details_json\": { \"room_type\": \"King Deluxe\", \"check_in\": \"15:00\", \"check_out\": \"11:00\" }\n}\n\nExample — Train:\n\n{\n  \"kind\": \"train\",\n  \"start_date\": \"2026-04-05\",\n  \"start_ts\": \"2026-04-05T09:00:00+09:00\",\n  \"end_ts\": \"2026-04-05T11:30:00+09:00\",\n  \"start_location\": \"Tokyo Station\",\n  \"end_location\": \"Kyoto Station\",\n  \"summary\": \"Shinkansen Nozomi 7\",\n  \"provider\": \"JR Central\",\n  \"confirmation_code\": \"JR-44521\",\n  \"details_json\": { \"car\": \"7\", \"seat\": \"3A\", \"class\": \"Green Car\" }\n}\n\nExample — Restaurant:\n\n{\n  \"kind\": \"restaurant\",\n  \"start_date\": \"2026-04-03\",\n  \"start_ts\": \"2026-04-03T19:00:00+09:00\",\n  \"start_location\": \"Sukiyabashi Jiro, Ginza, Tokyo\",\n  \"summary\": \"Dinner at Sukiyabashi Jiro\",\n  \"details_json\": { \"party_size\": 2, \"reservation_name\": \"Rogers\" }\n}\n\nExample — Ticket/Event (concert, sports, theater, festival, etc.):\n\n{\n  \"kind\": \"ticket\",\n  \"summary\": \"David Byrne at Théâtre du Châtelet\",\n  \"start_date\": \"2026-05-15\",\n  \"start_ts\": \"2026-05-15T20:00:00+02:00\",\n  \"start_location\": \"Paris\",\n  \"provider\": \"Ticketmaster\",\n  \"details_json\": {\n    \"event_name\": \"David Byrne: American Utopia\",\n    \"venue\": \"Théâtre du Châtelet\",\n    \"venue_address\": \"1 Place du Châtelet, 75001 Paris\",\n    \"performer\": \"David Byrne\",\n    \"event_time\": \"20:00\",\n    \"door_time\": \"19:00\",\n    \"section\": \"Orchestre\",\n    \"seat\": \"12\",\n    \"row\": \"G\",\n    \"ticket_count\": 2,\n    \"ticket_type\": \"Reserved\",\n    \"event_category\": \"concert\"\n  }\n}\n\nTicket detail fields:\n\nFieldTypeDescriptionevent_namestringName of the event/showvenuestringVenue namevenue_addressstring?Full addressevent_timeHH:MMShow start timedoor_timeHH:MM?Door opening timesectionstring?Seating sectionseatstring?Seat numberrowstring?Row identifierticket_countnumberNumber of ticketsticket_typestring?GA, Reserved, VIP, etc.performerstring?Artist/performer/teamevent_categoryenumconcert, theater, sports, museum, festival, other\n\nSupported ticket providers: Ticketmaster, AXS, Eventbrite, Dice, SeeTickets, StubHub, Viagogo, venue direct sales. Forward the confirmation email to trips@ubtrippin.xyz and the ticket is extracted automatically.\n\nEvent-driven trips: When a ticket email creates a new trip (no overlapping dates), the trip is named after the event/performer and the cover image is of the performer — not the city.\n\nBatch Add Items\n\nPOST /api/v1/trips/:id/items/batch\nContent-Type: application/json\n\n{ \"items\": [ <item>, <item>, ... ] }\n\nUp to 50 items per request. Same fields as single item creation above.\n\nResponse: { \"data\": [...items], \"meta\": { \"count\": N } }\n\nTip for agents: When your user gives you a booking confirmation (email text, screenshot, pasted text), parse it yourself and use these endpoints to add structured items. You handle the extraction; UBTRIPPIN handles the storage, grouping, and display.\n\nItem Status\n\nGET /api/v1/items/:id/status\n\nRefresh Item Status\n\nPOST /api/v1/items/:id/status/refresh\n\nRe-checks live status (e.g. flight delays, gate changes)."
      },
      {
        "title": "Loyalty Vault",
        "body": "List My Loyalty Programs\n\nGET /api/v1/me/loyalty\n\nResponse:\n\n{\n  \"data\": [\n    {\n      \"id\": \"uuid\",\n      \"provider_key\": \"delta_skymiles\",\n      \"provider_name\": \"Delta SkyMiles\",\n      \"member_number\": \"1234567890\",\n      \"tier\": \"Gold\",\n      \"notes\": null\n    }\n  ]\n}\n\nLookup by Provider\n\nGET /api/v1/me/loyalty/lookup?provider_key=delta_skymiles\n\nReturns matching loyalty entry for a specific provider.\n\nAdd Loyalty Program\n\nPOST /api/v1/me/loyalty\nContent-Type: application/json\n\n{ \"provider_key\": \"delta_skymiles\", \"member_number\": \"1234567890\", \"tier\": \"Gold\" }\n\nUpdate Loyalty Program\n\nPATCH /api/v1/me/loyalty/:id\nContent-Type: application/json\n\n{ \"member_number\": \"9876543210\", \"tier\": \"Platinum\" }\n\nDelete Loyalty Program\n\nDELETE /api/v1/me/loyalty/:id\n\nExport Loyalty Data\n\nGET /api/v1/me/loyalty/export\n\nReturns all loyalty data in a downloadable format.\n\nList Known Providers\n\nGET /api/v1/loyalty/providers\n\nReturns the full list of supported loyalty providers (no auth required)."
      },
      {
        "title": "Profile",
        "body": "Get My Profile\n\nGET /api/v1/me/profile\n\nResponse includes name, email, preferences, tier, and settings.\n\nUpdate My Profile\n\nPUT /api/v1/me/profile\nContent-Type: application/json\n\n{ \"display_name\": \"Ian Rogers\", \"timezone\": \"Europe/Paris\" }\n\nAlso accepts POST with the same body."
      },
      {
        "title": "Family",
        "body": "List My Families\n\nGET /api/v1/families\n\nCreate Family\n\nPOST /api/v1/families\nContent-Type: application/json\n\n{ \"name\": \"The Rogers Family\" }\n\nGet Family\n\nGET /api/v1/families/:id\n\nUpdate Family\n\nPATCH /api/v1/families/:id\nContent-Type: application/json\n\n{ \"name\": \"Updated Family Name\" }\n\nDelete Family\n\nDELETE /api/v1/families/:id\n\nInvite Member to Family\n\nPOST /api/v1/families/:id/members\nContent-Type: application/json\n\n{ \"email\": \"partner@example.com\", \"role\": \"member\" }\n\nRemove Family Member\n\nDELETE /api/v1/families/:id/members/:uid\n\nFamily Member Profiles\n\nGET /api/v1/families/:id/profiles\n\nFamily Trips\n\nGET /api/v1/families/:id/trips\n\nReturns all trips visible to family members.\n\nFamily Loyalty Programs\n\nGET /api/v1/families/:id/loyalty\n\nFamily Loyalty Lookup\n\nGET /api/v1/families/:id/loyalty/lookup?provider_key=delta_skymiles\n\nLook up a loyalty number across all family members.\n\nFamily City Guides\n\nGET /api/v1/families/:id/guides\n\nFamily Invites\n\nGET /api/v1/family-invites/:token\nPOST /api/v1/family-invites/:token/accept\n\nView and accept family invite links."
      },
      {
        "title": "Collaborators (Trip Sharing)",
        "body": "List Collaborators\n\nGET /api/v1/trips/:id/collaborators\n\nInvite Collaborator\n\nPOST /api/v1/trips/:id/collaborators\nContent-Type: application/json\n\n{ \"email\": \"friend@example.com\", \"role\": \"viewer\" }\n\nUpdate Collaborator Role\n\nPATCH /api/v1/trips/:id/collaborators/:uid\nContent-Type: application/json\n\n{ \"role\": \"editor\" }\n\nRemove Collaborator\n\nDELETE /api/v1/trips/:id/collaborators/:uid\n\nTrip Invites\n\nGET /api/v1/invites/:token\nPOST /api/v1/invites/:token/accept\n\nView and accept trip collaboration invite links."
      },
      {
        "title": "City Guides",
        "body": "List Guides\n\nGET /api/v1/guides\n\nQuery params: ?family_id=uuid (optional)\n\nCreate Guide\n\nPOST /api/v1/guides\nContent-Type: application/json\n\n{ \"city\": \"Tokyo\", \"title\": \"Tokyo Eats\" }\n\nGet Guide\n\nGET /api/v1/guides/:id\n\nUpdate Guide\n\nPATCH /api/v1/guides/:id\n\nDelete Guide\n\nDELETE /api/v1/guides/:id\n\nList Guide Entries\n\nGET /api/v1/guides/:id/entries\n\nAdd Guide Entry\n\nPOST /api/v1/guides/:id/entries\nContent-Type: application/json\n\n{ \"name\": \"Tsukiji Outer Market\", \"category\": \"food\", \"notes\": \"Go early\" }\n\nUpdate Guide Entry\n\nPATCH /api/v1/guides/:id/entries/:eid\n\nDelete Guide Entry\n\nDELETE /api/v1/guides/:id/entries/:eid\n\nNearby Guides\n\nGET /api/v1/guides/nearby?lat=35.6762&lng=139.6503\n\nFind guides near a location."
      },
      {
        "title": "Senders (Allowed Email Addresses)",
        "body": "List Senders\n\nGET /api/v1/settings/senders\n\nAdd Sender\n\nPOST /api/v1/settings/senders\nContent-Type: application/json\n\n{ \"email\": \"mywork@company.com\" }\n\nRemove Sender\n\nDELETE /api/v1/settings/senders/:id"
      },
      {
        "title": "Calendar",
        "body": "Get Calendar Token\n\nGET /api/v1/calendar/token\n\nReturns an iCal subscription URL for syncing trips to calendar apps.\n\nRegenerate Calendar Token\n\nPOST /api/v1/calendar/token\n\nInvalidates the old token and generates a new one."
      },
      {
        "title": "Notifications",
        "body": "List Notifications\n\nGET /api/v1/notifications\n\nQuery params: ?unread=true (optional)\n\nMark Notification Read\n\nPATCH /api/v1/notifications/:id\nContent-Type: application/json\n\n{ \"read\": true }"
      },
      {
        "title": "Webhooks",
        "body": "List Webhooks\n\nGET /api/v1/webhooks\n\nCreate Webhook\n\nPOST /api/v1/webhooks\nContent-Type: application/json\n\n{ \"url\": \"https://example.com/hook\", \"events\": [\"trip.created\", \"item.added\"] }\n\nGet Webhook\n\nGET /api/v1/webhooks/:id\n\nUpdate Webhook\n\nPATCH /api/v1/webhooks/:id\nContent-Type: application/json\n\n{ \"url\": \"https://example.com/new-hook\", \"active\": true }\n\nDelete Webhook\n\nDELETE /api/v1/webhooks/:id\n\nTest Webhook\n\nPOST /api/v1/webhooks/:id/test\n\nSends a test payload to verify the endpoint.\n\nWebhook Deliveries\n\nGET /api/v1/webhooks/:id/deliveries\n\nLists recent delivery attempts with status codes."
      },
      {
        "title": "Trains",
        "body": "Train Status\n\nGET /api/v1/trains/:trainNumber/status\n\nReturns real-time status for a train by number (delays, platform, etc.)."
      },
      {
        "title": "Images",
        "body": "Search Images\n\nGET /api/v1/images/search?q=tokyo+tower\n\nSearch for destination/cover images."
      },
      {
        "title": "Imports",
        "body": "List Imports\n\nGET /api/v1/imports\n\nCreate Import\n\nPOST /api/v1/imports\n\nUpload booking data for batch import.\n\nGet Import\n\nGET /api/v1/imports/:id"
      },
      {
        "title": "Billing",
        "body": "Get Subscription\n\nGET /api/v1/billing/subscription\n\nReturns current plan, tier, and billing period.\n\nGet Billing Portal URL\n\nGET /api/v1/billing/portal\n\nReturns a Stripe billing portal link for managing subscription.\n\nGet Prices\n\nGET /api/v1/billing/prices\n\nReturns available plans and pricing.\n\nCheckout\n\nPOST /api/v1/checkout\nContent-Type: application/json\n\n{ \"price_id\": \"price_xxx\" }\n\nCreates a Stripe checkout session."
      },
      {
        "title": "Activation",
        "body": "Check Activation Status\n\nGET /api/v1/activation/status\n\nReturns whether the user's account is activated."
      },
      {
        "title": "Adding New Bookings (Email Forwarding)",
        "body": "The primary way to add bookings is email forwarding. When your user receives a booking confirmation:\n\nForward the email to: trips@ubtrippin.xyz\nMust forward from their registered sender address — UBTRIPPIN rejects unknown senders.\nUBTRIPPIN's AI parser extracts the booking details automatically (usually within 30 seconds).\nThe item appears in the relevant trip (or a new trip is created).\n\nHow to do this as an agent:\n\nUse your email sending capability to forward the email from the user's address to trips@ubtrippin.xyz.\nOr instruct the user to do it manually from their inbox.\nPDF attachments (e.g. eTickets) are supported — include them in the forward.\n\nWorks with: flights, hotels, trains (Eurostar, SNCF, Thalys, etc.), rental cars, ferry bookings, concert/event tickets (Ticketmaster, AXS, Eventbrite, Dice, SeeTickets, StubHub, Viagogo), and most major booking platforms (Booking.com, Expedia, Kayak, Trainline, etc.)."
      },
      {
        "title": "\"What trips do I have coming up?\"",
        "body": "GET /api/v1/trips\nFilter by start_date >= today\nFormat and present"
      },
      {
        "title": "\"What's my itinerary for Tokyo?\"",
        "body": "GET /api/v1/trips — find the Tokyo trip ID\nGET /api/v1/trips/:id — get full itinerary with all items\nFormat chronologically by start_ts"
      },
      {
        "title": "\"I just booked a hotel in Tokyo — add it\"",
        "body": "Ask the user to forward the confirmation email from their registered address to trips@ubtrippin.xyz\nOr if you have email access: forward it yourself\nWait ~30 seconds, then GET /api/v1/trips/:id to confirm it appeared"
      },
      {
        "title": "\"What's my Delta SkyMiles number?\"",
        "body": "GET /api/v1/me/loyalty/lookup?provider_key=delta_skymiles\nReturn the member_number from the response"
      },
      {
        "title": "\"Add my Marriott Bonvoy membership\"",
        "body": "POST /api/v1/me/loyalty with { \"provider_key\": \"marriott_bonvoy\", \"member_number\": \"123456789\" }"
      },
      {
        "title": "\"What loyalty programs does my family have for Delta?\"",
        "body": "Get the family ID: GET /api/v1/families\nGET /api/v1/families/:id/loyalty/lookup?provider_key=delta_skymiles\nReturns all family members' Delta numbers"
      },
      {
        "title": "\"Add my family members\"",
        "body": "POST /api/v1/families to create a family group (if none exists)\nPOST /api/v1/families/:id/members with { \"email\": \"partner@example.com\" } for each member\nThey'll receive an invite email to accept"
      },
      {
        "title": "\"Share my trip with a friend\"",
        "body": "POST /api/v1/trips/:id/collaborators with { \"email\": \"friend@example.com\", \"role\": \"viewer\" }"
      },
      {
        "title": "\"Is my train on time?\"",
        "body": "GET /api/v1/trains/:trainNumber/status\nReport delays, platform changes, etc."
      },
      {
        "title": "\"Show me city guides near me\"",
        "body": "GET /api/v1/guides/nearby?lat=48.8566&lng=2.3522"
      },
      {
        "title": "\"Set up a webhook for new bookings\"",
        "body": "POST /api/v1/webhooks with { \"url\": \"https://...\", \"events\": [\"item.added\"] }"
      },
      {
        "title": "\"Get me a calendar link for my trips\"",
        "body": "GET /api/v1/calendar/token\nGive the user the iCal URL to add to their calendar app"
      },
      {
        "title": "Error Handling",
        "body": "StatusCodeMeaning401unauthorizedMissing/invalid API key400invalid_paramBad UUID or missing field404not_foundTrip/item not found or belongs to another user429(body varies)Rate limited — wait 60s500internal_errorServer error — retry once\n\nAll errors return: { \"error\": { \"code\": \"...\", \"message\": \"...\" } }"
      },
      {
        "title": "Notes for Agents",
        "body": "All IDs are UUIDs.\nDates are ISO 8601 (YYYY-MM-DD for dates, YYYY-MM-DDTHH:MM:SSZ for timestamps).\ndetails_json contains raw parsed data — useful for confirmation numbers, seat assignments, loyalty numbers, etc.\nconfidence (0–1): how confident the AI parser was. Items with needs_review: true may have errors.\nThe API key is the user's — never share it, log it, or store it beyond the session unless the user explicitly asks."
      },
      {
        "title": "Managing API Keys",
        "body": "Users manage keys at ubtrippin.xyz/settings. Each key has a name and a masked preview. If a key is compromised, the user can revoke it from the settings page and generate a new one."
      }
    ],
    "body": "UBTRIPPIN Skill\n\nUBTRIPPIN 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.\n\nSetup (First Time)\nAsk your user to visit ubtrippin.xyz/settings and generate an API key.\nThe key looks like: ubt_k1_<40 hex chars>. Store it securely.\nAsk for their registered sender email — the email address they use to forward bookings (typically their personal inbox). This is their \"allowed sender\" in UBTRIPPIN.\nYou'll need both to operate: the API key for reads/writes, the email address for adding new bookings via forwarding.\nAfter 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.\nAuthentication\n\nAll API calls use a Bearer token:\n\nAuthorization: Bearer ubt_k1_<your_key>\n\n\nBase URL: https://www.ubtrippin.xyz\n\nRate limit: 100 requests/minute per API key. HTTP 429 if exceeded — back off 60 seconds.\n\nAPI Endpoints\nTrips\nList All Trips\nGET /api/v1/trips\n\n\nQuery params: ?status=upcoming (optional filter)\n\nResponse:\n\n{\n  \"data\": [\n    {\n      \"id\": \"uuid\",\n      \"title\": \"Tokyo Spring 2026\",\n      \"start_date\": \"2026-04-01\",\n      \"end_date\": \"2026-04-14\",\n      \"primary_location\": \"Tokyo, Japan\",\n      \"travelers\": [\"Ian Rogers\"],\n      \"notes\": null,\n      \"cover_image_url\": \"https://...\",\n      \"share_enabled\": false,\n      \"created_at\": \"2026-02-15T10:00:00Z\",\n      \"updated_at\": \"2026-02-15T10:00:00Z\"\n    }\n  ],\n  \"meta\": { \"count\": 1 }\n}\n\n\nOrdered by start_date descending (soonest upcoming / most recent first).\n\nGet Trip with All Items\nGET /api/v1/trips/:id\n\n\nResponse 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.\n\nItem kinds: flight, hotel, train, car, ferry, activity, ticket, other\n\nCreate Trip\nPOST /api/v1/trips\nContent-Type: application/json\n\n{ \"title\": \"Summer in Provence\", \"start_date\": \"2026-07-01\", \"end_date\": \"2026-07-14\" }\n\nUpdate Trip\nPATCH /api/v1/trips/:id\nContent-Type: application/json\n\n{ \"title\": \"Updated Title\", \"notes\": \"Remember sunscreen\" }\n\nDelete Trip\nDELETE /api/v1/trips/:id\n\nRename Trip\nPOST /api/v1/trips/:id/rename\nContent-Type: application/json\n\n{ \"title\": \"New Trip Name\" }\n\nMerge Trips\nPOST /api/v1/trips/:id/merge\nContent-Type: application/json\n\n{ \"source_trip_id\": \"uuid-of-trip-to-merge-in\" }\n\n\nMerges items from the source trip into the target trip.\n\nTrip Status\nGET /api/v1/trips/:id/status\n\n\nReturns processing status for the trip.\n\nDemo Trip\nGET /api/v1/trips/demo\n\n\nReturns a sample trip for onboarding — no auth required.\n\nItems\nGet Single Item\nGET /api/v1/items/:id\n\n\nResponse: { \"data\": <item> } — full Item shape with details_json containing confirmation numbers, seat assignments, etc.\n\nUpdate Item\nPATCH /api/v1/items/:id\nContent-Type: application/json\n\n{ \"summary\": \"Updated summary\", \"start_location\": \"Paris CDG\" }\n\nDelete Item\nDELETE /api/v1/items/:id\n\nAdd Item to Trip\nPOST /api/v1/trips/:id/items\nContent-Type: application/json\n\n\nRequired fields: kind, start_date\n\nAll fields:\n\nField\tType\tDescription\nkind\tstring\tRequired. One of: flight, hotel, car_rental, train, activity, restaurant, ticket, other\nstart_date\tstring\tRequired. ISO date: YYYY-MM-DD\nend_date\tstring\tISO date. For hotels = checkout, flights = arrival date if different\nstart_ts\tstring\tISO 8601 datetime with timezone: 2026-04-01T08:30:00Z\nend_ts\tstring\tISO 8601 datetime with timezone\nstart_location\tstring\tDeparture/origin. City, airport code, or address (max 300 chars)\nend_location\tstring\tArrival/destination (max 300 chars)\nsummary\tstring\tOne-line summary, e.g. \"AF276 CDG→NRT\" (max 1000 chars)\nprovider\tstring\tAirline, hotel chain, etc. e.g. \"Air France\" (max 200 chars)\nconfirmation_code\tstring\tBooking reference (max 200 chars)\ntraveler_names\tstring[]\tArray of traveler names (max 20, each max 200 chars)\ndetails_json\tobject\tFreeform metadata — gate, seat, room type, etc. (max 10KB)\nnotes\tstring\tUser notes\nstatus\tstring\tItem status\n\nExample — Flight:\n\n{\n  \"kind\": \"flight\",\n  \"start_date\": \"2026-04-01\",\n  \"start_ts\": \"2026-04-01T08:30:00+01:00\",\n  \"end_ts\": \"2026-04-01T15:45:00+09:00\",\n  \"start_location\": \"Paris CDG\",\n  \"end_location\": \"Tokyo NRT\",\n  \"summary\": \"AF276 CDG→NRT\",\n  \"provider\": \"Air France\",\n  \"confirmation_code\": \"XK7J3M\",\n  \"traveler_names\": [\"Ian Rogers\"],\n  \"details_json\": { \"flight_number\": \"AF276\", \"seat\": \"14A\", \"class\": \"Economy\" }\n}\n\n\nExample — Hotel:\n\n{\n  \"kind\": \"hotel\",\n  \"start_date\": \"2026-04-01\",\n  \"end_date\": \"2026-04-05\",\n  \"start_location\": \"Tokyo, Japan\",\n  \"summary\": \"Park Hyatt Tokyo\",\n  \"provider\": \"Hyatt\",\n  \"confirmation_code\": \"HY-889923\",\n  \"traveler_names\": [\"Ian Rogers\", \"Hedvig Rogers\"],\n  \"details_json\": { \"room_type\": \"King Deluxe\", \"check_in\": \"15:00\", \"check_out\": \"11:00\" }\n}\n\n\nExample — Train:\n\n{\n  \"kind\": \"train\",\n  \"start_date\": \"2026-04-05\",\n  \"start_ts\": \"2026-04-05T09:00:00+09:00\",\n  \"end_ts\": \"2026-04-05T11:30:00+09:00\",\n  \"start_location\": \"Tokyo Station\",\n  \"end_location\": \"Kyoto Station\",\n  \"summary\": \"Shinkansen Nozomi 7\",\n  \"provider\": \"JR Central\",\n  \"confirmation_code\": \"JR-44521\",\n  \"details_json\": { \"car\": \"7\", \"seat\": \"3A\", \"class\": \"Green Car\" }\n}\n\n\nExample — Restaurant:\n\n{\n  \"kind\": \"restaurant\",\n  \"start_date\": \"2026-04-03\",\n  \"start_ts\": \"2026-04-03T19:00:00+09:00\",\n  \"start_location\": \"Sukiyabashi Jiro, Ginza, Tokyo\",\n  \"summary\": \"Dinner at Sukiyabashi Jiro\",\n  \"details_json\": { \"party_size\": 2, \"reservation_name\": \"Rogers\" }\n}\n\n\nExample — Ticket/Event (concert, sports, theater, festival, etc.):\n\n{\n  \"kind\": \"ticket\",\n  \"summary\": \"David Byrne at Théâtre du Châtelet\",\n  \"start_date\": \"2026-05-15\",\n  \"start_ts\": \"2026-05-15T20:00:00+02:00\",\n  \"start_location\": \"Paris\",\n  \"provider\": \"Ticketmaster\",\n  \"details_json\": {\n    \"event_name\": \"David Byrne: American Utopia\",\n    \"venue\": \"Théâtre du Châtelet\",\n    \"venue_address\": \"1 Place du Châtelet, 75001 Paris\",\n    \"performer\": \"David Byrne\",\n    \"event_time\": \"20:00\",\n    \"door_time\": \"19:00\",\n    \"section\": \"Orchestre\",\n    \"seat\": \"12\",\n    \"row\": \"G\",\n    \"ticket_count\": 2,\n    \"ticket_type\": \"Reserved\",\n    \"event_category\": \"concert\"\n  }\n}\n\n\nTicket detail fields:\n\nField\tType\tDescription\nevent_name\tstring\tName of the event/show\nvenue\tstring\tVenue name\nvenue_address\tstring?\tFull address\nevent_time\tHH:MM\tShow start time\ndoor_time\tHH:MM?\tDoor opening time\nsection\tstring?\tSeating section\nseat\tstring?\tSeat number\nrow\tstring?\tRow identifier\nticket_count\tnumber\tNumber of tickets\nticket_type\tstring?\tGA, Reserved, VIP, etc.\nperformer\tstring?\tArtist/performer/team\nevent_category\tenum\tconcert, theater, sports, museum, festival, other\n\nSupported ticket providers: Ticketmaster, AXS, Eventbrite, Dice, SeeTickets, StubHub, Viagogo, venue direct sales. Forward the confirmation email to trips@ubtrippin.xyz and the ticket is extracted automatically.\n\nEvent-driven trips: When a ticket email creates a new trip (no overlapping dates), the trip is named after the event/performer and the cover image is of the performer — not the city.\n\nBatch Add Items\nPOST /api/v1/trips/:id/items/batch\nContent-Type: application/json\n\n{ \"items\": [ <item>, <item>, ... ] }\n\n\nUp to 50 items per request. Same fields as single item creation above.\n\nResponse: { \"data\": [...items], \"meta\": { \"count\": N } }\n\nTip for agents: When your user gives you a booking confirmation (email text, screenshot, pasted text), parse it yourself and use these endpoints to add structured items. You handle the extraction; UBTRIPPIN handles the storage, grouping, and display.\n\nItem Status\nGET /api/v1/items/:id/status\n\nRefresh Item Status\nPOST /api/v1/items/:id/status/refresh\n\n\nRe-checks live status (e.g. flight delays, gate changes).\n\nLoyalty Vault\nList My Loyalty Programs\nGET /api/v1/me/loyalty\n\n\nResponse:\n\n{\n  \"data\": [\n    {\n      \"id\": \"uuid\",\n      \"provider_key\": \"delta_skymiles\",\n      \"provider_name\": \"Delta SkyMiles\",\n      \"member_number\": \"1234567890\",\n      \"tier\": \"Gold\",\n      \"notes\": null\n    }\n  ]\n}\n\nLookup by Provider\nGET /api/v1/me/loyalty/lookup?provider_key=delta_skymiles\n\n\nReturns matching loyalty entry for a specific provider.\n\nAdd Loyalty Program\nPOST /api/v1/me/loyalty\nContent-Type: application/json\n\n{ \"provider_key\": \"delta_skymiles\", \"member_number\": \"1234567890\", \"tier\": \"Gold\" }\n\nUpdate Loyalty Program\nPATCH /api/v1/me/loyalty/:id\nContent-Type: application/json\n\n{ \"member_number\": \"9876543210\", \"tier\": \"Platinum\" }\n\nDelete Loyalty Program\nDELETE /api/v1/me/loyalty/:id\n\nExport Loyalty Data\nGET /api/v1/me/loyalty/export\n\n\nReturns all loyalty data in a downloadable format.\n\nList Known Providers\nGET /api/v1/loyalty/providers\n\n\nReturns the full list of supported loyalty providers (no auth required).\n\nProfile\nGet My Profile\nGET /api/v1/me/profile\n\n\nResponse includes name, email, preferences, tier, and settings.\n\nUpdate My Profile\nPUT /api/v1/me/profile\nContent-Type: application/json\n\n{ \"display_name\": \"Ian Rogers\", \"timezone\": \"Europe/Paris\" }\n\n\nAlso accepts POST with the same body.\n\nFamily\nList My Families\nGET /api/v1/families\n\nCreate Family\nPOST /api/v1/families\nContent-Type: application/json\n\n{ \"name\": \"The Rogers Family\" }\n\nGet Family\nGET /api/v1/families/:id\n\nUpdate Family\nPATCH /api/v1/families/:id\nContent-Type: application/json\n\n{ \"name\": \"Updated Family Name\" }\n\nDelete Family\nDELETE /api/v1/families/:id\n\nInvite Member to Family\nPOST /api/v1/families/:id/members\nContent-Type: application/json\n\n{ \"email\": \"partner@example.com\", \"role\": \"member\" }\n\nRemove Family Member\nDELETE /api/v1/families/:id/members/:uid\n\nFamily Member Profiles\nGET /api/v1/families/:id/profiles\n\nFamily Trips\nGET /api/v1/families/:id/trips\n\n\nReturns all trips visible to family members.\n\nFamily Loyalty Programs\nGET /api/v1/families/:id/loyalty\n\nFamily Loyalty Lookup\nGET /api/v1/families/:id/loyalty/lookup?provider_key=delta_skymiles\n\n\nLook up a loyalty number across all family members.\n\nFamily City Guides\nGET /api/v1/families/:id/guides\n\nFamily Invites\nGET /api/v1/family-invites/:token\nPOST /api/v1/family-invites/:token/accept\n\n\nView and accept family invite links.\n\nCollaborators (Trip Sharing)\nList Collaborators\nGET /api/v1/trips/:id/collaborators\n\nInvite Collaborator\nPOST /api/v1/trips/:id/collaborators\nContent-Type: application/json\n\n{ \"email\": \"friend@example.com\", \"role\": \"viewer\" }\n\nUpdate Collaborator Role\nPATCH /api/v1/trips/:id/collaborators/:uid\nContent-Type: application/json\n\n{ \"role\": \"editor\" }\n\nRemove Collaborator\nDELETE /api/v1/trips/:id/collaborators/:uid\n\nTrip Invites\nGET /api/v1/invites/:token\nPOST /api/v1/invites/:token/accept\n\n\nView and accept trip collaboration invite links.\n\nCity Guides\nList Guides\nGET /api/v1/guides\n\n\nQuery params: ?family_id=uuid (optional)\n\nCreate Guide\nPOST /api/v1/guides\nContent-Type: application/json\n\n{ \"city\": \"Tokyo\", \"title\": \"Tokyo Eats\" }\n\nGet Guide\nGET /api/v1/guides/:id\n\nUpdate Guide\nPATCH /api/v1/guides/:id\n\nDelete Guide\nDELETE /api/v1/guides/:id\n\nList Guide Entries\nGET /api/v1/guides/:id/entries\n\nAdd Guide Entry\nPOST /api/v1/guides/:id/entries\nContent-Type: application/json\n\n{ \"name\": \"Tsukiji Outer Market\", \"category\": \"food\", \"notes\": \"Go early\" }\n\nUpdate Guide Entry\nPATCH /api/v1/guides/:id/entries/:eid\n\nDelete Guide Entry\nDELETE /api/v1/guides/:id/entries/:eid\n\nNearby Guides\nGET /api/v1/guides/nearby?lat=35.6762&lng=139.6503\n\n\nFind guides near a location.\n\nSenders (Allowed Email Addresses)\nList Senders\nGET /api/v1/settings/senders\n\nAdd Sender\nPOST /api/v1/settings/senders\nContent-Type: application/json\n\n{ \"email\": \"mywork@company.com\" }\n\nRemove Sender\nDELETE /api/v1/settings/senders/:id\n\nCalendar\nGet Calendar Token\nGET /api/v1/calendar/token\n\n\nReturns an iCal subscription URL for syncing trips to calendar apps.\n\nRegenerate Calendar Token\nPOST /api/v1/calendar/token\n\n\nInvalidates the old token and generates a new one.\n\nNotifications\nList Notifications\nGET /api/v1/notifications\n\n\nQuery params: ?unread=true (optional)\n\nMark Notification Read\nPATCH /api/v1/notifications/:id\nContent-Type: application/json\n\n{ \"read\": true }\n\nWebhooks\nList Webhooks\nGET /api/v1/webhooks\n\nCreate Webhook\nPOST /api/v1/webhooks\nContent-Type: application/json\n\n{ \"url\": \"https://example.com/hook\", \"events\": [\"trip.created\", \"item.added\"] }\n\nGet Webhook\nGET /api/v1/webhooks/:id\n\nUpdate Webhook\nPATCH /api/v1/webhooks/:id\nContent-Type: application/json\n\n{ \"url\": \"https://example.com/new-hook\", \"active\": true }\n\nDelete Webhook\nDELETE /api/v1/webhooks/:id\n\nTest Webhook\nPOST /api/v1/webhooks/:id/test\n\n\nSends a test payload to verify the endpoint.\n\nWebhook Deliveries\nGET /api/v1/webhooks/:id/deliveries\n\n\nLists recent delivery attempts with status codes.\n\nTrains\nTrain Status\nGET /api/v1/trains/:trainNumber/status\n\n\nReturns real-time status for a train by number (delays, platform, etc.).\n\nImages\nSearch Images\nGET /api/v1/images/search?q=tokyo+tower\n\n\nSearch for destination/cover images.\n\nImports\nList Imports\nGET /api/v1/imports\n\nCreate Import\nPOST /api/v1/imports\n\n\nUpload booking data for batch import.\n\nGet Import\nGET /api/v1/imports/:id\n\nBilling\nGet Subscription\nGET /api/v1/billing/subscription\n\n\nReturns current plan, tier, and billing period.\n\nGet Billing Portal URL\nGET /api/v1/billing/portal\n\n\nReturns a Stripe billing portal link for managing subscription.\n\nGet Prices\nGET /api/v1/billing/prices\n\n\nReturns available plans and pricing.\n\nCheckout\nPOST /api/v1/checkout\nContent-Type: application/json\n\n{ \"price_id\": \"price_xxx\" }\n\n\nCreates a Stripe checkout session.\n\nActivation\nCheck Activation Status\nGET /api/v1/activation/status\n\n\nReturns whether the user's account is activated.\n\nAdding New Bookings (Email Forwarding)\n\nThe primary way to add bookings is email forwarding. When your user receives a booking confirmation:\n\nForward the email to: trips@ubtrippin.xyz\nMust forward from their registered sender address — UBTRIPPIN rejects unknown senders.\nUBTRIPPIN's AI parser extracts the booking details automatically (usually within 30 seconds).\nThe item appears in the relevant trip (or a new trip is created).\n\nHow to do this as an agent:\n\nUse your email sending capability to forward the email from the user's address to trips@ubtrippin.xyz.\nOr instruct the user to do it manually from their inbox.\nPDF attachments (e.g. eTickets) are supported — include them in the forward.\n\nWorks with: flights, hotels, trains (Eurostar, SNCF, Thalys, etc.), rental cars, ferry bookings, concert/event tickets (Ticketmaster, AXS, Eventbrite, Dice, SeeTickets, StubHub, Viagogo), and most major booking platforms (Booking.com, Expedia, Kayak, Trainline, etc.).\n\nTypical Agent Workflows\n\"What trips do I have coming up?\"\nGET /api/v1/trips\nFilter by start_date >= today\nFormat and present\n\"What's my itinerary for Tokyo?\"\nGET /api/v1/trips — find the Tokyo trip ID\nGET /api/v1/trips/:id — get full itinerary with all items\nFormat chronologically by start_ts\n\"I just booked a hotel in Tokyo — add it\"\nAsk the user to forward the confirmation email from their registered address to trips@ubtrippin.xyz\nOr if you have email access: forward it yourself\nWait ~30 seconds, then GET /api/v1/trips/:id to confirm it appeared\n\"What's my Delta SkyMiles number?\"\nGET /api/v1/me/loyalty/lookup?provider_key=delta_skymiles\nReturn the member_number from the response\n\"Add my Marriott Bonvoy membership\"\nPOST /api/v1/me/loyalty with { \"provider_key\": \"marriott_bonvoy\", \"member_number\": \"123456789\" }\n\"What loyalty programs does my family have for Delta?\"\nGet the family ID: GET /api/v1/families\nGET /api/v1/families/:id/loyalty/lookup?provider_key=delta_skymiles\nReturns all family members' Delta numbers\n\"Add my family members\"\nPOST /api/v1/families to create a family group (if none exists)\nPOST /api/v1/families/:id/members with { \"email\": \"partner@example.com\" } for each member\nThey'll receive an invite email to accept\n\"Share my trip with a friend\"\nPOST /api/v1/trips/:id/collaborators with { \"email\": \"friend@example.com\", \"role\": \"viewer\" }\n\"Is my train on time?\"\nGET /api/v1/trains/:trainNumber/status\nReport delays, platform changes, etc.\n\"Show me city guides near me\"\nGET /api/v1/guides/nearby?lat=48.8566&lng=2.3522\n\"Set up a webhook for new bookings\"\nPOST /api/v1/webhooks with { \"url\": \"https://...\", \"events\": [\"item.added\"] }\n\"Get me a calendar link for my trips\"\nGET /api/v1/calendar/token\nGive the user the iCal URL to add to their calendar app\nError Handling\nStatus\tCode\tMeaning\n401\tunauthorized\tMissing/invalid API key\n400\tinvalid_param\tBad UUID or missing field\n404\tnot_found\tTrip/item not found or belongs to another user\n429\t(body varies)\tRate limited — wait 60s\n500\tinternal_error\tServer error — retry once\n\nAll errors return: { \"error\": { \"code\": \"...\", \"message\": \"...\" } }\n\nNotes for Agents\nAll IDs are UUIDs.\nDates are ISO 8601 (YYYY-MM-DD for dates, YYYY-MM-DDTHH:MM:SSZ for timestamps).\ndetails_json contains raw parsed data — useful for confirmation numbers, seat assignments, loyalty numbers, etc.\nconfidence (0–1): how confident the AI parser was. Items with needs_review: true may have errors.\nThe API key is the user's — never share it, log it, or store it beyond the session unless the user explicitly asks.\nManaging API Keys\n\nUsers manage keys at ubtrippin.xyz/settings. Each key has a name and a masked preview. If a key is compromised, the user can revoke it from the settings page and generate a new one."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/fistfulayen/ubtrippin",
    "publisherUrl": "https://clawhub.ai/fistfulayen/ubtrippin",
    "owner": "fistfulayen",
    "version": "2.3.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/ubtrippin",
    "downloadUrl": "https://openagent3.xyz/downloads/ubtrippin",
    "agentUrl": "https://openagent3.xyz/skills/ubtrippin/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ubtrippin/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ubtrippin/agent.md"
  }
}