{"openapi":"3.1.0","info":{"title":"LuxAlgo public API","version":"1.0.0","description":"The public, unauthenticated surface of the LuxAlgo app API: payment plans, prop-firm data (including a filterable query surface for firms, challenges, and offers), the indicator library, marketing state, and the Vela for desktop installers published for download. Every response is wrapped in a { data, errors } envelope — data on success, errors[] on failure. The full indicator library is also available as an MCP server at https://mcp.luxalgo.com/mcp, and site content as markdown via https://www.luxalgo.com/llms.txt."},"servers":[{"url":"https://app.luxalgo.com"}],"paths":{"/api/payments/plans":{"get":{"summary":"Get all the available payment plans","tags":["payments"],"parameters":[{"name":"country","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Z]{2}$"}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"plans":{"type":"array","items":{"type":"object","properties":{"tier":{"type":"string","enum":["essential","premium","ultimate","ultra"]},"imageSrc":{"type":"string"},"isFeatured":{"type":"boolean"},"yearlySavingsPercent":{"type":"number"},"aiUsage":{"anyOf":[{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"multiple"},"multiple":{"type":"number"},"versusTier":{"type":"string","enum":["free","essential","premium","ultimate","ultra"]}},"required":["kind","multiple","versusTier"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"more-than"},"versusTier":{"type":"string","enum":["free","essential"]}},"required":["kind","versusTier"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"included"},"sizedToLocalPrice":{"type":"boolean"}},"required":["kind","sizedToLocalPrice"],"additionalProperties":false}]},{"type":"null"}]},"byInterval":{"type":"object","properties":{"monthly":{"type":"object","properties":{"isActive":{"type":"boolean"},"description":{"type":"string"},"featuresHeading":{"type":"string"},"features":{"type":"array","items":{"type":"string"}},"hierarchyOrder":{"type":"number"},"product":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"price":{"type":"object","properties":{"id":{"type":"string"},"currency":{"type":"string"},"amountInCents":{"type":"object","properties":{"monthly":{"type":"object","properties":{"regular":{"type":"number"},"discounted":{"type":"number"}},"required":["regular","discounted"],"additionalProperties":false},"yearly":{"type":"object","properties":{"regular":{"type":"number"},"discounted":{"type":"number"}},"required":["regular","discounted"],"additionalProperties":false}},"required":["monthly","yearly"],"additionalProperties":false},"coupon":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"percentOff":{"type":"number"},"perks":{"anyOf":[{"type":"object","properties":{"purchase":{"anyOf":[{"type":"object","properties":{"freeMonths":{"type":"number"},"aiCredits":{"type":"number"}},"required":["freeMonths","aiCredits"],"additionalProperties":false},{"type":"null"}]},"stacking":{"type":"array","items":{"type":"object","properties":{"years":{"type":"number"},"freeMonths":{"type":"number"},"aiCredits":{"type":"number"}},"required":["years","freeMonths","aiCredits"],"additionalProperties":false}},"maxButton":{"type":"object","properties":{"enabled":{"type":"boolean"},"bonusFreeMonths":{"type":"number"},"bonusAiCredits":{"type":"number"}},"required":["enabled","bonusFreeMonths","bonusAiCredits"],"additionalProperties":false}},"required":["purchase","stacking","maxButton"],"additionalProperties":false},{"type":"null"}]}},"required":["id","name","percentOff"],"additionalProperties":false},{"type":"null"}]}},"required":["id","currency","amountInCents","coupon"],"additionalProperties":false}},"required":["isActive","description","featuresHeading","features","hierarchyOrder","product","price"],"additionalProperties":false},"yearly":{"type":"object","properties":{"isActive":{"type":"boolean"},"description":{"type":"string"},"featuresHeading":{"type":"string"},"features":{"type":"array","items":{"type":"string"}},"hierarchyOrder":{"type":"number"},"product":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"price":{"type":"object","properties":{"id":{"type":"string"},"currency":{"type":"string"},"amountInCents":{"type":"object","properties":{"monthly":{"type":"object","properties":{"regular":{"type":"number"},"discounted":{"type":"number"}},"required":["regular","discounted"],"additionalProperties":false},"yearly":{"type":"object","properties":{"regular":{"type":"number"},"discounted":{"type":"number"}},"required":["regular","discounted"],"additionalProperties":false}},"required":["monthly","yearly"],"additionalProperties":false},"coupon":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"percentOff":{"type":"number"},"perks":{"anyOf":[{"type":"object","properties":{"purchase":{"anyOf":[{"type":"object","properties":{"freeMonths":{"type":"number"},"aiCredits":{"type":"number"}},"required":["freeMonths","aiCredits"],"additionalProperties":false},{"type":"null"}]},"stacking":{"type":"array","items":{"type":"object","properties":{"years":{"type":"number"},"freeMonths":{"type":"number"},"aiCredits":{"type":"number"}},"required":["years","freeMonths","aiCredits"],"additionalProperties":false}},"maxButton":{"type":"object","properties":{"enabled":{"type":"boolean"},"bonusFreeMonths":{"type":"number"},"bonusAiCredits":{"type":"number"}},"required":["enabled","bonusFreeMonths","bonusAiCredits"],"additionalProperties":false}},"required":["purchase","stacking","maxButton"],"additionalProperties":false},{"type":"null"}]}},"required":["id","name","percentOff"],"additionalProperties":false},{"type":"null"}]}},"required":["id","currency","amountInCents","coupon"],"additionalProperties":false}},"required":["isActive","description","featuresHeading","features","hierarchyOrder","product","price"],"additionalProperties":false}},"required":["monthly","yearly"],"additionalProperties":false}},"required":["tier","isFeatured","yearlySavingsPercent","byInterval"],"additionalProperties":false}}},"required":["plans"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/propfirms/list":{"get":{"summary":"Public: list visible propfirms with offers, challenges and overview","tags":["propfirms"],"parameters":[],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"propfirms":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"yearFounded":{"anyOf":[{"type":"number"},{"type":"null"}]},"productTypes":{"type":"array","items":{"type":"string"}},"commissionAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"countryIso2":{"anyOf":[{"type":"string"},{"type":"null"}]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"isPreferredPartner":{"type":"boolean"},"isVisible":{"type":"boolean"},"logoImageUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"paymentMethods":{"type":"array","items":{"type":"string"}},"payoutMethods":{"type":"array","items":{"type":"string"}},"restrictedCountries":{"type":"array","items":{"type":"string"}},"reviewsTrustPilotCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"reviewsTrustPilotScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"tradedMarketTypes":{"type":"array","items":{"type":"string"}},"tradingPlatforms":{"type":"array","items":{"type":"string"}},"id":{"type":"string"},"propfirmId":{"type":"string"},"offers":{"type":"array","items":{"type":"object","properties":{"offerId":{"type":"string"},"propfirmId":{"type":"string"},"promoCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"affiliateLink":{"anyOf":[{"type":"string"},{"type":"null"}]},"discountIsPercent":{"type":"boolean"},"discountValue":{"anyOf":[{"type":"number"},{"type":"null"}]},"shortDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"fullDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"isActive":{"type":"boolean"},"isFeatured":{"type":"boolean"},"hasEndDate":{"type":"boolean"},"endsAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"scopeType":{"anyOf":[{"type":"string"},{"type":"null"}]},"scopeRaw":{}},"required":["offerId","propfirmId","promoCode","affiliateLink","discountIsPercent","discountValue","shortDescription","fullDescription","isActive","isFeatured","hasEndDate","endsAt","scopeType","scopeRaw"],"additionalProperties":false}},"challenges":{"type":"array","items":{"type":"object","properties":{"challengeId":{"type":"string"},"challengeName":{"type":"string"},"accountSize":{"type":"number"},"steps":{"type":"number"},"profitTarget":{"type":"array","items":{"type":"number"}},"profitTargetIsPercent":{"type":"boolean"},"minTradingDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"dailyLoss":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxLoss":{"anyOf":[{"type":"number"},{"type":"null"}]},"dailyLossType":{"anyOf":[{"type":"string"},{"type":"null"}]},"maxLossType":{"anyOf":[{"type":"string"},{"type":"null"}]},"lossIsPercent":{"type":"boolean"},"maxLeverage":{"anyOf":[{"type":"number"},{"type":"null"}]},"newsTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"copyTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"autoTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"weekendHolding":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"overnightHolding":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"stoplossRequired":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"activationFee":{"anyOf":[{"type":"number"},{"type":"null"}]},"resetFee":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxContractSize":{"anyOf":[{"type":"object","properties":{"minis":{"anyOf":[{"type":"number"},{"type":"null"}]},"micros":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["minis","micros"],"additionalProperties":false},{"type":"null"}]},"profitSplitPercent":{"anyOf":[{"type":"number"},{"type":"null"}]},"profitSplitDetails":{"anyOf":[{"type":"string"},{"type":"null"}]},"payoutFrequency":{"anyOf":[{"type":"string"},{"type":"null"}]},"isFeeRefundable":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"price":{"anyOf":[{"type":"number"},{"type":"null"}]},"interval":{"anyOf":[{"type":"string"},{"type":"null"}]},"maxLossMode":{"anyOf":[{"type":"string","enum":["static-initial","trailing-realized-eod","trailing-intraday-unrealized"]},{"type":"null"}]},"maxLossLocksAtInitial":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"maxLossLockOffset":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxLossIsPercent":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"dailyLossBasis":{"anyOf":[{"type":"string","enum":["prior-day-balance","prior-day-equity"]},{"type":"null"}]},"dailyLossLimitBasis":{"anyOf":[{"type":"string","enum":["initial-balance","anchor"]},{"type":"null"}]},"dailyLossIncludesOpenPnl":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"dailyLossEvaluation":{"anyOf":[{"type":"string","enum":["intraday","end-of-day"]},{"type":"null"}]},"dailyLossIsPercent":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"consistencyMaxBestDayPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutIntervalDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMinWinningDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutWinningDayMinProfit":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMaxPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMaxAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutBufferAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"fundedConsistencyPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"firstPayoutMinDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"feeCurrency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]},"sourceUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastVerifiedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["challengeId","challengeName","accountSize","steps","profitTarget","profitTargetIsPercent","minTradingDays","dailyLoss","maxLoss","dailyLossType","maxLossType","lossIsPercent","maxLeverage","newsTrading","copyTrading","autoTrading","weekendHolding","overnightHolding","stoplossRequired","activationFee","resetFee","maxContractSize","profitSplitPercent","profitSplitDetails","payoutFrequency","isFeeRefundable","price","interval"],"additionalProperties":false}},"overview":{"type":"object","properties":{"about":{"type":"string"},"leverage":{"type":"string"},"rules":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"payoutPolicy":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"faq":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["about","leverage","rules","payoutPolicy","faq"],"additionalProperties":false}},"required":["name","yearFounded","productTypes","commissionAmount","countryIso2","currency","isPreferredPartner","isVisible","logoImageUrl","paymentMethods","payoutMethods","restrictedCountries","reviewsTrustPilotCount","reviewsTrustPilotScore","tradedMarketTypes","tradingPlatforms","id","propfirmId","offers","challenges","overview"],"additionalProperties":false}}},"required":["propfirms"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/propfirms/query":{"get":{"summary":"Public: search visible prop firms. Combine firm, challenge, and offer filters; omit filters to list all. Nested challenge/offer filters match a firm when at least one child matches. Use include=challenges,offers,overview to nest matching children.","tags":["propfirms"],"parameters":[{"name":"text","in":"query","required":false,"schema":{"description":"Case-insensitive search over firm name and public slug.","type":"string"}},{"name":"id","in":"query","required":false,"schema":{"description":"Comma-separated internal firm ids.","type":"string"}},{"name":"propfirmId","in":"query","required":false,"schema":{"description":"Comma-separated public firm slugs (e.g. ftmo).","type":"string"}},{"name":"productTypes","in":"query","required":false,"schema":{"description":"Comma-separated product types (CFD, Futures). Firm must offer at least one.","type":"string"}},{"name":"tradedMarketTypes","in":"query","required":false,"schema":{"description":"Comma-separated markets (forex, indices, …). Firm must offer at least one.","type":"string"}},{"name":"tradingPlatforms","in":"query","required":false,"schema":{"description":"Comma-separated platforms (MT5, TradingView, …). Firm must offer at least one.","type":"string"}},{"name":"paymentMethods","in":"query","required":false,"schema":{"description":"Comma-separated payment methods. Firm must offer at least one.","type":"string"}},{"name":"payoutMethods","in":"query","required":false,"schema":{"description":"Comma-separated payout methods. Firm must offer at least one.","type":"string"}},{"name":"countryIso2","in":"query","required":false,"schema":{"description":"Comma-separated ISO-2 headquarters countries.","type":"string"}},{"name":"currency","in":"query","required":false,"schema":{"description":"Comma-separated account currencies (e.g. usd, eur).","type":"string"}},{"name":"isPreferredPartner","in":"query","required":false,"schema":{"description":"Only preferred-partner firms when true.","type":"string","enum":["true","false"]}},{"name":"availableIn","in":"query","required":false,"schema":{"description":"Comma-separated country names. Firm must not list any of them as restricted (e.g. United States).","type":"string"}},{"name":"minTrustPilotScore","in":"query","required":false,"schema":{"description":"Minimum Trustpilot score.","type":"string"}},{"name":"minTrustPilotCount","in":"query","required":false,"schema":{"description":"Minimum Trustpilot review count.","type":"string"}},{"name":"minYearFounded","in":"query","required":false,"schema":{"description":"Inclusive minimum year founded.","type":"string"}},{"name":"maxYearFounded","in":"query","required":false,"schema":{"description":"Inclusive maximum year founded.","type":"string"}},{"name":"hasActiveOffer","in":"query","required":false,"schema":{"description":"When true, firm must currently have a live (active, unexpired) offer.","type":"string","enum":["true","false"]}},{"name":"challengeId","in":"query","required":false,"schema":{"description":"Comma-separated public challenge ids.","type":"string"}},{"name":"challengeName","in":"query","required":false,"schema":{"description":"Case-insensitive substring of the challenge name.","type":"string"}},{"name":"accountSizeMin","in":"query","required":false,"schema":{"description":"Minimum account size (inclusive).","type":"string"}},{"name":"accountSizeMax","in":"query","required":false,"schema":{"description":"Maximum account size (inclusive).","type":"string"}},{"name":"steps","in":"query","required":false,"schema":{"description":"Exact evaluation step count (1 = instant / funded, 2 = two-step, …).","type":"string"}},{"name":"stepsMin","in":"query","required":false,"schema":{"description":"Minimum evaluation step count (ignored when steps is set).","type":"string"}},{"name":"stepsMax","in":"query","required":false,"schema":{"description":"Maximum evaluation step count (ignored when steps is set).","type":"string"}},{"name":"priceMin","in":"query","required":false,"schema":{"description":"Minimum challenge fee (inclusive).","type":"string"}},{"name":"priceMax","in":"query","required":false,"schema":{"description":"Maximum challenge fee (inclusive).","type":"string"}},{"name":"profitSplitMin","in":"query","required":false,"schema":{"description":"Minimum trader profit-split percent.","type":"string"}},{"name":"maxLeverageMin","in":"query","required":false,"schema":{"description":"Minimum max leverage.","type":"string"}},{"name":"minTradingDaysMax","in":"query","required":false,"schema":{"description":"Maximum required minimum trading days (less-strict challenges).","type":"string"}},{"name":"dailyLossMax","in":"query","required":false,"schema":{"description":"Maximum daily-loss limit magnitude (smaller number = stricter; this is an upper bound).","type":"string"}},{"name":"maxLossMax","in":"query","required":false,"schema":{"description":"Maximum overall-loss limit magnitude.","type":"string"}},{"name":"maxLossMode","in":"query","required":false,"schema":{"description":"Comma-separated drawdown modes: static-initial, trailing-realized-eod, trailing-intraday-unrealized. Challenges without a captured mode never match.","type":"string"}},{"name":"newsTrading","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"copyTrading","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"autoTrading","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"weekendHolding","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"overnightHolding","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"stoplossRequired","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"isFeeRefundable","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"interval","in":"query","required":false,"schema":{"description":"Comma-separated challenge fee intervals (e.g. one-time, monthly).","type":"string"}},{"name":"offerId","in":"query","required":false,"schema":{"description":"Comma-separated public offer ids.","type":"string"}},{"name":"promoCode","in":"query","required":false,"schema":{"description":"Case-insensitive substring of the promo code.","type":"string"}},{"name":"offerText","in":"query","required":false,"schema":{"description":"Case-insensitive search over promo code and offer descriptions.","type":"string"}},{"name":"isActive","in":"query","required":false,"schema":{"description":"Defaults to live offers only. Pass false to look at inactive offers.","type":"string","enum":["true","false"]}},{"name":"isFeatured","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"discountIsPercent","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"discountMin","in":"query","required":false,"schema":{"description":"Minimum discount value (percent or absolute, matching discountIsPercent).","type":"string"}},{"name":"discountMax","in":"query","required":false,"schema":{"description":"Maximum discount value.","type":"string"}},{"name":"includeInactive","in":"query","required":false,"schema":{"description":"When true, inactive offers are not hidden. Defaults to false.","type":"string","enum":["true","false"]}},{"name":"includeExpired","in":"query","required":false,"schema":{"description":"When true, ended offers are not hidden. Defaults to false.","type":"string","enum":["true","false"]}},{"name":"pageIndex","in":"query","required":false,"schema":{"description":"0-based page index. Defaults to 0.","type":"string"}},{"name":"pageQuantity","in":"query","required":false,"schema":{"description":"Page size. Defaults to 50, capped at 100.","type":"string"}},{"name":"direction","in":"query","required":false,"schema":{"description":"Sort direction. Defaults per sort key.","type":"string","enum":["asc","desc"]}},{"name":"include","in":"query","required":false,"schema":{"description":"Comma-separated extra payloads: challenges, offers, overview.","type":"string"}},{"name":"sort","in":"query","required":false,"schema":{"description":"Defaults to name.","type":"string","enum":["name","yearFounded","reviewsTrustPilotScore","reviewsTrustPilotCount"]}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"firms":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"yearFounded":{"anyOf":[{"type":"number"},{"type":"null"}]},"productTypes":{"type":"array","items":{"type":"string"}},"commissionAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"countryIso2":{"anyOf":[{"type":"string"},{"type":"null"}]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"isPreferredPartner":{"type":"boolean"},"isVisible":{"type":"boolean"},"logoImageUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"paymentMethods":{"type":"array","items":{"type":"string"}},"payoutMethods":{"type":"array","items":{"type":"string"}},"restrictedCountries":{"type":"array","items":{"type":"string"}},"reviewsTrustPilotCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"reviewsTrustPilotScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"tradedMarketTypes":{"type":"array","items":{"type":"string"}},"tradingPlatforms":{"type":"array","items":{"type":"string"}},"id":{"type":"string"},"propfirmId":{"type":"string"},"offers":{"type":"array","items":{"type":"object","properties":{"offerId":{"type":"string"},"firmId":{"type":"string"},"propfirmId":{"type":"string"},"propfirmName":{"type":"string"},"promoCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"affiliateLink":{"anyOf":[{"type":"string"},{"type":"null"}]},"discountIsPercent":{"type":"boolean"},"discountValue":{"anyOf":[{"type":"number"},{"type":"null"}]},"shortDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"fullDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"isActive":{"type":"boolean"},"isFeatured":{"type":"boolean"},"hasEndDate":{"type":"boolean"},"endsAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"scope":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"all_challenges"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"specific_challenges"},"challengeIds":{"type":"array","items":{"type":"string"}}},"required":["type","challengeIds"],"additionalProperties":false}]}},"required":["offerId","firmId","propfirmId","propfirmName","promoCode","affiliateLink","discountIsPercent","discountValue","shortDescription","fullDescription","isActive","isFeatured","hasEndDate","endsAt","scope"],"additionalProperties":false}},"challenges":{"type":"array","items":{"type":"object","properties":{"challengeId":{"type":"string"},"challengeName":{"type":"string"},"accountSize":{"type":"number"},"steps":{"type":"number"},"profitTarget":{"type":"array","items":{"type":"number"}},"profitTargetIsPercent":{"type":"boolean"},"minTradingDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"dailyLoss":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxLoss":{"anyOf":[{"type":"number"},{"type":"null"}]},"dailyLossType":{"anyOf":[{"type":"string"},{"type":"null"}]},"maxLossType":{"anyOf":[{"type":"string"},{"type":"null"}]},"lossIsPercent":{"type":"boolean"},"maxLeverage":{"anyOf":[{"type":"number"},{"type":"null"}]},"newsTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"copyTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"autoTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"weekendHolding":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"overnightHolding":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"stoplossRequired":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"activationFee":{"anyOf":[{"type":"number"},{"type":"null"}]},"resetFee":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxContractSize":{"anyOf":[{"type":"object","properties":{"minis":{"anyOf":[{"type":"number"},{"type":"null"}]},"micros":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["minis","micros"],"additionalProperties":false},{"type":"null"}]},"profitSplitPercent":{"anyOf":[{"type":"number"},{"type":"null"}]},"profitSplitDetails":{"anyOf":[{"type":"string"},{"type":"null"}]},"payoutFrequency":{"anyOf":[{"type":"string"},{"type":"null"}]},"isFeeRefundable":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"price":{"anyOf":[{"type":"number"},{"type":"null"}]},"interval":{"anyOf":[{"type":"string"},{"type":"null"}]},"maxLossMode":{"anyOf":[{"type":"string","enum":["static-initial","trailing-realized-eod","trailing-intraday-unrealized"]},{"type":"null"}]},"maxLossLocksAtInitial":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"maxLossLockOffset":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxLossIsPercent":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"dailyLossBasis":{"anyOf":[{"type":"string","enum":["prior-day-balance","prior-day-equity"]},{"type":"null"}]},"dailyLossLimitBasis":{"anyOf":[{"type":"string","enum":["initial-balance","anchor"]},{"type":"null"}]},"dailyLossIncludesOpenPnl":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"dailyLossEvaluation":{"anyOf":[{"type":"string","enum":["intraday","end-of-day"]},{"type":"null"}]},"dailyLossIsPercent":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"consistencyMaxBestDayPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutIntervalDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMinWinningDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutWinningDayMinProfit":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMaxPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMaxAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutBufferAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"fundedConsistencyPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"firstPayoutMinDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"feeCurrency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]},"sourceUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastVerifiedAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"firmId":{"type":"string"},"propfirmId":{"type":"string"},"propfirmName":{"type":"string"},"offers":{"type":"array","items":{"type":"object","properties":{"offerId":{"type":"string"},"firmId":{"type":"string"},"propfirmId":{"type":"string"},"propfirmName":{"type":"string"},"promoCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"affiliateLink":{"anyOf":[{"type":"string"},{"type":"null"}]},"discountIsPercent":{"type":"boolean"},"discountValue":{"anyOf":[{"type":"number"},{"type":"null"}]},"shortDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"fullDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"isActive":{"type":"boolean"},"isFeatured":{"type":"boolean"},"hasEndDate":{"type":"boolean"},"endsAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"scope":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"all_challenges"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"specific_challenges"},"challengeIds":{"type":"array","items":{"type":"string"}}},"required":["type","challengeIds"],"additionalProperties":false}]}},"required":["offerId","firmId","propfirmId","propfirmName","promoCode","affiliateLink","discountIsPercent","discountValue","shortDescription","fullDescription","isActive","isFeatured","hasEndDate","endsAt","scope"],"additionalProperties":false}}},"required":["challengeId","challengeName","accountSize","steps","profitTarget","profitTargetIsPercent","minTradingDays","dailyLoss","maxLoss","dailyLossType","maxLossType","lossIsPercent","maxLeverage","newsTrading","copyTrading","autoTrading","weekendHolding","overnightHolding","stoplossRequired","activationFee","resetFee","maxContractSize","profitSplitPercent","profitSplitDetails","payoutFrequency","isFeeRefundable","price","interval","firmId","propfirmId","propfirmName"],"additionalProperties":false}},"overview":{"type":"object","properties":{"about":{"type":"string"},"leverage":{"type":"string"},"rules":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"payoutPolicy":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"faq":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["about","leverage","rules","payoutPolicy","faq"],"additionalProperties":false}},"required":["name","yearFounded","productTypes","commissionAmount","countryIso2","currency","isPreferredPartner","isVisible","logoImageUrl","paymentMethods","payoutMethods","restrictedCountries","reviewsTrustPilotCount","reviewsTrustPilotScore","tradedMarketTypes","tradingPlatforms","id","propfirmId"],"additionalProperties":false}},"count":{"type":"number"}},"required":["firms","count"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/propfirms/challenges/query":{"get":{"summary":"Public: search challenges across visible firms. Filter by challenge rules and parent firm; pass propfirmId to list one firm's challenges. Use include=offers to attach live offers that apply to each challenge.","tags":["propfirms"],"parameters":[{"name":"challengeId","in":"query","required":false,"schema":{"description":"Comma-separated public challenge ids.","type":"string"}},{"name":"challengeName","in":"query","required":false,"schema":{"description":"Case-insensitive substring of the challenge name.","type":"string"}},{"name":"accountSizeMin","in":"query","required":false,"schema":{"description":"Minimum account size (inclusive).","type":"string"}},{"name":"accountSizeMax","in":"query","required":false,"schema":{"description":"Maximum account size (inclusive).","type":"string"}},{"name":"steps","in":"query","required":false,"schema":{"description":"Exact evaluation step count (1 = instant / funded, 2 = two-step, …).","type":"string"}},{"name":"stepsMin","in":"query","required":false,"schema":{"description":"Minimum evaluation step count (ignored when steps is set).","type":"string"}},{"name":"stepsMax","in":"query","required":false,"schema":{"description":"Maximum evaluation step count (ignored when steps is set).","type":"string"}},{"name":"priceMin","in":"query","required":false,"schema":{"description":"Minimum challenge fee (inclusive).","type":"string"}},{"name":"priceMax","in":"query","required":false,"schema":{"description":"Maximum challenge fee (inclusive).","type":"string"}},{"name":"profitSplitMin","in":"query","required":false,"schema":{"description":"Minimum trader profit-split percent.","type":"string"}},{"name":"maxLeverageMin","in":"query","required":false,"schema":{"description":"Minimum max leverage.","type":"string"}},{"name":"minTradingDaysMax","in":"query","required":false,"schema":{"description":"Maximum required minimum trading days (less-strict challenges).","type":"string"}},{"name":"dailyLossMax","in":"query","required":false,"schema":{"description":"Maximum daily-loss limit magnitude (smaller number = stricter; this is an upper bound).","type":"string"}},{"name":"maxLossMax","in":"query","required":false,"schema":{"description":"Maximum overall-loss limit magnitude.","type":"string"}},{"name":"maxLossMode","in":"query","required":false,"schema":{"description":"Comma-separated drawdown modes: static-initial, trailing-realized-eod, trailing-intraday-unrealized. Challenges without a captured mode never match.","type":"string"}},{"name":"newsTrading","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"copyTrading","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"autoTrading","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"weekendHolding","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"overnightHolding","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"stoplossRequired","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"isFeeRefundable","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"interval","in":"query","required":false,"schema":{"description":"Comma-separated challenge fee intervals (e.g. one-time, monthly).","type":"string"}},{"name":"pageIndex","in":"query","required":false,"schema":{"description":"0-based page index. Defaults to 0.","type":"string"}},{"name":"pageQuantity","in":"query","required":false,"schema":{"description":"Page size. Defaults to 50, capped at 100.","type":"string"}},{"name":"direction","in":"query","required":false,"schema":{"description":"Sort direction. Defaults per sort key.","type":"string","enum":["asc","desc"]}},{"name":"text","in":"query","required":false,"schema":{"description":"Case-insensitive search over challenge name and firm name/slug.","type":"string"}},{"name":"firmId","in":"query","required":false,"schema":{"description":"Comma-separated internal firm ids.","type":"string"}},{"name":"propfirmId","in":"query","required":false,"schema":{"description":"Comma-separated public firm slugs.","type":"string"}},{"name":"productTypes","in":"query","required":false,"schema":{"description":"Comma-separated product types the parent firm must offer.","type":"string"}},{"name":"tradedMarketTypes","in":"query","required":false,"schema":{"description":"Comma-separated markets the parent firm must offer.","type":"string"}},{"name":"tradingPlatforms","in":"query","required":false,"schema":{"description":"Comma-separated platforms the parent firm must offer.","type":"string"}},{"name":"isPreferredPartner","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}},{"name":"availableIn","in":"query","required":false,"schema":{"description":"Comma-separated country names the parent firm must not restrict.","type":"string"}},{"name":"include","in":"query","required":false,"schema":{"description":"Comma-separated extra payloads: offers.","type":"string"}},{"name":"sort","in":"query","required":false,"schema":{"description":"Defaults to accountSize descending.","type":"string","enum":["challengeName","accountSize","price","steps","profitSplitPercent"]}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"challenges":{"type":"array","items":{"type":"object","properties":{"challengeId":{"type":"string"},"challengeName":{"type":"string"},"accountSize":{"type":"number"},"steps":{"type":"number"},"profitTarget":{"type":"array","items":{"type":"number"}},"profitTargetIsPercent":{"type":"boolean"},"minTradingDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"dailyLoss":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxLoss":{"anyOf":[{"type":"number"},{"type":"null"}]},"dailyLossType":{"anyOf":[{"type":"string"},{"type":"null"}]},"maxLossType":{"anyOf":[{"type":"string"},{"type":"null"}]},"lossIsPercent":{"type":"boolean"},"maxLeverage":{"anyOf":[{"type":"number"},{"type":"null"}]},"newsTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"copyTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"autoTrading":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"weekendHolding":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"overnightHolding":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"stoplossRequired":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"activationFee":{"anyOf":[{"type":"number"},{"type":"null"}]},"resetFee":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxContractSize":{"anyOf":[{"type":"object","properties":{"minis":{"anyOf":[{"type":"number"},{"type":"null"}]},"micros":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["minis","micros"],"additionalProperties":false},{"type":"null"}]},"profitSplitPercent":{"anyOf":[{"type":"number"},{"type":"null"}]},"profitSplitDetails":{"anyOf":[{"type":"string"},{"type":"null"}]},"payoutFrequency":{"anyOf":[{"type":"string"},{"type":"null"}]},"isFeeRefundable":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"price":{"anyOf":[{"type":"number"},{"type":"null"}]},"interval":{"anyOf":[{"type":"string"},{"type":"null"}]},"maxLossMode":{"anyOf":[{"type":"string","enum":["static-initial","trailing-realized-eod","trailing-intraday-unrealized"]},{"type":"null"}]},"maxLossLocksAtInitial":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"maxLossLockOffset":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxLossIsPercent":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"dailyLossBasis":{"anyOf":[{"type":"string","enum":["prior-day-balance","prior-day-equity"]},{"type":"null"}]},"dailyLossLimitBasis":{"anyOf":[{"type":"string","enum":["initial-balance","anchor"]},{"type":"null"}]},"dailyLossIncludesOpenPnl":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"dailyLossEvaluation":{"anyOf":[{"type":"string","enum":["intraday","end-of-day"]},{"type":"null"}]},"dailyLossIsPercent":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"consistencyMaxBestDayPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutIntervalDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMinWinningDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutWinningDayMinProfit":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMaxPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutMaxAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"payoutBufferAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"fundedConsistencyPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"firstPayoutMinDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"feeCurrency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]},"sourceUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastVerifiedAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"firmId":{"type":"string"},"propfirmId":{"type":"string"},"propfirmName":{"type":"string"},"offers":{"type":"array","items":{"type":"object","properties":{"offerId":{"type":"string"},"firmId":{"type":"string"},"propfirmId":{"type":"string"},"propfirmName":{"type":"string"},"promoCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"affiliateLink":{"anyOf":[{"type":"string"},{"type":"null"}]},"discountIsPercent":{"type":"boolean"},"discountValue":{"anyOf":[{"type":"number"},{"type":"null"}]},"shortDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"fullDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"isActive":{"type":"boolean"},"isFeatured":{"type":"boolean"},"hasEndDate":{"type":"boolean"},"endsAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"scope":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"all_challenges"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"specific_challenges"},"challengeIds":{"type":"array","items":{"type":"string"}}},"required":["type","challengeIds"],"additionalProperties":false}]}},"required":["offerId","firmId","propfirmId","propfirmName","promoCode","affiliateLink","discountIsPercent","discountValue","shortDescription","fullDescription","isActive","isFeatured","hasEndDate","endsAt","scope"],"additionalProperties":false}}},"required":["challengeId","challengeName","accountSize","steps","profitTarget","profitTargetIsPercent","minTradingDays","dailyLoss","maxLoss","dailyLossType","maxLossType","lossIsPercent","maxLeverage","newsTrading","copyTrading","autoTrading","weekendHolding","overnightHolding","stoplossRequired","activationFee","resetFee","maxContractSize","profitSplitPercent","profitSplitDetails","payoutFrequency","isFeeRefundable","price","interval","firmId","propfirmId","propfirmName"],"additionalProperties":false}},"count":{"type":"number"}},"required":["challenges","count"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/propfirms/offers/query":{"get":{"summary":"Public: search promotional offers across visible firms. Defaults to live (active, unexpired) offers. Pass propfirmId for one firm's offers, or challengeId for offers that apply to a challenge (firm-wide offers included).","tags":["propfirms"],"parameters":[{"name":"offerId","in":"query","required":false,"schema":{"description":"Comma-separated public offer ids.","type":"string"}},{"name":"promoCode","in":"query","required":false,"schema":{"description":"Case-insensitive substring of the promo code.","type":"string"}},{"name":"offerText","in":"query","required":false,"schema":{"description":"Case-insensitive search over promo code and offer descriptions.","type":"string"}},{"name":"isActive","in":"query","required":false,"schema":{"description":"Defaults to live offers only. Pass false to look at inactive offers.","type":"string","enum":["true","false"]}},{"name":"isFeatured","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"discountIsPercent","in":"query","required":false,"schema":{"description":"Boolean filter as \"true\" or \"false\".","type":"string","enum":["true","false"]}},{"name":"discountMin","in":"query","required":false,"schema":{"description":"Minimum discount value (percent or absolute, matching discountIsPercent).","type":"string"}},{"name":"discountMax","in":"query","required":false,"schema":{"description":"Maximum discount value.","type":"string"}},{"name":"includeInactive","in":"query","required":false,"schema":{"description":"When true, inactive offers are not hidden. Defaults to false.","type":"string","enum":["true","false"]}},{"name":"includeExpired","in":"query","required":false,"schema":{"description":"When true, ended offers are not hidden. Defaults to false.","type":"string","enum":["true","false"]}},{"name":"pageIndex","in":"query","required":false,"schema":{"description":"0-based page index. Defaults to 0.","type":"string"}},{"name":"pageQuantity","in":"query","required":false,"schema":{"description":"Page size. Defaults to 50, capped at 100.","type":"string"}},{"name":"direction","in":"query","required":false,"schema":{"description":"Sort direction. Defaults per sort key.","type":"string","enum":["asc","desc"]}},{"name":"text","in":"query","required":false,"schema":{"description":"Case-insensitive search over promo code, descriptions, and firm name/slug.","type":"string"}},{"name":"firmId","in":"query","required":false,"schema":{"description":"Comma-separated internal firm ids.","type":"string"}},{"name":"propfirmId","in":"query","required":false,"schema":{"description":"Comma-separated public firm slugs.","type":"string"}},{"name":"challengeId","in":"query","required":false,"schema":{"description":"Comma-separated challenge ids. An offer matches when it applies to at least one (all-challenges offers match that firm's challenges).","type":"string"}},{"name":"sort","in":"query","required":false,"schema":{"description":"Defaults to featured first, then discount.","type":"string","enum":["discountValue","endsAt","promoCode"]}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"offers":{"type":"array","items":{"type":"object","properties":{"offerId":{"type":"string"},"firmId":{"type":"string"},"propfirmId":{"type":"string"},"propfirmName":{"type":"string"},"promoCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"affiliateLink":{"anyOf":[{"type":"string"},{"type":"null"}]},"discountIsPercent":{"type":"boolean"},"discountValue":{"anyOf":[{"type":"number"},{"type":"null"}]},"shortDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"fullDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"isActive":{"type":"boolean"},"isFeatured":{"type":"boolean"},"hasEndDate":{"type":"boolean"},"endsAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"scope":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"all_challenges"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"specific_challenges"},"challengeIds":{"type":"array","items":{"type":"string"}}},"required":["type","challengeIds"],"additionalProperties":false}]}},"required":["offerId","firmId","propfirmId","propfirmName","promoCode","affiliateLink","discountIsPercent","discountValue","shortDescription","fullDescription","isActive","isFeatured","hasEndDate","endsAt","scope"],"additionalProperties":false}},"count":{"type":"number"}},"required":["offers","count"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/propfirms/suggested-strategies":{"get":{"summary":"Public: suggested backtesting strategies per propfirm, optionally filtered by product type","tags":["propfirms"],"parameters":[{"name":"productType","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"strategies":{"type":"array","items":{"type":"object","properties":{"propfirmId":{"type":"string"},"propfirmName":{"type":"string"},"id":{"type":"string"},"startDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"ticker":{"type":"string"},"timeframe":{"anyOf":[{"type":"number"},{"type":"null"}]},"netProfit":{"anyOf":[{"type":"number"},{"type":"null"}]},"closedTrades":{"anyOf":[{"type":"number"},{"type":"null"}]},"winrate":{"anyOf":[{"type":"number"},{"type":"null"}]},"profitFactor":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxDrawdownPct":{"anyOf":[{"type":"number"},{"type":"null"}]},"avgTrade":{"anyOf":[{"type":"number"},{"type":"null"}]},"avgWinningTrade":{"anyOf":[{"type":"number"},{"type":"null"}]},"avgLosingTrade":{"anyOf":[{"type":"number"},{"type":"null"}]},"longConditions":{"type":"array","items":{"type":"string"}},"shortConditions":{"type":"array","items":{"type":"string"}},"currency":{"type":"string"},"historicalNetProfit":{"anyOf":[{"type":"array","items":{"type":"number"}},{"type":"null"}]},"productType":{"type":"string","enum":["Futures","CFD"]}},"required":["propfirmId","propfirmName","id","startDate","ticker","timeframe","netProfit","closedTrades","winrate","profitFactor","maxDrawdownPct","avgTrade","avgWinningTrade","avgLosingTrade","longConditions","shortConditions","currency","historicalNetProfit","productType"],"additionalProperties":false}}},"required":["strategies"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/library/indicators/query":{"get":{"summary":"Public: filtered/paginated published library indicators with LuxAlgo pinning","tags":["library"],"parameters":[{"name":"text","in":"query","required":false,"schema":{"type":"string"}},{"name":"creator","in":"query","required":false,"schema":{"type":"string"}},{"name":"tier","in":"query","required":false,"schema":{"type":"string"}},{"name":"platform","in":"query","required":false,"schema":{"type":"string"}},{"name":"authorName","in":"query","required":false,"schema":{"type":"string"}},{"name":"family","in":"query","required":false,"schema":{"type":"string","enum":["trend","momentum","volatility","volume-orderflow","market-structure","smc-ict","wyckoff","elliott-harmonics","patterns","levels","statistics","machine-learning","time-seasonality","sentiment-breadth","risk-exits","meta-composition","validation"]}},{"name":"concept","in":"query","required":false,"schema":{"type":"string"}},{"name":"slugs","in":"query","required":false,"schema":{"type":"string"}},{"name":"fields","in":"query","required":false,"schema":{"type":"string","enum":["full","card"]}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["name","creationDateDisplayed","family"]}},{"name":"direction","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}},{"name":"pageIndex","in":"query","required":false,"schema":{"type":"string"}},{"name":"pageQuantity","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"indicators":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"slug":{"type":"string"},"imageUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"body":{"anyOf":[{"type":"string"},{"type":"null"}]},"authorName":{"anyOf":[{"type":"string"},{"type":"null"}]},"creationDateDisplayed":{"type":"string"},"isPublished":{"type":"boolean"},"pineScriptCodeId":{"anyOf":[{"type":"string"},{"type":"null"}]},"family":{"anyOf":[{"type":"string","enum":["trend","momentum","volatility","volume-orderflow","market-structure","smc-ict","wyckoff","elliott-harmonics","patterns","levels","statistics","machine-learning","time-seasonality","sentiment-breadth","risk-exits","meta-composition","validation"]},{"type":"null"}]},"creator":{"type":"object","properties":{"slug":{"type":"string"}},"required":["slug"],"additionalProperties":false},"plans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false}}},"required":["id","name","slug","imageUrl","description","body","authorName","creationDateDisplayed","isPublished","pineScriptCodeId","family","creator","plans"],"additionalProperties":false}},"count":{"type":"number"}},"required":["indicators","count"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/library/indicators/slugs":{"get":{"summary":"Public: list published library indicator slugs (for checkout's getStaticPaths prefetch)","tags":["library"],"parameters":[],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"slugs":{"type":"array","items":{"type":"string"}}},"required":["slugs"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/library/indicators/by-slug/{slug}":{"get":{"summary":"Public: get a published library indicator by slug (with legacy-slug fallback)","tags":["library"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"indicator":{"type":"object","properties":{"id":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"slug":{"type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"body":{"anyOf":[{"type":"string"},{"type":"null"}]},"metaDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"imageUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"authorName":{"anyOf":[{"type":"string"},{"type":"null"}]},"creationDateDisplayed":{"type":"string"},"isPublished":{"type":"boolean"},"pineScriptCodeId":{"anyOf":[{"type":"string"},{"type":"null"}]},"family":{"anyOf":[{"type":"string","enum":["trend","momentum","volatility","volume-orderflow","market-structure","smc-ict","wyckoff","elliott-harmonics","patterns","levels","statistics","machine-learning","time-seasonality","sentiment-breadth","risk-exits","meta-composition","validation"]},{"type":"null"}]},"tradingviewUuid":{"anyOf":[{"type":"string"},{"type":"null"}]},"tradingviewSharedChartId":{"anyOf":[{"type":"string"},{"type":"null"}]},"tradingPlatforms":{"type":"array","items":{"type":"string"}},"chartPreviewData":{"anyOf":[{},{"type":"null"}]},"plans":{"type":"array","items":{"type":"object","properties":{"isPublic":{"type":"boolean"},"tier":{"type":"string"}},"required":["isPublic","tier"],"additionalProperties":false}},"concepts":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"primary":{"type":"boolean"}},"required":["slug","name","primary"],"additionalProperties":false}}},"required":["id","name","slug","description","body","metaDescription","imageUrl","authorName","creationDateDisplayed","isPublished","pineScriptCodeId","family","tradingviewUuid","tradingviewSharedChartId","tradingPlatforms","chartPreviewData","plans","concepts"],"additionalProperties":false},"pineScriptCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"sourcePreview":{"anyOf":[{"type":"object","properties":{"shownLines":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalLines":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["shownLines","totalLines"],"additionalProperties":false},{"type":"null"}]}},"required":["indicator","pineScriptCode","sourcePreview"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/marketing/sales/applicable":{"get":{"summary":"Public: get the currently applicable sale for an audience","tags":["marketing"],"parameters":[{"name":"audience","in":"query","required":false,"schema":{"type":"string"}},{"name":"country","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Z]{2}$"}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sale":{"anyOf":[{"type":"object","properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"intervalTagline":{"anyOf":[{"type":"string"},{"type":"null"}]},"stripeCouponIds":{"type":"array","items":{"type":"string"}},"colorScheme":{"anyOf":[{"type":"string"},{"type":"null"}]},"beginDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"endDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"audiences":{"type":"array","items":{"type":"string"}},"hasCountdown":{"type":"boolean"},"isPublic":{"type":"boolean"},"countries":{"type":"array","items":{"type":"string"}},"id":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"heroTheme":{"anyOf":[{"type":"string"},{"type":"null"}]},"heroMode":{"anyOf":[{"type":"string"},{"type":"null"}]},"heroConfig":{"anyOf":[{"type":"object","properties":{"home":{"type":"object","properties":{"badge":{"type":"string"},"h1":{"type":"string"},"sub":{"anyOf":[{"type":"string"},{"type":"null"}]},"primaryCta":{"type":"object","properties":{"label":{"type":"string","minLength":1},"href":{"type":"string","minLength":1}},"required":["label","href"],"additionalProperties":false},"secondaryCta":{"anyOf":[{"type":"object","properties":{"label":{"type":"string","minLength":1},"href":{"type":"string","minLength":1}},"required":["label","href"],"additionalProperties":false},{"type":"null"}]}},"additionalProperties":false},"pricing":{"type":"object","properties":{"h1":{"type":"string"},"sub":{"anyOf":[{"type":"string"},{"type":"null"}]},"bonusTagline":{"type":"string"},"annualOnly":{"type":"boolean"},"ctaLabel":{"type":"string"},"discountFirst":{"type":"boolean"}},"additionalProperties":false},"homePricing":{"type":"object","properties":{"h1":{"type":"string"},"sub":{"anyOf":[{"type":"string"},{"type":"null"}]}},"additionalProperties":false},"seasonal":{"type":"object","properties":{"season":{"type":"string","enum":["winter","spring","summer","fall"]},"accent":{"type":"string"},"emoji":{"type":"string"}},"additionalProperties":false},"prelaunch":{"type":"object","properties":{"enabled":{"type":"boolean"},"beginDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"h1":{"type":"string"},"sub":{"anyOf":[{"type":"string"},{"type":"null"}]},"notifyTag":{"type":"string"}},"required":["enabled"],"additionalProperties":false}},"additionalProperties":false},{"type":"null"}]},"perks":{"anyOf":[{"type":"object","propertyNames":{"type":"string","minLength":1},"additionalProperties":{"type":"object","properties":{"purchase":{"type":"object","properties":{"freeMonths":{"type":"integer","minimum":0,"maximum":24},"aiCredits":{"description":"Bonus AI, stored in credits: $1 of extra usage = 2,500 credits (so $40 of extra usage = 100,000). Members on credits receive these credits; members on plan usage receive the same Quant as extra usage.","type":"integer","minimum":0,"maximum":100000000}},"additionalProperties":false},"stacking":{"type":"array","items":{"type":"object","properties":{"freeMonths":{"type":"integer","minimum":0,"maximum":24},"aiCredits":{"description":"Bonus AI, stored in credits: $1 of extra usage = 2,500 credits (so $40 of extra usage = 100,000). Members on credits receive these credits; members on plan usage receive the same Quant as extra usage.","type":"integer","minimum":0,"maximum":100000000},"years":{"type":"integer","minimum":2,"maximum":10}},"required":["years"],"additionalProperties":false}},"maxButton":{"type":"object","properties":{"enabled":{"type":"boolean"},"bonus":{"type":"object","properties":{"freeMonths":{"type":"integer","minimum":0,"maximum":24},"aiCredits":{"description":"Bonus AI, stored in credits: $1 of extra usage = 2,500 credits (so $40 of extra usage = 100,000). Members on credits receive these credits; members on plan usage receive the same Quant as extra usage.","type":"integer","minimum":0,"maximum":100000000}},"additionalProperties":false}},"required":["enabled"],"additionalProperties":false}},"additionalProperties":false}},{"type":"null"}]},"phases":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"displayPercent":{"type":"number"},"stripeCouponIds":{"type":"array","items":{"type":"string"}},"beginDate":{"type":"string"},"id":{"type":"string"},"sortOrder":{"type":"number"}},"required":["label","displayPercent","stripeCouponIds","beginDate","id","sortOrder"],"additionalProperties":false}},"banner":{"anyOf":[{"type":"object","properties":{"content":{"type":"string"},"linkUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"colorScheme":{"anyOf":[{"type":"string"},{"type":"null"}]},"beginDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"endDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"audiences":{"type":"array","items":{"type":"string"}},"isPublic":{"type":"boolean"},"countries":{"type":"array","items":{"type":"string"}},"surface":{"type":"string","enum":["bar","hero_pill","app_bar"]},"targetPathnames":{"type":"array","items":{"type":"string"}},"id":{"type":"string"},"saleId":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["content","linkUrl","colorScheme","beginDate","endDate","audiences","isPublic","countries","surface","targetPathnames","id","saleId","createdAt","updatedAt"],"additionalProperties":false},{"type":"null"}]}},"required":["name","intervalTagline","stripeCouponIds","colorScheme","beginDate","endDate","audiences","hasCountdown","isPublic","countries","id","createdAt","updatedAt","heroTheme","heroMode","heroConfig","perks","phases","banner"],"additionalProperties":false},{"type":"null"}]},"activePhase":{"anyOf":[{"type":"object","properties":{"label":{"type":"string"},"displayPercent":{"type":"number"},"stripeCouponIds":{"type":"array","items":{"type":"string"}},"beginDate":{"type":"string"},"id":{"type":"string"},"sortOrder":{"type":"number"}},"required":["label","displayPercent","stripeCouponIds","beginDate","id","sortOrder"],"additionalProperties":false},{"type":"null"}]},"effectiveStripeCouponIds":{"type":"array","items":{"type":"string"}}},"required":["sale","activePhase","effectiveStripeCouponIds"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/marketing/sales/upcoming":{"get":{"summary":"Public: get the sale whose pre-launch window is open for an audience","tags":["marketing"],"parameters":[{"name":"audience","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sale":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"heroTheme":{"anyOf":[{"type":"string"},{"type":"null"}]},"heroMode":{"anyOf":[{"type":"string"},{"type":"null"}]},"colorScheme":{"anyOf":[{"type":"string"},{"type":"null"}]},"beginDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"endDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"hasCountdown":{"type":"boolean"},"prelaunch":{"type":"object","properties":{"beginDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"h1":{"anyOf":[{"type":"string"},{"type":"null"}]},"sub":{"anyOf":[{"type":"string"},{"type":"null"}]},"canNotify":{"type":"boolean"}},"required":["beginDate","h1","sub","canNotify"],"additionalProperties":false},"phases":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"displayPercent":{"type":"number"},"beginDate":{"type":"string"}},"required":["label","displayPercent","beginDate"],"additionalProperties":false}},"perks":{"anyOf":[{"type":"object","propertyNames":{"type":"string","minLength":1},"additionalProperties":{"type":"object","properties":{"purchase":{"type":"object","properties":{"freeMonths":{"type":"integer","minimum":0,"maximum":24},"aiCredits":{"description":"Bonus AI, stored in credits: $1 of extra usage = 2,500 credits (so $40 of extra usage = 100,000). Members on credits receive these credits; members on plan usage receive the same Quant as extra usage.","type":"integer","minimum":0,"maximum":100000000}},"additionalProperties":false},"stacking":{"type":"array","items":{"type":"object","properties":{"freeMonths":{"type":"integer","minimum":0,"maximum":24},"aiCredits":{"description":"Bonus AI, stored in credits: $1 of extra usage = 2,500 credits (so $40 of extra usage = 100,000). Members on credits receive these credits; members on plan usage receive the same Quant as extra usage.","type":"integer","minimum":0,"maximum":100000000},"years":{"type":"integer","minimum":2,"maximum":10}},"required":["years"],"additionalProperties":false}},"maxButton":{"type":"object","properties":{"enabled":{"type":"boolean"},"bonus":{"type":"object","properties":{"freeMonths":{"type":"integer","minimum":0,"maximum":24},"aiCredits":{"description":"Bonus AI, stored in credits: $1 of extra usage = 2,500 credits (so $40 of extra usage = 100,000). Members on credits receive these credits; members on plan usage receive the same Quant as extra usage.","type":"integer","minimum":0,"maximum":100000000}},"additionalProperties":false}},"required":["enabled"],"additionalProperties":false}},"additionalProperties":false}},{"type":"null"}]}},"required":["id","name","heroTheme","heroMode","colorScheme","beginDate","endDate","hasCountdown","prelaunch","phases","perks"],"additionalProperties":false},{"type":"null"}]}},"required":["sale"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/marketing/sales/coupon":{"get":{"summary":"Public: get the applicable sale coupon for a product","tags":["marketing"],"parameters":[{"name":"productId","in":"query","required":true,"schema":{"type":"string"}},{"name":"audience","in":"query","required":false,"schema":{"type":"string"}},{"name":"country","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Z]{2}$"}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"coupon":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"percentOff":{"type":"number"},"name":{"type":"string"}},"required":["id","percentOff","name"],"additionalProperties":false},{"type":"null"}]}},"required":["coupon"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/marketing/banners/applicable":{"get":{"summary":"Public: get the currently applicable banners for an audience","tags":["marketing"],"parameters":[{"name":"audience","in":"query","required":false,"schema":{"type":"string"}},{"name":"country","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Z]{2}$"}},{"name":"surface","in":"query","required":false,"schema":{"type":"string","enum":["bar","hero_pill","app_bar"]}}],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"banners":{"type":"array","items":{"type":"object","properties":{"content":{"type":"string"},"linkUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"colorScheme":{"anyOf":[{"type":"string"},{"type":"null"}]},"beginDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"endDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"audiences":{"type":"array","items":{"type":"string"}},"isPublic":{"type":"boolean"},"countries":{"type":"array","items":{"type":"string"}},"surface":{"type":"string","enum":["bar","hero_pill","app_bar"]},"targetPathnames":{"type":"array","items":{"type":"string"}},"id":{"type":"string"},"saleId":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["content","linkUrl","colorScheme","beginDate","endDate","audiences","isPublic","countries","surface","targetPathnames","id","saleId","createdAt","updatedAt"],"additionalProperties":false}}},"required":["banners"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/marketing/popups/applicable":{"get":{"summary":"Public: get currently enabled in-app popups","tags":["marketing"],"parameters":[],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"popups":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"content":{"type":"string"},"imageUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"ctaLabel":{"type":"string"},"ctaUrl":{"type":"string"},"ctaStyle":{"oneOf":[{"type":"object","properties":{"useDefaults":{"type":"boolean","const":true}},"required":["useDefaults"],"additionalProperties":false},{"type":"object","properties":{"useDefaults":{"type":"boolean","const":false},"backgroundColor":{"type":"string","pattern":"^(transparent|#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|oklch\\([^)]+\\))$"},"borderColor":{"type":"string","pattern":"^(transparent|#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|oklch\\([^)]+\\))$"},"textColor":{"type":"string","pattern":"^(transparent|#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|oklch\\([^)]+\\))$"}},"required":["useDefaults","backgroundColor","borderColor","textColor"],"additionalProperties":false}]},"pathnames":{"type":"array","items":{"type":"string"}},"isPublic":{"type":"boolean"},"beginDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"endDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"id":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["title","content","imageUrl","ctaLabel","ctaUrl","ctaStyle","pathnames","isPublic","beginDate","endDate","id","createdAt","updatedAt"],"additionalProperties":false}}},"required":["popups"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/marketing/notify":{"post":{"summary":"Public: campaign email opt-in → Mailchimp list + per-campaign tag (Turnstile-protected)","tags":["marketing"],"parameters":[],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"subscribed":{"type":"boolean"}},"required":["subscribed"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"saleId":{"type":"string"},"turnstileToken":{"type":"string"}},"required":["email","saleId"],"additionalProperties":false}}}}}},"/api/vela/desktop-release":{"get":{"summary":"Public: every Vela for desktop installer published for download, by system (macOS, Windows, Linux)","tags":["vela"],"parameters":[],"responses":{"200":{"description":"Success. The payload is wrapped in the standard { data, errors } envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"feed":{"type":"string","enum":["ok","failed","unset"],"description":"`ok`: `platforms` is exactly what is published, possibly nothing. `failed`: the feed could not be read just now for the systems in `unavailable` (not the same as nothing published). `unset`: no feed is configured here."},"platforms":{"type":"array","items":{"type":"object","properties":{"os":{"type":"string","enum":["macos","windows","linux"]},"version":{"type":"string"},"releasedAt":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO 8601; null when the feed does not say."},"downloads":{"type":"array","items":{"type":"object","properties":{"os":{"type":"string","enum":["macos","windows","linux"]},"arch":{"type":"string","enum":["arm64","x64","universal"],"description":"`universal` is one installer for both processors."},"package":{"type":"string","enum":["dmg","zip","exe","AppImage","deb","rpm"]},"url":{"type":"string","description":"Absolute https URL of the installer, on the feed's own host."},"fileName":{"type":"string"},"version":{"type":"string"},"size":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In bytes; null when the feed does not say."}},"required":["os","arch","package","url","fileName","version","size"],"additionalProperties":false},"description":"Best installer first."}},"required":["os","version","releasedAt","downloads"],"additionalProperties":false},"description":"Every system with something published, in macOS, Windows, Linux order."},"unavailable":{"type":"array","items":{"type":"string","enum":["macos","windows","linux"]},"description":"Systems whose builds are unknown right now because the feed failed."}},"required":["feed","platforms","unavailable"],"additionalProperties":false},"errors":{"type":"null"}},"required":["data"]}}}},"400":{"description":"Validation error — errors[].details carries the zod issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}},"components":{"schemas":{"ErrorEnvelope":{"type":"object","properties":{"data":{"type":"null"},"errors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"details":{}},"required":["message"]}}},"required":["errors"]}}}}