{"openapi":"3.1.0","info":{"title":"PriceTik Agent API","version":"0.4.0","description":"Price intelligence REST API for AI agents. Provides cross-retailer price checking, buy/wait decisions, price history, deal scoring, demand intelligence, ML predictions, catalog search, visual dupe matching, webhook alerts, hotel search, hotel rate comparison, hotel deal scoring, hotel content details, hotel rate history, hotel booking-decision recommendations, hotel side-by-side comparison, hotel booking handoff, hotel watch-rate alerts, and hotel cache-side health.","contact":{"name":"PriceTik","url":"https://pricetik.com"}},"servers":[{"url":"https://api.pricetik.com/api/v1/intel","description":"Production"},{"url":"http://localhost:3001/api/v1/intel","description":"Local development"}],"security":[{"BearerAuth":[]},{"AgentFingerprint":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"Developer API key with ptk_ prefix. Required for Pro/Scale/Enterprise tiers."},"AgentFingerprint":{"type":"apiKey","in":"header","name":"X-Agent-ID","description":"Optional agent identifier for Open tier fingerprinting. Combined with IP + User-Agent for rate limiting."}},"headers":{"X-RateLimit-Tier":{"description":"Current access tier (open, pro, scale, enterprise)","schema":{"type":"string","enum":["open","pro","scale","enterprise"]}},"X-RateLimit-Limit":{"description":"Daily request limit for the current tier","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Remaining requests for the current day","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the daily limit resets","schema":{"type":"integer"}},"X-PriceTik-Cached":{"description":"Whether the response was served from cache","schema":{"type":"string","enum":["hit","miss"]}}},"schemas":{"Error":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string"}},"required":["statusCode","error","message"]}}},"paths":{"/price-check":{"get":{"operationId":"priceCheck","summary":"Check current prices across retailers","description":"Returns current prices, history summary, and deal score for a product. Available to all tiers.","parameters":[{"name":"url","in":"query","schema":{"type":"string"},"description":"Retailer product URL (mutually exclusive with productId)"},{"name":"productId","in":"query","schema":{"type":"string","format":"uuid"},"description":"PriceTik product ID (mutually exclusive with url)"}],"responses":{"200":{"description":"Price check result"},"400":{"description":"Validation error"},"404":{"description":"Product not found"},"429":{"description":"Rate limit exceeded"}}}},"/should-buy":{"get":{"operationId":"shouldBuy","summary":"Get buy/wait recommendation","description":"Returns a structured buy or wait recommendation with reasoning. ML predictions included for Pro+ tiers.","parameters":[{"name":"url","in":"query","schema":{"type":"string"}},{"name":"productId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"maxPrice","in":"query","schema":{"type":"number"},"description":"Target maximum price"},{"name":"urgency","in":"query","schema":{"type":"string","enum":["low","medium","high"],"default":"medium"}}],"responses":{"200":{"description":"Buy/wait recommendation"},"400":{"description":"Validation error"},"404":{"description":"Product not found"},"429":{"description":"Rate limit exceeded"}}}},"/price-history":{"get":{"operationId":"priceHistory","summary":"Get historical price data","description":"Returns price history with trend analysis. Day range limited by tier (Open: 7d, Pro: 180d, Scale+: 365d).","parameters":[{"name":"productId","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"days","in":"query","schema":{"type":"integer","enum":[7,30,90,180,365]}},{"name":"granularity","in":"query","schema":{"type":"string","enum":["daily","hourly"]},"description":"Hourly granularity available for Scale+ tiers"}],"responses":{"200":{"description":"Price history data"},"400":{"description":"Validation error"},"429":{"description":"Rate limit exceeded"}}}},"/deal-score":{"get":{"operationId":"dealScore","summary":"Get deal quality score (0-100)","description":"Returns a composite deal score. Full breakdown available for Pro+ tiers.","parameters":[{"name":"url","in":"query","schema":{"type":"string"}},{"name":"productId","in":"query","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deal score result"},"400":{"description":"Validation error"},"404":{"description":"Product not found"},"429":{"description":"Rate limit exceeded"}}}},"/demand":{"get":{"operationId":"demand","summary":"Get consumer demand intelligence","description":"Returns demand data including bid counts, zones, and trends. Restricted to Pro+ tiers. Set targetType=hotel with checkIn and checkOut to query hotel demand for a property and stay window.","parameters":[{"name":"productId","in":"query","required":true,"schema":{"type":"string","format":"uuid"},"description":"Product or hotel property UUID, depending on targetType."},{"name":"targetType","in":"query","schema":{"type":"string","enum":["product","hotel"],"default":"product"}},{"name":"checkIn","in":"query","schema":{"type":"string","format":"date"},"description":"Required when targetType=hotel."},{"name":"checkOut","in":"query","schema":{"type":"string","format":"date"},"description":"Required when targetType=hotel."}],"responses":{"200":{"description":"Demand intelligence data"},"400":{"description":"Validation error"},"403":{"description":"Tier restricted (Pro+ required)"},"429":{"description":"Rate limit exceeded"}}}},"/predict":{"get":{"operationId":"predict","summary":"Get ML price predictions","description":"Returns probability estimates for hitting a target price. Restricted to Pro+ tiers.","parameters":[{"name":"productId","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"targetPrice","in":"query","required":true,"schema":{"type":"number"}}],"responses":{"200":{"description":"Price prediction result"},"403":{"description":"Tier restricted (Pro+ required)"},"429":{"description":"Rate limit exceeded"}}}},"/search":{"get":{"operationId":"search","summary":"Search product catalog","description":"Search PriceTik catalog. Result limit varies by tier (Open: 10, Pro: 25, Scale+: 50).","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search query text"},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"maxPrice","in":"query","schema":{"type":"number"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Search results"},"400":{"description":"Validation error"},"429":{"description":"Rate limit exceeded"}}}},"/alerts":{"post":{"operationId":"createAlert","summary":"Create webhook alert subscription","description":"Subscribe to price condition alerts. Restricted to Pro+ tiers.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["productId","conditions","webhookUrl"],"properties":{"productId":{"type":"string","format":"uuid"},"conditions":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["price_below","price_drop_percent","historical_low"]},"value":{"type":"number"},"retailer":{"type":"string"},"window":{"type":"string"}}}},"webhookUrl":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"Alert created"},"403":{"description":"Tier restricted"},"429":{"description":"Rate limit exceeded"}}},"get":{"operationId":"listAlerts","summary":"List active webhook alerts","description":"Returns paginated list of active alerts. Restricted to Pro+ tiers.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"perPage","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Alert list"},"403":{"description":"Tier restricted"}}}},"/alerts/{alertId}":{"patch":{"operationId":"updateAlert","summary":"Update alert conditions or webhook URL","description":"Modify an existing alert subscription. Restricted to Pro+ tiers.","parameters":[{"name":"alertId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"conditions":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["price_below","price_drop_percent","historical_low","deal_score_above"]},"value":{"type":"number"},"retailer":{"type":"string"},"window":{"type":"string"}}}},"webhookUrl":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Alert updated"},"403":{"description":"Tier restricted"},"404":{"description":"Alert not found"}}},"delete":{"operationId":"deleteAlert","summary":"Delete a webhook alert","description":"Remove an alert subscription. Restricted to Pro+ tiers.","parameters":[{"name":"alertId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Alert deleted"},"403":{"description":"Tier restricted"},"404":{"description":"Alert not found"}}}},"/alerts/test/{alertId}":{"post":{"operationId":"testAlert","summary":"Send a test webhook payload","description":"Delivers a synthetic test payload to the alert's webhook URL to verify connectivity. Restricted to Pro+ tiers.","parameters":[{"name":"alertId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Test result with status code from webhook endpoint"},"403":{"description":"Tier restricted"},"404":{"description":"Alert not found"},"502":{"description":"Webhook delivery failed"}}}},"/compare":{"get":{"operationId":"compare","summary":"Side-by-side product comparison","description":"Compare two products — prices, deal scores, and retailer availability. Available to all tiers.","parameters":[{"name":"productIds","in":"query","required":true,"schema":{"type":"string"},"description":"Comma-separated pair of product UUIDs"}],"responses":{"200":{"description":"Comparison result"},"400":{"description":"Validation error (need exactly 2 IDs)"},"404":{"description":"One or both products not found"},"429":{"description":"Rate limit exceeded"}}}},"/batch-price-check":{"get":{"operationId":"batchPriceCheck","summary":"Check prices for multiple products","description":"Returns current prices for up to 10 products in a single call. Available to all tiers.","parameters":[{"name":"productIds","in":"query","required":true,"schema":{"type":"string"},"description":"Comma-separated product UUIDs (1-10)"}],"responses":{"200":{"description":"Batch price check results"},"400":{"description":"Validation error"},"429":{"description":"Rate limit exceeded"}}}},"/status":{"get":{"operationId":"status","summary":"Intel API health check","description":"Returns current API status, resolved tier, and feature flag state. Use to check availability before making calls.","responses":{"200":{"description":"Status response with feature flags"}}}},"/hotel-search":{"get":{"operationId":"hotelSearch","summary":"Search hotels by destination and dates","description":"Search hotels by destination, dates, and guest count. Returns properties with the lowest available nightly rate cached on PriceTik. Use the returned providerPropertyId with pricetik_hotel_price_check for live rates.","parameters":[{"name":"destination","in":"query","required":true,"schema":{"type":"string"},"description":"City, region, or landmark"},{"name":"checkIn","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"checkOut","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"guests","in":"query","schema":{"type":"integer","default":2}},{"name":"rooms","in":"query","schema":{"type":"integer","default":1}},{"name":"maxPrice","in":"query","schema":{"type":"number"},"description":"Max nightly rate"},{"name":"starRating","in":"query","schema":{"type":"integer","minimum":1,"maximum":5}},{"name":"segments","in":"query","schema":{"type":"array","items":{"type":"string"},"maxItems":10},"description":"Optional segment filter (e.g. Beach, Business). Comma-separated when sent as a query string."},{"name":"chainCode","in":"query","schema":{"type":"string","pattern":"^[A-Z0-9]{2,20}$"},"description":"Optional hotel chain affiliation code"},{"name":"accommodationType","in":"query","schema":{"type":"string","enum":["HOTEL","APT","RES","HOSTEL","ALL"]},"description":"Optional accommodation type filter"},{"name":"limit","in":"query","schema":{"type":"integer","default":10,"maximum":50}}],"responses":{"200":{"description":"Hotel search results"},"400":{"description":"Validation error"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/hotel-price-check":{"get":{"operationId":"hotelPriceCheck","summary":"Check hotel rates for a property","description":"Returns current cached rates for a hotel property and date range, plus a tier-aware projection of cached property content. Open tier surfaces base property fields; Pro tier adds description, top amenities, payment and rate type, and free-cancellation flag; Scale tier adds the full description, full amenities, paid extras, top points of interest, per-rate cancellation policy, and rate-comments id; Enterprise tier adds the full room catalog, property issues, and voucher facilities.","parameters":[{"name":"propertyId","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"checkIn","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"checkOut","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"roomType","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Hotel rate response"},"400":{"description":"Validation error"},"404":{"description":"Property not found"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/hotel-deal-score":{"get":{"operationId":"hotelDealScore","summary":"Get hotel deal quality score (0-100)","description":"Returns a composite deal score based on rate history, demand, seasonality, and timing. Includes a seasonalFlag block surfacing peak-window awareness.","parameters":[{"name":"propertyId","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"checkIn","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"checkOut","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Hotel deal score"},"400":{"description":"Validation error"},"404":{"description":"Property not found"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/hotel-details":{"get":{"operationId":"hotelDetails","summary":"Get hotel content details","description":"Returns cached property content (description, amenities, nearby points of interest, segments, media). Falls through to a live content fetch when the cached row is stale or missing geo, star, or gallery fields. Tier-shaped: Open tier caps amenities at 8, points of interest at 3, and description at 240 characters; Pro tier raises amenities to 15 and points of interest to 8 and may include rooms and issues when requested; Scale tier and above are unbounded and may include voucherFacilities and the full description.","parameters":[{"name":"propertyId","in":"query","schema":{"type":"string","format":"uuid"},"description":"PriceTik property UUID. Mutually exclusive with providerPropertyId."},{"name":"providerPropertyId","in":"query","schema":{"type":"string"},"description":"Provider-side property identifier. Mutually exclusive with propertyId."},{"name":"include","in":"query","schema":{"type":"string"},"description":"Comma-separated opt-in expansions: any of 'rooms', 'issues', 'voucherFacilities', 'fullDescription'."},{"name":"language","in":"query","schema":{"type":"string","minLength":2,"maxLength":5,"default":"en"},"description":"ISO 639-1 language code for resolving segment and category labels."}],"responses":{"200":{"description":"Hotel details response"},"400":{"description":"Validation error"},"404":{"description":"Property not found"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/hotel-rate-history":{"get":{"operationId":"hotelRateHistory","summary":"Get hotel rate history","description":"Returns a daily best-rate-across-providers series for a property, plus a deterministic OLS trend slope and a one-line headline. Days are tier-clamped: Open tier up to 7 days, Pro tier up to 90 days, Scale and Enterprise tiers up to 180 days.","parameters":[{"name":"propertyId","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"checkIn","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"checkOut","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"days","in":"query","required":true,"schema":{"type":"integer","enum":[7,30,90,180]}},{"name":"currency","in":"query","schema":{"type":"string","minLength":3,"maxLength":3},"description":"Optional ISO 4217 currency code."}],"responses":{"200":{"description":"Hotel rate history response"},"400":{"description":"Validation error"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/hotel-should-book":{"get":{"operationId":"hotelShouldBook","summary":"Get a book/wait/watch recommendation for a hotel stay","description":"Composes a deterministic book_now / wait / watch recommendation with a confidence score and a template-composed reasoning string. No LLM is invoked. Combines trend slope, demand zone, seasonal flag, free-cancellation policy, and budget fit.","parameters":[{"name":"propertyId","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"checkIn","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"checkOut","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"guests","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":10}},{"name":"rooms","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":5}},{"name":"maxNightlyRate","in":"query","schema":{"type":"number","exclusiveMinimum":0},"description":"Optional ceiling used to evaluate the budget-fit input."},{"name":"urgency","in":"query","schema":{"type":"string","enum":["low","medium","high"]}}],"responses":{"200":{"description":"Should-book recommendation"},"400":{"description":"Validation error"},"404":{"description":"Property not found"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/hotel-compare":{"get":{"operationId":"hotelCompare","summary":"Side-by-side hotel comparison","description":"Compares two to four hotel properties side by side using cached property content, current best rate, and cached deal score. Optional reference point of interest powers a per-row haversine distance. Response order matches input order.","parameters":[{"name":"propertyIds","in":"query","required":true,"schema":{"type":"string"},"description":"Comma-separated PriceTik UUIDs (2 to 4 entries)."},{"name":"checkIn","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"checkOut","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"guests","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":10}},{"name":"rooms","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":5}},{"name":"referencePoi","in":"query","schema":{"type":"string"},"description":"Optional JSON-encoded reference point with name, latitude, longitude."}],"responses":{"200":{"description":"Hotel comparison rows"},"400":{"description":"Validation error (need 2 to 4 propertyIds)"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/hotel-booking-url":{"get":{"operationId":"hotelBookingUrl","summary":"Compose a signed hotel booking deep link","description":"Returns a signed booking deep link wrapped in /go/{click_id} for attribution. Refreshes the rateKey via a single live availability check when within 2 minutes of expiry or when rateType is RECHECK. PriceTik never sells packaged rates hotel-only; packaging-only rates return 422 PackagingDenied. Expired rateKeys return 410 with retryWith pricetik_hotel_price_check so the agent can re-price deterministically.","parameters":[{"name":"rateKey","in":"query","required":true,"schema":{"type":"string"}},{"name":"providerPropertyId","in":"query","required":true,"schema":{"type":"string"}},{"name":"checkIn","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"checkOut","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"guests","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":10}},{"name":"rooms","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":5}},{"name":"children","in":"query","schema":{"type":"integer","minimum":0,"maximum":8}},{"name":"childrenAges","in":"query","schema":{"type":"string"},"description":"Comma-separated ages; length must equal children count when both are present."},{"name":"holderEmail","in":"query","schema":{"type":"string","format":"email"}}],"responses":{"200":{"description":"Signed booking URL with expiresAt and currentBest block"},"400":{"description":"Validation error"},"410":{"description":"RateKeyExpired — re-price via pricetik_hotel_price_check"},"422":{"description":"PackagingDenied — rate may not be sold hotel-only"},"429":{"description":"Rate limit exceeded"},"500":{"description":"Signer failure"},"503":{"description":"Upstream availability check unavailable, or hotel tools disabled"}}}},"/hotel-watch-rate":{"post":{"operationId":"hotelWatchRate","summary":"Subscribe to a hotel rate webhook alert","description":"Persists a Pro+ webhook alert that fires when the cross-provider best nightly rate hits or drops below the supplied target. Defaults expiresAt to checkIn minus 48 hours when omitted. Webhook URLs must be HTTPS; signed delivery uses HMAC-SHA256 with the developer key webhook secret.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["propertyId","checkIn","checkOut","guests","rooms","targetNightlyRate","webhookUrl"],"properties":{"propertyId":{"type":"string","format":"uuid"},"checkIn":{"type":"string","format":"date"},"checkOut":{"type":"string","format":"date"},"guests":{"type":"integer","minimum":1,"maximum":10},"rooms":{"type":"integer","minimum":1,"maximum":5},"targetNightlyRate":{"type":"number","exclusiveMinimum":0},"currency":{"type":"string","minLength":3,"maxLength":3,"default":"USD"},"webhookUrl":{"type":"string","format":"uri","pattern":"^https://"},"expiresAt":{"type":"string","description":"ISO 8601 timestamp. Must be before checkIn."}}}}}},"responses":{"201":{"description":"Hotel watch-rate alert created"},"400":{"description":"Validation error or per-tier alert budget exceeded"},"401":{"description":"Unauthorized — missing developer API key"},"403":{"description":"Tier restricted — Pro+ required"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/hotel-status":{"get":{"operationId":"hotelStatus","summary":"Hotel cache-side health snapshot","description":"Reports cache-side health only: content cache row count and freshness, rate-history coverage in the trailing 24 hours, type catalog row counts and recency, and refresh-worker classifications. Available to all tiers under the hotel free-tier path. Does NOT surface live partner-side quota numbers.","responses":{"200":{"description":"Hotel status snapshot"},"400":{"description":"Validation error (no parameters accepted)"},"503":{"description":"Hotel tools temporarily disabled"}}}},"/alerts/{alertId}/deliveries":{"get":{"operationId":"alertDeliveries","summary":"View webhook delivery history","description":"Returns the last 20 delivery attempts for an alert including status codes and latency. Restricted to Pro+ tiers.","parameters":[{"name":"alertId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Delivery history"},"403":{"description":"Tier restricted"},"404":{"description":"Alert not found"}}}}}}