Agent TicketWallet API TicketWallet event discovery, identity-bound account linking, and SPT checkout. This deployment targets the TicketWallet production environment. No authentication is required for catalogue endpoints. Every endpoint returns JSON except this text document. Live ticket inventory is fetched from TicketWallet only on explicit user request. Catalogue discovery is available only after a complete production sync. AGENT WORKFLOW 1. GET https://agent-ticketwallet.vercel.app/v1/catalog/schema Read the exact allowed SQL relations, columns, limits, and guidance. 2. Compose one PostgreSQL SELECT using only the published catalog_query relations. 3. GET https://agent-ticketwallet.vercel.app/v1/catalog/query Send intent, sql, and params as URL query parameters. 4. Use the returned id as the canonical TicketWallet event ID. 5. GET https://agent-ticketwallet.vercel.app/v1/catalog/events/{id} Fetch the complete stored catalogue record for one event. 6. Only when the user asks for current tickets or prices: GET https://agent-ticketwallet.vercel.app/v1/catalog/events/{id}/tickets Fetch uncached production inventory. Never prefetch, poll, or schedule it. 7. For a purchase, authenticate the caller. Public AgentCash clients follow the endpoint's SIWX challenge. A trusted server may instead send its secret X-Internal-API-Key and stable X-User-Id. Link a TicketWallet account through the OTP endpoints if no active link exists. The service stores its provider session encrypted under the authenticated identity. 8. Fetch fresh inventory, choose a quantity from splits, and skip any listing whose is_tw_ticket value is not "False". 9. GET https://agent-ticketwallet.vercel.app/v1/checkout/payment-requirements Mint one single-use Stripe SPT granted to the returned TicketWallet profile. Set the USD max_amount to ticket_price times quantity in integer cents. 10. POST https://agent-ticketwallet.vercel.app/v1/checkout with an AgentCash SIWX proof, the granted spt_ token, buyer address, and exact fresh listing facts. The service resolves and refreshes the linked TicketWallet session internally. LIVE TICKET EXAMPLE GET https://agent-ticketwallet.vercel.app/v1/catalog/events/470593/tickets?is_event_ticket=true Each ticket group includes ticket_group_id, available_quantity, price, section, row, splits, type, format, instant_delivery, is_tw_ticket, and in_hand_on. price is the per-ticket USD price with buyer fees included. Only offer quantities present in splits, and skip listings whose is_tw_ticket value is not "False". SEAT-VIEW IMAGES When helping a user browse or compare tickets, show the supplied seat-view image alongside each shortlisted option, not just its price. Prefer wide_image_path (the wide WebP view); fall back to thumbnail_image_path when the wide image is unavailable. Use the exact returned HTTPS image URL, with a caption and alt text identifying the venue and section; keep the listing's row, quantity, and all-in price beside it. In Markdown-capable clients, embed the image; otherwise provide a labeled seat-view link. These are illustrative section views, not a guarantee of the exact seat's sightline. Preserve any view_type or obstruction information in the listing. If neither image is available or loads, omit the preview rather than inventing a URL or substituting another section. Use images from the inventory already fetched for the user's request; do not poll inventory just to display photos. ACCOUNT LINKING GET /v1/account-links POST /v1/account-links/register/send-otp POST /v1/account-links/register POST /v1/account-links/login/request-otp POST /v1/account-links/login DELETE /v1/account-links/{id} These routes require either AgentCash SIWX or both trusted server headers: X-Internal-API-Key and X-User-Id. The internal key must never be exposed to an agent or browser. OTPs are six digits, expire after 30 minutes, and are single-use. Login and registration responses contain only the linked-account record. TicketWallet access and refresh tokens are encrypted in server-side storage, automatically refreshed, and never returned to callers. AUTOMATIC MPP CHECKOUT POST /v1/checkout/mpp For AgentCash card payments, submit the exact checkout body without shared_payment_token. Keep SIWX authentication (or trusted-client headers). After identity verification, the Stripe MPP 402 challenge allows the client to mint a token for TicketWallet and resend the order with a Payment Authorization credential. TicketWallet alone charges it. A 201 and Payment-Receipt confirm the purchase. Never restart negotiation after an ambiguous checkout: retain the identical credential/token and order for reconciliation or same-token retry. The challenge identifies the configured provider environment. QA requests go only to TicketWallet QA. Token mode is controlled by the issuer, not this proxy; the challenge does not itself turn a live token into a test token. DIRECT CHECKOUT GET /v1/checkout/payment-requirements Returns TicketWallet's Stripe network business profile, provider environment, and SPT constraints. SPTs are single-use and must be scoped to usd and the exact total. POST /v1/checkout Requires AgentCash SIWX or trusted server authentication and one active linked TicketWallet account. If multiple accounts are linked, set X-TicketWallet-Link to the selected twl_ ID. Send event_id, tevo_ticket_group_id, ticket_price, ticket_quantity, section, row, shared_payment_token, address_line_1, city, and zipcode. Optional fields are address_line_2, email, notes, and is_parking_ticket. Never send a TicketWallet JWT; the service obtains it from the encrypted link. If checkout times out or has an ambiguous outcome, retry with the SAME SPT. Never mint a replacement until the previous attempt is known to have failed. On 406, re-fetch inventory and re-quote. On 503 agent_cash_disabled, stop. RESTRICTED SQL EXAMPLE curl --get 'https://agent-ticketwallet.vercel.app/v1/catalog/query' \ --data-urlencode 'intent=Find ticketed Serie A events in Italy' \ --data-urlencode 'sql=SELECT id, name, start_time, league_name FROM catalog_query.events WHERE venue_country = $1 AND league_name = $2 AND has_tickets IS TRUE ORDER BY start_time LIMIT 20' \ --data-urlencode 'params=["IT","Serie A"]' FACET EXAMPLE SELECT venue_country, count(*) AS events FROM catalog_query.events GROUP BY venue_country ORDER BY events DESC LIMIT 20 Execute it with: curl --get 'https://agent-ticketwallet.vercel.app/v1/catalog/query' \ --data-urlencode 'intent=Count events by country' \ --data-urlencode 'sql=SELECT venue_country, count(*) AS events FROM catalog_query.events GROUP BY venue_country ORDER BY events DESC LIMIT 20' SIMPLE SEARCH GET https://agent-ticketwallet.vercel.app/v1/catalog/search?query=AC%20Milan&country=IT&has_tickets=true&limit=10 Supported filters: query, city, state, country, event_type, league, category, has_tickets, starts_after, starts_before, limit Country values come directly from TicketWallet and commonly use codes such as US and IT. Search results are ordered chronologically. PUBLIC ENDPOINTS GET /webmcp Open the WebMCP document to register five read-only TicketWallet site tools. Keep that page open while the agent uses the tools. GET /v1/catalog/schema Exact restricted SQL schema, policy, and agent guidance. GET /v1/catalog/query Execute one bounded, read-only PostgreSQL SELECT. GET /v1/catalog/search Convenience search over upcoming events. GET /v1/catalog/events/{id} Fetch one event by TicketWallet ID. GET /v1/catalog/events/{id}/tickets Fetch fresh production ticket groups on demand. Responses are never cached. Optional filters: is_event_ticket, is_parking_ticket. GET /openapi.json OpenAPI 3.1 specification. GET /health Service health check. BRAND ASSETS The following paths proxy the canonical production assets from ticketwallet.com: GET /favicon.ico GET /favicon-16x16.png GET /favicon-32x32.png GET /apple-touch-icon.png GET /android-chrome-192x192.png GET /android-chrome-512x512.png GET /manifest.webmanifest GET /images/ticketwallet/ticketwallet-text-white.svg SQL SAFETY AND LIMITS Only curated catalog_query views are addressable. Mutations, system tables, multiple statements, row locks, recursive or data-changing CTEs, table-valued functions, and unapproved functions or casts are rejected. Queries run in a database-enforced read-only transaction with a 1.5-second timeout and return at most 100 rows. Each client receives 30 attempts per minute and at most two concurrent queries. SQL text is retained for diagnostics and abuse prevention. Parameter values and result rows are not stored. DATA NOTES Events include venue, teams, league, category, performers, UTC start time, and TicketWallet's has_tickets catalogue hint. Use venue_timezone for local display. has_tickets is not a real-time availability guarantee. Event search and detail responses include nullable image_url and image_performer_id. Use image_url as event-card performer artwork; it is not a seat-view image. venue.lat and venue.lng contain resolved venue coordinates when available. The SQL events view exposes these as venue_lat and venue_lng. Images and coordinates are enriched after production catalogue syncs and served from local storage. Missing enrichment stays null. Do not fetch live inventory for images or location. Live inventory is not stored. TicketWallet may encode boolean-like delivery fields as "True", "False", or "None" strings. Authentication and checkout responses are never cached. Provider credentials are persisted only as authenticated encryption envelopes bound to the caller identity and TicketWallet account. The stored catalogue must come from the same production environment; QA and production IDs must never be mixed. CATALOGUE REFRESH Production syncs the complete TicketWallet catalogue at 06:00 and 18:00 UTC. Preview syncs are started through the protected internal catalogue route after Neon provisions the preview branch. Catalogue routes return 503 until the latest successful sync matches this deployment's production environment.