{"openapi":"3.1.0","info":{"title":"Dear Travel — External Agent API","version":"1.0.0","description":"Dear Travel's external agent API. One bearer key per traveller, issued by\nthat traveller in Settings → External agent. A key acts as exactly one account.\n\nThree rules the API will not bend on:\n  • The agent's mind is READ-ONLY from outside. There is no endpoint that writes it.\n  • No tool deletes anything. Adds and edits only.\n  • No tool reaches account settings.\n\nFull documentation: https://dear.travel/docs/api"},"servers":[{"url":"https://dear.travel"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"The key issued in Settings → External agent. Sent as `Authorization: Bearer dt_…`."}}},"security":[{"bearerAuth":[]}],"x-scopes":[{"scope":"travel:read","grants":"Read trips, plans, packing lists and the wishlist."},{"scope":"travel:write","grants":"Create and update trips, packing lists, items and journal entries. Never delete."},{"scope":"wallet:read","grants":"Read the travel wallet — passports, visas, trusted-traveler and elite status, card names (never numbers)."},{"scope":"mind:read","grants":"Read the agent's mind — the rendered index, and one page in full. Read only."},{"scope":"files:write","grants":"Send files along with a write, to be filed onto what it creates."},{"scope":"agent:chat","grants":"Hold a conversation with the in-app agent and act on the traveller’s behalf."}],"x-tools":[{"name":"list_trips","description":"List the traveller's trips with dates, location and plan counts. Use scope to focus: 'upcoming' (active/future), 'past', or 'all'.","parameters":{"type":"object","properties":{"scope":{"type":"string","enum":["upcoming","past","all"]}}},"scope":"travel:read","effect":"read","acceptsFiles":false},{"name":"get_trip","description":"Get one trip in detail: its plans (flights, lodging, activities, …) and packing lists. Pass the trip id (with or without the trip: prefix).","parameters":{"type":"object","properties":{"trip_id":{"type":"string"}},"required":["trip_id"]},"scope":"travel:read","effect":"read","acceptsFiles":false},{"name":"list_packing","description":"List the traveller's packing lists with packed/total counts.","parameters":{"type":"object","properties":{}},"scope":"travel:read","effect":"read","acceptsFiles":false},{"name":"list_wishlist","description":"List the traveller's saved Wishlist — places AND activities they want to do, including bucket-list items, each with status and any target timing. Use for \"what's on my wishlist\", planning ideas, or matching a trip to something they wanted to do.","parameters":{"type":"object","properties":{}},"scope":"travel:read","effect":"read","acceptsFiles":false},{"name":"list_wallet","description":"List the traveller's travel wallet — passports, residency/visa status, Global Entry / trusted-traveler programs, airline & hotel elite status, the credit cards they carry (names only, never numbers), lounge access, insurance. Use for visa/entry, lounge, best-card, alliance-perk, and document-validity questions.","parameters":{"type":"object","properties":{}},"scope":"wallet:read","effect":"read","acceptsFiles":false},{"name":"create_trip","description":"Create a new trip for the traveller. Use when they ask you to start/plan a trip. Dates are optional (they fill in as plans land). For the destination pass a plain city name in `city` (e.g. 'Lisbon'); the server resolves it. This WRITES immediately when called on this endpoint — there is no approval step here, so confirm with the traveller yourself before calling it.","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Trip name, e.g. \"Lisbon spring break\"."},"city":{"type":"string","description":"Destination city name (optional), e.g. \"Lisbon\"."},"start_date":{"type":"string","description":"YYYY-MM-DD (optional)."},"end_date":{"type":"string","description":"YYYY-MM-DD (optional)."},"trip_type":{"type":"string","enum":["solo","family","business"]}},"required":["name"]},"scope":"travel:write","effect":"add","acceptsFiles":true},{"name":"update_trip","description":"Edit an existing trip (rename, change dates, destination, or type). Pass `trip_id` and only the fields to change. To clear a date pass it as null. This WRITES immediately when called on this endpoint — there is no approval step here, so confirm with the traveller yourself before calling it.","parameters":{"type":"object","properties":{"trip_id":{"type":"string","description":"The trip id (with or without a \"trip:\" prefix)."},"name":{"type":"string"},"city":{"type":"string","description":"New destination city name; null to clear."},"start_date":{"type":"string","description":"YYYY-MM-DD, or null to clear."},"end_date":{"type":"string","description":"YYYY-MM-DD, or null to clear."},"trip_type":{"type":"string","enum":["solo","family","business"]}},"required":["trip_id"]},"scope":"travel:write","effect":"edit","acceptsFiles":true},{"name":"create_packing_list","description":"Create a new packing list, optionally pre-filled with items and linked to a trip. Use when the traveller asks you to make them a list. (For an AI-generated list from a trip's specifics, the traveller can also use the trip's “Create Packing List” button.) This WRITES immediately when called on this endpoint — there is no approval step here, so confirm with the traveller yourself before calling it.","parameters":{"type":"object","properties":{"name":{"type":"string","description":"List name, e.g. \"Lisbon essentials\"."},"items":{"type":"array","description":"Optional item labels to pre-fill, e.g. [\"Passport\", \"Sunscreen\"].","items":{"type":"string"}},"trip_id":{"type":"string","description":"Optional trip id to associate the list with."}},"required":["name"]},"scope":"travel:write","effect":"add","acceptsFiles":false},{"name":"add_packing_item","description":"Add one item to an existing packing list. Pass `list_id` and the item `label`. Use `list_packing` first to find the list id. This WRITES immediately when called on this endpoint — there is no approval step here, so confirm with the traveller yourself before calling it.","parameters":{"type":"object","properties":{"list_id":{"type":"string"},"label":{"type":"string"},"category":{"type":"string","description":"Optional grouping, e.g. \"Toiletries\"."}},"required":["list_id","label"]},"scope":"travel:write","effect":"add","acceptsFiles":false},{"name":"create_journal_entry","description":"Write a journal entry on the traveller's behalf — a note, reflection, or record of something that happened. Optionally pin it to a trip. This WRITES immediately when called on this endpoint — there is no approval step here, so confirm with the traveller yourself before calling it.","parameters":{"type":"object","properties":{"body":{"type":"string","description":"The entry text (Markdown allowed)."},"title":{"type":"string","description":"Optional short title."},"trip_id":{"type":"string","description":"Optional trip id to pin the entry to."},"entry_type":{"type":"string","enum":["note","reflection","activity","meal","place"]}},"required":["body"]},"scope":"travel:write","effect":"add","acceptsFiles":true},{"name":"read_memory","description":"Read one page of the agent's mind in full by node_id, plus its directly-connected pages. Ids come from the index at GET /api/agent/external/mind. Read only — nothing outside Dear Travel can write the mind.","parameters":{"type":"object","properties":{"node_id":{"type":"string"}},"required":["node_id"]},"scope":"mind:read","effect":"read","acceptsFiles":false}],"x-attachments":{"maxPerCall":5,"maxBytes":10485760,"encoding":"base64","accepts":["image/*","video/*","audio/*","application/pdf"],"note":"SVG is refused. Files are filed onto the record the call creates."},"paths":{"/api/agent/external/tools":{"get":{"summary":"The tool catalog for this key","description":"Every tool an external agent may call, its JSON-schema parameters, the permission it needs, and whether this key holds it. Tools the key cannot call are listed too, so an agent can ask its owner for the right permission.","responses":{"200":{"description":"The catalog."}}},"post":{"summary":"Run one tool","description":"Returns 200 even when the tool refuses or fails — a refused write is an answered request, and `ok: false` plus the sentence in `result` is the answer. 404 means the tool is not in the catalog; 403 names the permission the key is missing.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tool"],"properties":{"tool":{"type":"string","description":"A name from the catalog."},"args":{"type":"object","description":"The tool's own parameters."},"attachments":{"type":"array","description":"Up to 5 files, filed onto whatever this call creates. Requires the files:write permission.","items":{"type":"object","required":["filename","mimeType","data"],"properties":{"filename":{"type":"string"},"mimeType":{"type":"string"},"data":{"type":"string","description":"base64, no data: prefix."},"caption":{"type":"string"}}}},"correlationId":{"type":"string","description":"Echoed back, for tracing across systems."},"ownerConfirmed":{"type":"boolean","description":"Your assertion that a human approved this. Recorded, never trusted — it is not authorization."}}}}}},"responses":{"200":{"description":"The tool ran, or answered with a refusal."}}}},"/api/agent/external/mind":{"get":{"summary":"Read the agent's mind index","description":"The rendered index the in-app agent reasons over. Requires mind:read. There is no POST: the mind has exactly one author, the agent itself.","responses":{"200":{"description":"The index."}}}},"/api/agent/external/chat":{"post":{"summary":"Hand the in-app agent a whole turn","description":"Conversational entry point. Pass the returned conversationId to continue a thread. Proposed writes come back pending unless the key is marked trusted. Requires agent:chat. This is also the ONLY road by which something learned outside can reach the mind — you tell the agent, and the agent decides what to remember.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"conversationId":{"type":"string"}}}}}},"responses":{"200":{"description":"The agent replied."}}}}}}