[{"data":1,"prerenderedAt":2630},["ShallowReactive",2],{"page-\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fbuilding-api-marketplaces\u002Flisting-your-api-on-rapidapi\u002F":3,"faq-schema-\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fbuilding-api-marketplaces\u002Flisting-your-api-on-rapidapi\u002F":2609},{"id":4,"title":5,"body":6,"description":2599,"extension":2600,"meta":2601,"navigation":195,"path":2605,"seo":2606,"stem":2607,"__hash__":2608},"content\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fbuilding-api-marketplaces\u002Flisting-your-api-on-rapidapi\u002Findex.md","Listing Your API on RapidAPI: Revenue Share, Proxy Auth and Quota Mapping",{"type":7,"value":8,"toc":2589},"minimark",[9,13,28,33,36,39,140,143,669,672,676,683,699,825,832,1333,1352,1356,1364,1372,1480,1560,1563,2001,2018,2021,2337,2341,2435,2443,2446,2450,2453,2486,2489,2493,2501,2505,2512,2518,2528,2538,2548,2552,2585],[10,11,5],"h1",{"id":12},"listing-your-api-on-rapidapi-revenue-share-proxy-auth-and-quota-mapping",[14,15,16,17,22,23,27],"p",{},"A marketplace listing is a distribution channel, not a business model. That distinction decides everything else on this page. Part of the ",[18,19,21],"a",{"href":20},"\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fbuilding-api-marketplaces\u002F","Building API Marketplaces"," guide, this article resolves one specific question: should you put your commercial Python API on RapidAPI, and if you do, how do you wire the gateway into your own auth and quota system without handing over the customer relationship? The short version of the verdict — argued properly further down — is list it as a secondary channel, keep ",[18,24,26],{"href":25},"\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fintegrating-stripe-with-python-apis\u002F","direct Stripe billing"," as the primary one, and never let the marketplace become the only place a customer can buy.",[29,30,32],"h2",{"id":31},"the-revenue-share-maths","The revenue share maths",[14,34,35],{},"Marketplaces charge a percentage of collected revenue. RapidAPI's published commission has sat at 20% of what your subscribers pay, and the platform handles card processing, invoicing, tax handling and dunning out of that cut. Compare that against selling directly: card processing costs roughly 2.9% plus 30 cents per charge, so a $29 monthly plan clears about $27.86 into your account. The same plan sold through the marketplace clears $23.20. The gap is $4.66 per subscriber per month, or 16.7% of gross.",[14,37,38],{},"That number is small in isolation and enormous in aggregate. At 100 paying subscribers on a $29 plan you are handing over $466 a month — roughly the cost of a decent managed Postgres instance plus your entire compute bill. At 500 subscribers it is $2,330 a month, which is real salary money for a side hustle. The honest framing is this: the commission is a customer acquisition cost, and you should evaluate it exactly like paid ads. If the marketplace brings you subscribers you would never have found, 20% is cheap. If it merely intercepts people who would have signed up on your own site anyway, 20% is a tax on traffic you already owned.",[40,41,49,50,49,54,49,58,49,65,49,73,49,81,49,87,49,93,49,99,49,103,49,108,49,113,49,117,49,122,49,127,49,130,49,135],"svg",{"viewBox":42,"role":43,"ariaLabelledBy":44,"xmlns":47,"style":48},"0 0 720 250","img",[45,46],"rapidapi-rev-t","rapidapi-rev-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;margin:1.5rem 0;font-family:var(--font-sans);","\n  ",[51,52,53],"title",{"id":45},"Monthly net revenue by sales channel at 100 subscribers",[55,56,57],"desc",{"id":46},"Bar chart comparing net monthly revenue from one hundred subscribers on a twenty-nine dollar plan: direct billing clears 2,786 dollars, a seventy-thirty blend clears 2,646 dollars, and marketplace-only clears 2,320 dollars.",[59,60],"rect",{"x":61,"y":61,"width":62,"height":63,"fill":64},"0","720","250","var(--c-surface)",[66,67,72],"text",{"x":68,"y":69,"fill":70,"style":71},"20","30","var(--c-text)","font-size:14;font-family:var(--font-sans);","Net monthly revenue, 100 subscribers on a $29 plan",[74,75],"line",{"x1":76,"y1":77,"x2":76,"y2":78,"stroke":79,"style":80},"200","52","212","var(--c-border)","stroke-width:2;",[66,82,86],{"x":83,"y":84,"fill":70,"style":85},"190","83","text-anchor:end;font-size:12;font-family:var(--font-sans);","Direct only",[59,88],{"x":76,"y":89,"width":90,"height":69,"rx":91,"fill":92},"66","380","4","var(--c-teal)",[66,94,98],{"x":95,"y":96,"fill":70,"style":97},"592","86","font-size:12;font-family:var(--font-sans);","$2,786",[66,100,102],{"x":83,"y":101,"fill":70,"style":85},"133","70\u002F30 blend",[59,104],{"x":76,"y":105,"width":106,"height":69,"rx":91,"fill":107},"116","361","var(--c-blue)",[66,109,112],{"x":110,"y":111,"fill":70,"style":97},"573","136","$2,646",[66,114,116],{"x":83,"y":115,"fill":70,"style":85},"183","Marketplace only",[59,118],{"x":76,"y":119,"width":120,"height":69,"rx":91,"fill":121},"166","316","var(--c-coral)",[66,123,126],{"x":124,"y":125,"fill":70,"style":97},"528","186","$2,320",[74,128],{"x1":76,"y1":78,"x2":129,"y2":78,"stroke":79,"style":80},"690",[66,131,134],{"x":76,"y":132,"fill":133,"style":97},"232","var(--c-text-muted)","$0",[66,136,139],{"x":137,"y":132,"fill":133,"style":138},"580","text-anchor:middle;font-size:12;font-family:var(--font-sans);","gap = marketplace commission",[14,141,142],{},"Run the arithmetic on your own numbers before you commit. Keep the rates in environment variables so you can re-run the model when a platform changes its terms.",[144,145,150],"pre",{"className":146,"code":147,"language":148,"meta":149,"style":149},"language-python shiki shiki-themes github-light github-dark","\"\"\"Channel margin model. Usage: python channel_margin.py\"\"\"\nimport os\nfrom decimal import Decimal, ROUND_HALF_UP\n\n\ndef money(value: Decimal) -> Decimal:\n    return value.quantize(Decimal(\"0.01\"), rounding=ROUND_HALF_UP)\n\n\ndef net_direct(gross: Decimal) -> Decimal:\n    pct = Decimal(os.getenv(\"CARD_FEE_PCT\", \"0.029\"))\n    fixed = Decimal(os.getenv(\"CARD_FEE_FIXED\", \"0.30\"))\n    return money(gross - (gross * pct) - fixed)\n\n\ndef net_marketplace(gross: Decimal) -> Decimal:\n    share = Decimal(os.getenv(\"MARKETPLACE_REV_SHARE\", \"0.20\"))\n    return money(gross * (Decimal(1) - share))\n\n\nif __name__ == \"__main__\":\n    price = Decimal(os.getenv(\"PLAN_PRICE_USD\", \"29.00\"))\n    seats = int(os.getenv(\"SUBSCRIBER_COUNT\", \"100\"))\n    split = Decimal(os.getenv(\"MARKETPLACE_SHARE_OF_SUBS\", \"0.30\"))\n\n    direct_seats = Decimal(seats) * (Decimal(1) - split)\n    market_seats = Decimal(seats) * split\n    blended = money(direct_seats * net_direct(price) + market_seats * net_marketplace(price))\n\n    print(f\"direct per sub      {net_direct(price)}\")\n    print(f\"marketplace per sub {net_marketplace(price)}\")\n    print(f\"blended monthly     {blended}\")\n    print(f\"commission drag     {money(Decimal(seats) * net_direct(price) - blended)}\")\n","python","",[151,152,153,161,172,190,197,202,215,243,248,253,264,287,307,332,337,342,352,372,395,400,405,423,443,467,486,491,515,530,557,562,591,614,637],"code",{"__ignoreMap":149},[154,155,157],"span",{"class":74,"line":156},1,[154,158,160],{"class":159},"sZZnC","\"\"\"Channel margin model. Usage: python channel_margin.py\"\"\"\n",[154,162,164,168],{"class":74,"line":163},2,[154,165,167],{"class":166},"szBVR","import",[154,169,171],{"class":170},"sVt8B"," os\n",[154,173,175,178,181,183,186],{"class":74,"line":174},3,[154,176,177],{"class":166},"from",[154,179,180],{"class":170}," decimal ",[154,182,167],{"class":166},[154,184,185],{"class":170}," Decimal, ",[154,187,189],{"class":188},"sj4cs","ROUND_HALF_UP\n",[154,191,193],{"class":74,"line":192},4,[154,194,196],{"emptyLinePlaceholder":195},true,"\n",[154,198,200],{"class":74,"line":199},5,[154,201,196],{"emptyLinePlaceholder":195},[154,203,205,208,212],{"class":74,"line":204},6,[154,206,207],{"class":166},"def",[154,209,211],{"class":210},"sScJk"," money",[154,213,214],{"class":170},"(value: Decimal) -> Decimal:\n",[154,216,218,221,224,227,230,234,237,240],{"class":74,"line":217},7,[154,219,220],{"class":166},"    return",[154,222,223],{"class":170}," value.quantize(Decimal(",[154,225,226],{"class":159},"\"0.01\"",[154,228,229],{"class":170},"), ",[154,231,233],{"class":232},"s4XuR","rounding",[154,235,236],{"class":166},"=",[154,238,239],{"class":188},"ROUND_HALF_UP",[154,241,242],{"class":170},")\n",[154,244,246],{"class":74,"line":245},8,[154,247,196],{"emptyLinePlaceholder":195},[154,249,251],{"class":74,"line":250},9,[154,252,196],{"emptyLinePlaceholder":195},[154,254,256,258,261],{"class":74,"line":255},10,[154,257,207],{"class":166},[154,259,260],{"class":210}," net_direct",[154,262,263],{"class":170},"(gross: Decimal) -> Decimal:\n",[154,265,267,270,272,275,278,281,284],{"class":74,"line":266},11,[154,268,269],{"class":170},"    pct ",[154,271,236],{"class":166},[154,273,274],{"class":170}," Decimal(os.getenv(",[154,276,277],{"class":159},"\"CARD_FEE_PCT\"",[154,279,280],{"class":170},", ",[154,282,283],{"class":159},"\"0.029\"",[154,285,286],{"class":170},"))\n",[154,288,290,293,295,297,300,302,305],{"class":74,"line":289},12,[154,291,292],{"class":170},"    fixed ",[154,294,236],{"class":166},[154,296,274],{"class":170},[154,298,299],{"class":159},"\"CARD_FEE_FIXED\"",[154,301,280],{"class":170},[154,303,304],{"class":159},"\"0.30\"",[154,306,286],{"class":170},[154,308,310,312,315,318,321,324,327,329],{"class":74,"line":309},13,[154,311,220],{"class":166},[154,313,314],{"class":170}," money(gross ",[154,316,317],{"class":166},"-",[154,319,320],{"class":170}," (gross ",[154,322,323],{"class":166},"*",[154,325,326],{"class":170}," pct) ",[154,328,317],{"class":166},[154,330,331],{"class":170}," fixed)\n",[154,333,335],{"class":74,"line":334},14,[154,336,196],{"emptyLinePlaceholder":195},[154,338,340],{"class":74,"line":339},15,[154,341,196],{"emptyLinePlaceholder":195},[154,343,345,347,350],{"class":74,"line":344},16,[154,346,207],{"class":166},[154,348,349],{"class":210}," net_marketplace",[154,351,263],{"class":170},[154,353,355,358,360,362,365,367,370],{"class":74,"line":354},17,[154,356,357],{"class":170},"    share ",[154,359,236],{"class":166},[154,361,274],{"class":170},[154,363,364],{"class":159},"\"MARKETPLACE_REV_SHARE\"",[154,366,280],{"class":170},[154,368,369],{"class":159},"\"0.20\"",[154,371,286],{"class":170},[154,373,375,377,379,381,384,387,390,392],{"class":74,"line":374},18,[154,376,220],{"class":166},[154,378,314],{"class":170},[154,380,323],{"class":166},[154,382,383],{"class":170}," (Decimal(",[154,385,386],{"class":188},"1",[154,388,389],{"class":170},") ",[154,391,317],{"class":166},[154,393,394],{"class":170}," share))\n",[154,396,398],{"class":74,"line":397},19,[154,399,196],{"emptyLinePlaceholder":195},[154,401,403],{"class":74,"line":402},20,[154,404,196],{"emptyLinePlaceholder":195},[154,406,408,411,414,417,420],{"class":74,"line":407},21,[154,409,410],{"class":166},"if",[154,412,413],{"class":188}," __name__",[154,415,416],{"class":166}," ==",[154,418,419],{"class":159}," \"__main__\"",[154,421,422],{"class":170},":\n",[154,424,426,429,431,433,436,438,441],{"class":74,"line":425},22,[154,427,428],{"class":170},"    price ",[154,430,236],{"class":166},[154,432,274],{"class":170},[154,434,435],{"class":159},"\"PLAN_PRICE_USD\"",[154,437,280],{"class":170},[154,439,440],{"class":159},"\"29.00\"",[154,442,286],{"class":170},[154,444,446,449,451,454,457,460,462,465],{"class":74,"line":445},23,[154,447,448],{"class":170},"    seats ",[154,450,236],{"class":166},[154,452,453],{"class":188}," int",[154,455,456],{"class":170},"(os.getenv(",[154,458,459],{"class":159},"\"SUBSCRIBER_COUNT\"",[154,461,280],{"class":170},[154,463,464],{"class":159},"\"100\"",[154,466,286],{"class":170},[154,468,470,473,475,477,480,482,484],{"class":74,"line":469},24,[154,471,472],{"class":170},"    split ",[154,474,236],{"class":166},[154,476,274],{"class":170},[154,478,479],{"class":159},"\"MARKETPLACE_SHARE_OF_SUBS\"",[154,481,280],{"class":170},[154,483,304],{"class":159},[154,485,286],{"class":170},[154,487,489],{"class":74,"line":488},25,[154,490,196],{"emptyLinePlaceholder":195},[154,492,494,497,499,502,504,506,508,510,512],{"class":74,"line":493},26,[154,495,496],{"class":170},"    direct_seats ",[154,498,236],{"class":166},[154,500,501],{"class":170}," Decimal(seats) ",[154,503,323],{"class":166},[154,505,383],{"class":170},[154,507,386],{"class":188},[154,509,389],{"class":170},[154,511,317],{"class":166},[154,513,514],{"class":170}," split)\n",[154,516,518,521,523,525,527],{"class":74,"line":517},27,[154,519,520],{"class":170},"    market_seats ",[154,522,236],{"class":166},[154,524,501],{"class":170},[154,526,323],{"class":166},[154,528,529],{"class":170}," split\n",[154,531,533,536,538,541,543,546,549,552,554],{"class":74,"line":532},28,[154,534,535],{"class":170},"    blended ",[154,537,236],{"class":166},[154,539,540],{"class":170}," money(direct_seats ",[154,542,323],{"class":166},[154,544,545],{"class":170}," net_direct(price) ",[154,547,548],{"class":166},"+",[154,550,551],{"class":170}," market_seats ",[154,553,323],{"class":166},[154,555,556],{"class":170}," net_marketplace(price))\n",[154,558,560],{"class":74,"line":559},29,[154,561,196],{"emptyLinePlaceholder":195},[154,563,565,568,571,574,577,580,583,586,589],{"class":74,"line":564},30,[154,566,567],{"class":188},"    print",[154,569,570],{"class":170},"(",[154,572,573],{"class":166},"f",[154,575,576],{"class":159},"\"direct per sub      ",[154,578,579],{"class":188},"{",[154,581,582],{"class":170},"net_direct(price)",[154,584,585],{"class":188},"}",[154,587,588],{"class":159},"\"",[154,590,242],{"class":170},[154,592,594,596,598,600,603,605,608,610,612],{"class":74,"line":593},31,[154,595,567],{"class":188},[154,597,570],{"class":170},[154,599,573],{"class":166},[154,601,602],{"class":159},"\"marketplace per sub ",[154,604,579],{"class":188},[154,606,607],{"class":170},"net_marketplace(price)",[154,609,585],{"class":188},[154,611,588],{"class":159},[154,613,242],{"class":170},[154,615,617,619,621,623,626,628,631,633,635],{"class":74,"line":616},32,[154,618,567],{"class":188},[154,620,570],{"class":170},[154,622,573],{"class":166},[154,624,625],{"class":159},"\"blended monthly     ",[154,627,579],{"class":188},[154,629,630],{"class":170},"blended",[154,632,585],{"class":188},[154,634,588],{"class":159},[154,636,242],{"class":170},[154,638,640,642,644,646,649,651,654,656,658,660,663,665,667],{"class":74,"line":639},33,[154,641,567],{"class":188},[154,643,570],{"class":170},[154,645,573],{"class":166},[154,647,648],{"class":159},"\"commission drag     ",[154,650,579],{"class":188},[154,652,653],{"class":170},"money(Decimal(seats) ",[154,655,323],{"class":166},[154,657,545],{"class":170},[154,659,317],{"class":166},[154,661,662],{"class":170}," blended)",[154,664,585],{"class":188},[154,666,588],{"class":159},[154,668,242],{"class":170},[14,670,671],{},"Two costs never show up in that model and both matter. Payouts arrive on a delay measured in weeks rather than days, so a marketplace-heavy revenue mix worsens your cash conversion cycle exactly when you are paying infrastructure bills monthly. And you do not get the customer's email address — support arrives through the platform, churn arrives without warning, and you cannot run a price increase or a win-back campaign against a list you do not hold.",[29,673,675],{"id":674},"the-proxy-secret-is-your-entire-perimeter","The proxy secret is your entire perimeter",[14,677,678,679,682],{},"When a consumer calls your API through the marketplace, the request hits the platform gateway first. The gateway authenticates the subscriber against its own key, meters the call against their plan, then forwards the request to your origin with a set of injected headers. The critical one is ",[151,680,681],{},"X-RapidAPI-Proxy-Secret",": a per-listing shared secret proving the request genuinely came through the gateway and not from someone who found your origin hostname.",[14,684,685,686,689,690,693,694,698],{},"If you skip that check, your origin is an open API. Anyone who reads a ",[151,687,688],{},"Host"," header in a network trace can call you directly, bypass the meter entirely, and you will pay the compute while the marketplace shows zero usage. Verify the secret in a dependency, compare it with ",[151,691,692],{},"hmac.compare_digest"," so you are not leaking timing information, and reject with 403 before any business logic runs. This slots naturally into an async-native ",[18,695,697],{"href":696},"\u002Fgetting-started-with-python-apis-for-builders\u002Fsetting-up-fastapi\u002F","FastAPI setup",".",[40,700,49,705,49,708,49,711,49,714,49,732,49,737,49,743,49,749,49,755,49,759,49,763,49,767,49,772,49,779,49,783,49,787,49,791,49,793,49,797,49,801,49,804,49,807,49,810,49,814,49,818,49,821],{"viewBox":701,"role":43,"ariaLabelledBy":702,"xmlns":47,"style":48},"0 0 720 300",[703,704],"rapidapi-flow-t","rapidapi-flow-d",[51,706,707],{"id":703},"Marketplace gateway path versus direct customer path",[55,709,710],{"id":704},"Marketplace consumers call the platform gateway, which meters the call and forwards it with an injected proxy secret and subscription headers; direct customers send a bearer key straight to the origin. Both paths converge on one auth gate inside the origin.",[59,712],{"x":61,"y":61,"width":62,"height":713,"fill":64},"300",[715,716,717,718,49],"defs",{},"\n    ",[719,720,727,728,717],"marker",{"id":721,"viewBox":722,"refX":723,"refY":724,"markerWidth":725,"markerHeight":725,"orient":726},"rapidapi-flow-arrow","0 0 10 10","9","5","7","auto-start-reverse","\n      ",[729,730],"path",{"d":731,"fill":133},"M0 0 L10 5 L0 10 z",[59,733],{"x":68,"y":734,"width":735,"height":77,"rx":736,"fill":64,"stroke":107,"style":80},"48","150","10",[66,738,742],{"x":739,"y":740,"fill":70,"style":741},"95","79","text-anchor:middle;font-size:13;font-family:var(--font-sans);","Marketplace user",[74,744],{"x1":745,"y1":746,"x2":747,"y2":746,"stroke":133,"style":748},"170","74","222","stroke-width:2;marker-end:url(#rapidapi-flow-arrow);",[59,750],{"x":751,"y":752,"width":753,"height":754,"rx":736,"fill":64,"stroke":121,"style":80},"226","42","180","64",[66,756,758],{"x":120,"y":757,"fill":70,"style":741},"68","Platform gateway",[66,760,762],{"x":120,"y":761,"fill":133,"style":138},"88","meters + bills",[74,764],{"x1":765,"y1":746,"x2":766,"y2":746,"stroke":133,"style":748},"406","498",[66,768,771],{"x":769,"y":770,"fill":133,"style":138},"452","36","injects headers",[59,773],{"x":774,"y":775,"width":776,"height":777,"rx":736,"fill":778,"stroke":79,"style":80},"502","34","196","80","var(--c-surface-alt)",[66,780,681],{"x":781,"y":782,"fill":70,"style":138},"600","58",[66,784,786],{"x":781,"y":785,"fill":70,"style":138},"78","X-RapidAPI-User",[66,788,790],{"x":781,"y":789,"fill":70,"style":138},"98","X-RapidAPI-Subscription",[59,792],{"x":68,"y":776,"width":735,"height":77,"rx":736,"fill":64,"stroke":92,"style":80},[66,794,796],{"x":739,"y":795,"fill":70,"style":741},"227","Direct customer",[66,798,800],{"x":120,"y":799,"fill":133,"style":138},"216","Authorization: Bearer sk_live_…",[74,802],{"x1":745,"y1":747,"x2":766,"y2":747,"stroke":133,"style":803},"stroke-width:2;marker-end:url(#rapidapi-flow-arrow);stroke-dasharray:5 4;",[59,805],{"x":774,"y":735,"width":776,"height":806,"rx":736,"fill":64,"stroke":107,"style":80},"120",[66,808,809],{"x":781,"y":753,"fill":70,"style":741},"Your FastAPI origin",[66,811,813],{"x":781,"y":812,"fill":133,"style":138},"206","one auth gate",[66,815,817],{"x":781,"y":816,"fill":133,"style":138},"228","one quota counter",[66,819,820],{"x":781,"y":63,"fill":133,"style":138},"one usage log",[74,822],{"x1":781,"y1":823,"x2":781,"y2":824,"stroke":133,"style":748},"114","146",[14,826,827,828,698],{},"Two hardening rules go with that check. First, lock your origin at the network edge as well: if your host supports it, allow only the gateway's egress ranges on the marketplace hostname and serve direct customers on a separate hostname. Defence in depth costs nothing here. Second, treat the proxy secret as a rotating credential, not a constant — accept a current and a previous value during a rotation window, exactly as you would when ",[18,829,831],{"href":830},"\u002Fgetting-started-with-python-apis-for-builders\u002Fhandling-api-authentication-in-python\u002Frotating-api-keys-without-downtime\u002F","rotating API keys without downtime",[144,833,835],{"className":146,"code":834,"language":148,"meta":149,"style":149},"import hmac\nimport os\nfrom dataclasses import dataclass\nfrom typing import Annotated\n\nfrom fastapi import Depends, Header, HTTPException, status\n\n\ndef _accepted_proxy_secrets() -> tuple[str, ...]:\n    raw = os.getenv(\"RAPIDAPI_PROXY_SECRETS\", \"\")\n    return tuple(s.strip() for s in raw.split(\",\") if s.strip())\n\n\n@dataclass(frozen=True, slots=True)\nclass Caller:\n    channel: str          # \"marketplace\" or \"direct\"\n    account_id: str\n    plan: str\n\n\nasync def marketplace_caller(\n    proxy_secret: Annotated[str | None, Header(alias=\"X-RapidAPI-Proxy-Secret\")] = None,\n    rapid_user: Annotated[str | None, Header(alias=\"X-RapidAPI-User\")] = None,\n    subscription: Annotated[str | None, Header(alias=\"X-RapidAPI-Subscription\")] = None,\n) -> Caller | None:\n    if proxy_secret is None:\n        return None\n    accepted = _accepted_proxy_secrets()\n    if not any(hmac.compare_digest(proxy_secret, s) for s in accepted):\n        raise HTTPException(status.HTTP_403_FORBIDDEN, \"Invalid gateway credential\")\n    if not rapid_user:\n        raise HTTPException(status.HTTP_400_BAD_REQUEST, \"Missing subscriber identity\")\n    return Caller(\n        channel=\"marketplace\",\n        account_id=f\"rapidapi:{rapid_user}\",\n        plan=(subscription or \"BASIC\").upper(),\n    )\n",[151,836,837,844,850,862,874,878,890,894,898,919,939,971,975,979,1005,1015,1026,1034,1041,1045,1049,1063,1097,1125,1153,1165,1180,1188,1198,1220,1238,1247,1263,1270,1283,1307,1327],{"__ignoreMap":149},[154,838,839,841],{"class":74,"line":156},[154,840,167],{"class":166},[154,842,843],{"class":170}," hmac\n",[154,845,846,848],{"class":74,"line":163},[154,847,167],{"class":166},[154,849,171],{"class":170},[154,851,852,854,857,859],{"class":74,"line":174},[154,853,177],{"class":166},[154,855,856],{"class":170}," dataclasses ",[154,858,167],{"class":166},[154,860,861],{"class":170}," dataclass\n",[154,863,864,866,869,871],{"class":74,"line":192},[154,865,177],{"class":166},[154,867,868],{"class":170}," typing ",[154,870,167],{"class":166},[154,872,873],{"class":170}," Annotated\n",[154,875,876],{"class":74,"line":199},[154,877,196],{"emptyLinePlaceholder":195},[154,879,880,882,885,887],{"class":74,"line":204},[154,881,177],{"class":166},[154,883,884],{"class":170}," fastapi ",[154,886,167],{"class":166},[154,888,889],{"class":170}," Depends, Header, HTTPException, status\n",[154,891,892],{"class":74,"line":217},[154,893,196],{"emptyLinePlaceholder":195},[154,895,896],{"class":74,"line":245},[154,897,196],{"emptyLinePlaceholder":195},[154,899,900,902,905,908,911,913,916],{"class":74,"line":250},[154,901,207],{"class":166},[154,903,904],{"class":210}," _accepted_proxy_secrets",[154,906,907],{"class":170},"() -> tuple[",[154,909,910],{"class":188},"str",[154,912,280],{"class":170},[154,914,915],{"class":188},"...",[154,917,918],{"class":170},"]:\n",[154,920,921,924,926,929,932,934,937],{"class":74,"line":255},[154,922,923],{"class":170},"    raw ",[154,925,236],{"class":166},[154,927,928],{"class":170}," os.getenv(",[154,930,931],{"class":159},"\"RAPIDAPI_PROXY_SECRETS\"",[154,933,280],{"class":170},[154,935,936],{"class":159},"\"\"",[154,938,242],{"class":170},[154,940,941,943,946,949,952,955,958,961,964,966,968],{"class":74,"line":266},[154,942,220],{"class":166},[154,944,945],{"class":188}," tuple",[154,947,948],{"class":170},"(s.strip() ",[154,950,951],{"class":166},"for",[154,953,954],{"class":170}," s ",[154,956,957],{"class":166},"in",[154,959,960],{"class":170}," raw.split(",[154,962,963],{"class":159},"\",\"",[154,965,389],{"class":170},[154,967,410],{"class":166},[154,969,970],{"class":170}," s.strip())\n",[154,972,973],{"class":74,"line":289},[154,974,196],{"emptyLinePlaceholder":195},[154,976,977],{"class":74,"line":309},[154,978,196],{"emptyLinePlaceholder":195},[154,980,981,984,986,989,991,994,996,999,1001,1003],{"class":74,"line":334},[154,982,983],{"class":210},"@dataclass",[154,985,570],{"class":170},[154,987,988],{"class":232},"frozen",[154,990,236],{"class":166},[154,992,993],{"class":188},"True",[154,995,280],{"class":170},[154,997,998],{"class":232},"slots",[154,1000,236],{"class":166},[154,1002,993],{"class":188},[154,1004,242],{"class":170},[154,1006,1007,1010,1013],{"class":74,"line":339},[154,1008,1009],{"class":166},"class",[154,1011,1012],{"class":210}," Caller",[154,1014,422],{"class":170},[154,1016,1017,1020,1022],{"class":74,"line":344},[154,1018,1019],{"class":170},"    channel: ",[154,1021,910],{"class":188},[154,1023,1025],{"class":1024},"sJ8bj","          # \"marketplace\" or \"direct\"\n",[154,1027,1028,1031],{"class":74,"line":354},[154,1029,1030],{"class":170},"    account_id: ",[154,1032,1033],{"class":188},"str\n",[154,1035,1036,1039],{"class":74,"line":374},[154,1037,1038],{"class":170},"    plan: ",[154,1040,1033],{"class":188},[154,1042,1043],{"class":74,"line":397},[154,1044,196],{"emptyLinePlaceholder":195},[154,1046,1047],{"class":74,"line":402},[154,1048,196],{"emptyLinePlaceholder":195},[154,1050,1051,1054,1057,1060],{"class":74,"line":407},[154,1052,1053],{"class":166},"async",[154,1055,1056],{"class":166}," def",[154,1058,1059],{"class":210}," marketplace_caller",[154,1061,1062],{"class":170},"(\n",[154,1064,1065,1068,1070,1073,1076,1079,1082,1084,1087,1090,1092,1094],{"class":74,"line":425},[154,1066,1067],{"class":170},"    proxy_secret: Annotated[",[154,1069,910],{"class":188},[154,1071,1072],{"class":166}," |",[154,1074,1075],{"class":188}," None",[154,1077,1078],{"class":170},", Header(",[154,1080,1081],{"class":232},"alias",[154,1083,236],{"class":166},[154,1085,1086],{"class":159},"\"X-RapidAPI-Proxy-Secret\"",[154,1088,1089],{"class":170},")] ",[154,1091,236],{"class":166},[154,1093,1075],{"class":188},[154,1095,1096],{"class":170},",\n",[154,1098,1099,1102,1104,1106,1108,1110,1112,1114,1117,1119,1121,1123],{"class":74,"line":445},[154,1100,1101],{"class":170},"    rapid_user: Annotated[",[154,1103,910],{"class":188},[154,1105,1072],{"class":166},[154,1107,1075],{"class":188},[154,1109,1078],{"class":170},[154,1111,1081],{"class":232},[154,1113,236],{"class":166},[154,1115,1116],{"class":159},"\"X-RapidAPI-User\"",[154,1118,1089],{"class":170},[154,1120,236],{"class":166},[154,1122,1075],{"class":188},[154,1124,1096],{"class":170},[154,1126,1127,1130,1132,1134,1136,1138,1140,1142,1145,1147,1149,1151],{"class":74,"line":469},[154,1128,1129],{"class":170},"    subscription: Annotated[",[154,1131,910],{"class":188},[154,1133,1072],{"class":166},[154,1135,1075],{"class":188},[154,1137,1078],{"class":170},[154,1139,1081],{"class":232},[154,1141,236],{"class":166},[154,1143,1144],{"class":159},"\"X-RapidAPI-Subscription\"",[154,1146,1089],{"class":170},[154,1148,236],{"class":166},[154,1150,1075],{"class":188},[154,1152,1096],{"class":170},[154,1154,1155,1158,1161,1163],{"class":74,"line":488},[154,1156,1157],{"class":170},") -> Caller ",[154,1159,1160],{"class":166},"|",[154,1162,1075],{"class":188},[154,1164,422],{"class":170},[154,1166,1167,1170,1173,1176,1178],{"class":74,"line":493},[154,1168,1169],{"class":166},"    if",[154,1171,1172],{"class":170}," proxy_secret ",[154,1174,1175],{"class":166},"is",[154,1177,1075],{"class":188},[154,1179,422],{"class":170},[154,1181,1182,1185],{"class":74,"line":517},[154,1183,1184],{"class":166},"        return",[154,1186,1187],{"class":188}," None\n",[154,1189,1190,1193,1195],{"class":74,"line":532},[154,1191,1192],{"class":170},"    accepted ",[154,1194,236],{"class":166},[154,1196,1197],{"class":170}," _accepted_proxy_secrets()\n",[154,1199,1200,1202,1205,1208,1211,1213,1215,1217],{"class":74,"line":559},[154,1201,1169],{"class":166},[154,1203,1204],{"class":166}," not",[154,1206,1207],{"class":188}," any",[154,1209,1210],{"class":170},"(hmac.compare_digest(proxy_secret, s) ",[154,1212,951],{"class":166},[154,1214,954],{"class":170},[154,1216,957],{"class":166},[154,1218,1219],{"class":170}," accepted):\n",[154,1221,1222,1225,1228,1231,1233,1236],{"class":74,"line":564},[154,1223,1224],{"class":166},"        raise",[154,1226,1227],{"class":170}," HTTPException(status.",[154,1229,1230],{"class":188},"HTTP_403_FORBIDDEN",[154,1232,280],{"class":170},[154,1234,1235],{"class":159},"\"Invalid gateway credential\"",[154,1237,242],{"class":170},[154,1239,1240,1242,1244],{"class":74,"line":593},[154,1241,1169],{"class":166},[154,1243,1204],{"class":166},[154,1245,1246],{"class":170}," rapid_user:\n",[154,1248,1249,1251,1253,1256,1258,1261],{"class":74,"line":616},[154,1250,1224],{"class":166},[154,1252,1227],{"class":170},[154,1254,1255],{"class":188},"HTTP_400_BAD_REQUEST",[154,1257,280],{"class":170},[154,1259,1260],{"class":159},"\"Missing subscriber identity\"",[154,1262,242],{"class":170},[154,1264,1265,1267],{"class":74,"line":639},[154,1266,220],{"class":166},[154,1268,1269],{"class":170}," Caller(\n",[154,1271,1273,1276,1278,1281],{"class":74,"line":1272},34,[154,1274,1275],{"class":232},"        channel",[154,1277,236],{"class":166},[154,1279,1280],{"class":159},"\"marketplace\"",[154,1282,1096],{"class":170},[154,1284,1286,1289,1291,1293,1296,1298,1301,1303,1305],{"class":74,"line":1285},35,[154,1287,1288],{"class":232},"        account_id",[154,1290,236],{"class":166},[154,1292,573],{"class":166},[154,1294,1295],{"class":159},"\"rapidapi:",[154,1297,579],{"class":188},[154,1299,1300],{"class":170},"rapid_user",[154,1302,585],{"class":188},[154,1304,588],{"class":159},[154,1306,1096],{"class":170},[154,1308,1310,1313,1315,1318,1321,1324],{"class":74,"line":1309},36,[154,1311,1312],{"class":232},"        plan",[154,1314,236],{"class":166},[154,1316,1317],{"class":170},"(subscription ",[154,1319,1320],{"class":166},"or",[154,1322,1323],{"class":159}," \"BASIC\"",[154,1325,1326],{"class":170},").upper(),\n",[154,1328,1330],{"class":74,"line":1329},37,[154,1331,1332],{"class":170},"    )\n",[14,1334,1335,1336,1339,1340,1343,1344,1347,1348,1351],{},"Note the ",[151,1337,1338],{},"Header(alias=...)"," form. FastAPI will happily map ",[151,1341,1342],{},"x_rapidapi_proxy_secret"," to the header name by convention, but the explicit alias survives refactors and reads unambiguously to the next person. Note also that ",[151,1345,1346],{},"marketplace_caller"," returns ",[151,1349,1350],{},"None"," rather than raising when the header is absent — that is what lets one route serve both channels.",[29,1353,1355],{"id":1354},"mapping-marketplace-plans-onto-your-own-quotas","Mapping marketplace plans onto your own quotas",[14,1357,1358,1359,1363],{},"The gateway meters calls against the plan the subscriber bought on the platform. You still need your own counter. Platform metering is eventually consistent from your side, gives you no per-endpoint cost visibility, and disappears the moment you delist. The rule: the marketplace plan name is an ",[1360,1361,1362],"em",{},"input"," to your quota system, never a replacement for it.",[14,1365,1366,1367,1371],{},"Keep the mapping in a TOML file rather than a dict buried in a module. Pricing changes are commercial decisions made under time pressure, and a config file can be edited and reviewed without a code deploy. The same table should drive your direct tiers, which keeps ",[18,1368,1370],{"href":1369},"\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fdesigning-api-pricing-tiers\u002F","pricing tier design"," honest across both channels.",[40,1373,49,1378,49,1381,49,1384,49,1387,49,1391,49,1394,49,1398,49,1400,49,1405,49,1409,49,1413,49,1416,49,1420,49,1423,49,1426,49,1430,49,1433,49,1435,49,1438,49,1441,49,1444,49,1448,49,1450,49,1452,49,1455,49,1458,49,1461,49,1465,49,1468,49,1470,49,1473,49,1476],{"viewBox":1374,"role":43,"ariaLabelledBy":1375,"xmlns":47,"style":48},"0 0 720 290",[1376,1377],"rapidapi-map-t","rapidapi-map-d",[51,1379,1380],{"id":1376},"Marketplace plan names mapped to internal tiers and limits",[55,1382,1383],{"id":1377},"Four rows map the marketplace subscription header values BASIC, PRO, ULTRA and MEGA onto internal tier names free, starter, growth and scale, each with its own monthly quota and per-second rate limit.",[59,1385],{"x":61,"y":61,"width":62,"height":1386,"fill":64},"290",[66,1388,1390],{"x":69,"y":1389,"fill":70,"style":97},"32","Subscription header",[66,1392,1393],{"x":713,"y":1389,"fill":70,"style":97},"Internal tier",[66,1395,1397],{"x":1396,"y":1389,"fill":70,"style":97},"500","Enforced limit",[74,1399],{"x1":69,"y1":752,"x2":129,"y2":752,"stroke":79,"style":80},[59,1401],{"x":69,"y":1402,"width":735,"height":1403,"rx":1404,"fill":64,"stroke":79,"style":80},"56","38","6",[66,1406,1408],{"x":1407,"y":777,"fill":70,"style":138},"105","BASIC",[74,1410],{"x1":753,"y1":1411,"x2":1412,"y2":1411,"stroke":133,"style":80},"75","292",[59,1414],{"x":1415,"y":1402,"width":735,"height":1403,"rx":1404,"fill":64,"stroke":92,"style":80},"296",[66,1417,1419],{"x":1418,"y":777,"fill":70,"style":138},"371","free",[66,1421,1422],{"x":1396,"y":777,"fill":133,"style":97},"500 \u002F mo · 2 rps",[59,1424],{"x":69,"y":1425,"width":735,"height":1403,"rx":1404,"fill":64,"stroke":79,"style":80},"110",[66,1427,1429],{"x":1407,"y":1428,"fill":70,"style":138},"134","PRO",[74,1431],{"x1":753,"y1":1432,"x2":1412,"y2":1432,"stroke":133,"style":80},"129",[59,1434],{"x":1415,"y":1425,"width":735,"height":1403,"rx":1404,"fill":64,"stroke":107,"style":80},[66,1436,1437],{"x":1418,"y":1428,"fill":70,"style":138},"starter",[66,1439,1440],{"x":1396,"y":1428,"fill":133,"style":97},"25k \u002F mo · 10 rps",[59,1442],{"x":69,"y":1443,"width":735,"height":1403,"rx":1404,"fill":64,"stroke":79,"style":80},"164",[66,1445,1447],{"x":1407,"y":1446,"fill":70,"style":138},"188","ULTRA",[74,1449],{"x1":753,"y1":115,"x2":1412,"y2":115,"stroke":133,"style":80},[59,1451],{"x":1415,"y":1443,"width":735,"height":1403,"rx":1404,"fill":64,"stroke":107,"style":80},[66,1453,1454],{"x":1418,"y":1446,"fill":70,"style":138},"growth",[66,1456,1457],{"x":1396,"y":1446,"fill":133,"style":97},"250k \u002F mo · 40 rps",[59,1459],{"x":69,"y":1460,"width":735,"height":1403,"rx":1404,"fill":64,"stroke":79,"style":80},"218",[66,1462,1464],{"x":1407,"y":1463,"fill":70,"style":138},"242","MEGA",[74,1466],{"x1":753,"y1":1467,"x2":1412,"y2":1467,"stroke":133,"style":80},"237",[59,1469],{"x":1415,"y":1460,"width":735,"height":1403,"rx":1404,"fill":64,"stroke":121,"style":80},[66,1471,1472],{"x":1418,"y":1463,"fill":70,"style":138},"scale",[66,1474,1475],{"x":1396,"y":1463,"fill":133,"style":97},"2M \u002F mo · 120 rps",[66,1477,1479],{"x":69,"y":1478,"fill":133,"style":97},"278","Unknown header value falls back to the free tier — never to unlimited.",[1481,1482,1483,1501],"table",{},[1484,1485,1486],"thead",{},[1487,1488,1489,1493,1495,1498],"tr",{},[1490,1491,1492],"th",{},"Header value",[1490,1494,1393],{},[1490,1496,1497],{},"Monthly quota",[1490,1499,1500],{},"Rate limit",[1502,1503,1504,1518,1532,1546],"tbody",{},[1487,1505,1506,1511,1513,1515],{},[1507,1508,1509],"td",{},[151,1510,1408],{},[1507,1512,1419],{},[1507,1514,1396],{},[1507,1516,1517],{},"2 rps",[1487,1519,1520,1524,1526,1529],{},[1507,1521,1522],{},[151,1523,1429],{},[1507,1525,1437],{},[1507,1527,1528],{},"25,000",[1507,1530,1531],{},"10 rps",[1487,1533,1534,1538,1540,1543],{},[1507,1535,1536],{},[151,1537,1447],{},[1507,1539,1454],{},[1507,1541,1542],{},"250,000",[1507,1544,1545],{},"40 rps",[1487,1547,1548,1552,1554,1557],{},[1507,1549,1550],{},[151,1551,1464],{},[1507,1553,1472],{},[1507,1555,1556],{},"2,000,000",[1507,1558,1559],{},"120 rps",[14,1561,1562],{},"The fallback matters more than the mapping. A subscription header you do not recognise means the platform shipped a plan you have not configured, and the safe response is the free tier, not unlimited access. Get that backwards once and a misconfigured listing becomes a free unlimited endpoint you are paying to serve.",[144,1564,1566],{"className":146,"code":1565,"language":148,"meta":149,"style":149},"import functools\nimport os\nimport tomllib\nfrom dataclasses import dataclass\n\n\n@dataclass(frozen=True, slots=True)\nclass Quota:\n    tier: str\n    monthly: int\n    per_second: int\n\n\n@functools.lru_cache(maxsize=1)\ndef _plan_table() -> dict[str, Quota]:\n    path = os.getenv(\"PLAN_CONFIG_PATH\", \"config\u002Fplans.toml\")\n    with open(path, \"rb\") as fh:\n        data = tomllib.load(fh)\n    return {\n        name.upper(): Quota(\n            tier=cfg[\"tier\"],\n            monthly=int(cfg[\"monthly_quota\"]),\n            per_second=int(cfg[\"rate_limit_per_second\"]),\n        )\n        for name, cfg in data[\"plans\"].items()\n    }\n\n\ndef resolve_quota(caller: Caller) -> Quota:\n    table = _plan_table()\n    match caller:\n        case Caller(channel=\"marketplace\", plan=plan) if plan in table:\n            return table[plan]\n        case Caller(channel=\"marketplace\"):\n            return table[\"BASIC\"]          # unknown plan -> most restrictive\n        case Caller(channel=\"direct\", plan=plan):\n            return table.get(plan.upper(), table[\"BASIC\"])\n    raise ValueError(\"unroutable caller\")\n",[151,1567,1568,1575,1581,1588,1598,1602,1606,1628,1637,1644,1652,1659,1663,1667,1683,1698,1717,1739,1749,1756,1761,1777,1796,1812,1817,1836,1841,1845,1849,1859,1869,1877,1912,1920,1935,1951,1973,1985],{"__ignoreMap":149},[154,1569,1570,1572],{"class":74,"line":156},[154,1571,167],{"class":166},[154,1573,1574],{"class":170}," functools\n",[154,1576,1577,1579],{"class":74,"line":163},[154,1578,167],{"class":166},[154,1580,171],{"class":170},[154,1582,1583,1585],{"class":74,"line":174},[154,1584,167],{"class":166},[154,1586,1587],{"class":170}," tomllib\n",[154,1589,1590,1592,1594,1596],{"class":74,"line":192},[154,1591,177],{"class":166},[154,1593,856],{"class":170},[154,1595,167],{"class":166},[154,1597,861],{"class":170},[154,1599,1600],{"class":74,"line":199},[154,1601,196],{"emptyLinePlaceholder":195},[154,1603,1604],{"class":74,"line":204},[154,1605,196],{"emptyLinePlaceholder":195},[154,1607,1608,1610,1612,1614,1616,1618,1620,1622,1624,1626],{"class":74,"line":217},[154,1609,983],{"class":210},[154,1611,570],{"class":170},[154,1613,988],{"class":232},[154,1615,236],{"class":166},[154,1617,993],{"class":188},[154,1619,280],{"class":170},[154,1621,998],{"class":232},[154,1623,236],{"class":166},[154,1625,993],{"class":188},[154,1627,242],{"class":170},[154,1629,1630,1632,1635],{"class":74,"line":245},[154,1631,1009],{"class":166},[154,1633,1634],{"class":210}," Quota",[154,1636,422],{"class":170},[154,1638,1639,1642],{"class":74,"line":250},[154,1640,1641],{"class":170},"    tier: ",[154,1643,1033],{"class":188},[154,1645,1646,1649],{"class":74,"line":255},[154,1647,1648],{"class":170},"    monthly: ",[154,1650,1651],{"class":188},"int\n",[154,1653,1654,1657],{"class":74,"line":266},[154,1655,1656],{"class":170},"    per_second: ",[154,1658,1651],{"class":188},[154,1660,1661],{"class":74,"line":289},[154,1662,196],{"emptyLinePlaceholder":195},[154,1664,1665],{"class":74,"line":309},[154,1666,196],{"emptyLinePlaceholder":195},[154,1668,1669,1672,1674,1677,1679,1681],{"class":74,"line":334},[154,1670,1671],{"class":210},"@functools.lru_cache",[154,1673,570],{"class":170},[154,1675,1676],{"class":232},"maxsize",[154,1678,236],{"class":166},[154,1680,386],{"class":188},[154,1682,242],{"class":170},[154,1684,1685,1687,1690,1693,1695],{"class":74,"line":339},[154,1686,207],{"class":166},[154,1688,1689],{"class":210}," _plan_table",[154,1691,1692],{"class":170},"() -> dict[",[154,1694,910],{"class":188},[154,1696,1697],{"class":170},", Quota]:\n",[154,1699,1700,1703,1705,1707,1710,1712,1715],{"class":74,"line":344},[154,1701,1702],{"class":170},"    path ",[154,1704,236],{"class":166},[154,1706,928],{"class":170},[154,1708,1709],{"class":159},"\"PLAN_CONFIG_PATH\"",[154,1711,280],{"class":170},[154,1713,1714],{"class":159},"\"config\u002Fplans.toml\"",[154,1716,242],{"class":170},[154,1718,1719,1722,1725,1728,1731,1733,1736],{"class":74,"line":354},[154,1720,1721],{"class":166},"    with",[154,1723,1724],{"class":188}," open",[154,1726,1727],{"class":170},"(path, ",[154,1729,1730],{"class":159},"\"rb\"",[154,1732,389],{"class":170},[154,1734,1735],{"class":166},"as",[154,1737,1738],{"class":170}," fh:\n",[154,1740,1741,1744,1746],{"class":74,"line":374},[154,1742,1743],{"class":170},"        data ",[154,1745,236],{"class":166},[154,1747,1748],{"class":170}," tomllib.load(fh)\n",[154,1750,1751,1753],{"class":74,"line":397},[154,1752,220],{"class":166},[154,1754,1755],{"class":170}," {\n",[154,1757,1758],{"class":74,"line":402},[154,1759,1760],{"class":170},"        name.upper(): Quota(\n",[154,1762,1763,1766,1768,1771,1774],{"class":74,"line":407},[154,1764,1765],{"class":232},"            tier",[154,1767,236],{"class":166},[154,1769,1770],{"class":170},"cfg[",[154,1772,1773],{"class":159},"\"tier\"",[154,1775,1776],{"class":170},"],\n",[154,1778,1779,1782,1784,1787,1790,1793],{"class":74,"line":425},[154,1780,1781],{"class":232},"            monthly",[154,1783,236],{"class":166},[154,1785,1786],{"class":188},"int",[154,1788,1789],{"class":170},"(cfg[",[154,1791,1792],{"class":159},"\"monthly_quota\"",[154,1794,1795],{"class":170},"]),\n",[154,1797,1798,1801,1803,1805,1807,1810],{"class":74,"line":445},[154,1799,1800],{"class":232},"            per_second",[154,1802,236],{"class":166},[154,1804,1786],{"class":188},[154,1806,1789],{"class":170},[154,1808,1809],{"class":159},"\"rate_limit_per_second\"",[154,1811,1795],{"class":170},[154,1813,1814],{"class":74,"line":469},[154,1815,1816],{"class":170},"        )\n",[154,1818,1819,1822,1825,1827,1830,1833],{"class":74,"line":488},[154,1820,1821],{"class":166},"        for",[154,1823,1824],{"class":170}," name, cfg ",[154,1826,957],{"class":166},[154,1828,1829],{"class":170}," data[",[154,1831,1832],{"class":159},"\"plans\"",[154,1834,1835],{"class":170},"].items()\n",[154,1837,1838],{"class":74,"line":493},[154,1839,1840],{"class":170},"    }\n",[154,1842,1843],{"class":74,"line":517},[154,1844,196],{"emptyLinePlaceholder":195},[154,1846,1847],{"class":74,"line":532},[154,1848,196],{"emptyLinePlaceholder":195},[154,1850,1851,1853,1856],{"class":74,"line":559},[154,1852,207],{"class":166},[154,1854,1855],{"class":210}," resolve_quota",[154,1857,1858],{"class":170},"(caller: Caller) -> Quota:\n",[154,1860,1861,1864,1866],{"class":74,"line":564},[154,1862,1863],{"class":170},"    table ",[154,1865,236],{"class":166},[154,1867,1868],{"class":170}," _plan_table()\n",[154,1870,1871,1874],{"class":74,"line":593},[154,1872,1873],{"class":166},"    match",[154,1875,1876],{"class":170}," caller:\n",[154,1878,1879,1882,1885,1888,1890,1892,1894,1897,1899,1902,1904,1907,1909],{"class":74,"line":616},[154,1880,1881],{"class":166},"        case",[154,1883,1884],{"class":170}," Caller(",[154,1886,1887],{"class":232},"channel",[154,1889,236],{"class":166},[154,1891,1280],{"class":159},[154,1893,280],{"class":170},[154,1895,1896],{"class":232},"plan",[154,1898,236],{"class":166},[154,1900,1901],{"class":170},"plan) ",[154,1903,410],{"class":166},[154,1905,1906],{"class":170}," plan ",[154,1908,957],{"class":166},[154,1910,1911],{"class":170}," table:\n",[154,1913,1914,1917],{"class":74,"line":639},[154,1915,1916],{"class":166},"            return",[154,1918,1919],{"class":170}," table[plan]\n",[154,1921,1922,1924,1926,1928,1930,1932],{"class":74,"line":1272},[154,1923,1881],{"class":166},[154,1925,1884],{"class":170},[154,1927,1887],{"class":232},[154,1929,236],{"class":166},[154,1931,1280],{"class":159},[154,1933,1934],{"class":170},"):\n",[154,1936,1937,1939,1942,1945,1948],{"class":74,"line":1285},[154,1938,1916],{"class":166},[154,1940,1941],{"class":170}," table[",[154,1943,1944],{"class":159},"\"BASIC\"",[154,1946,1947],{"class":170},"]          ",[154,1949,1950],{"class":1024},"# unknown plan -> most restrictive\n",[154,1952,1953,1955,1957,1959,1961,1964,1966,1968,1970],{"class":74,"line":1309},[154,1954,1881],{"class":166},[154,1956,1884],{"class":170},[154,1958,1887],{"class":232},[154,1960,236],{"class":166},[154,1962,1963],{"class":159},"\"direct\"",[154,1965,280],{"class":170},[154,1967,1896],{"class":232},[154,1969,236],{"class":166},[154,1971,1972],{"class":170},"plan):\n",[154,1974,1975,1977,1980,1982],{"class":74,"line":1329},[154,1976,1916],{"class":166},[154,1978,1979],{"class":170}," table.get(plan.upper(), table[",[154,1981,1944],{"class":159},[154,1983,1984],{"class":170},"])\n",[154,1986,1988,1991,1994,1996,1999],{"class":74,"line":1987},38,[154,1989,1990],{"class":166},"    raise",[154,1992,1993],{"class":188}," ValueError",[154,1995,570],{"class":170},[154,1997,1998],{"class":159},"\"unroutable caller\"",[154,2000,242],{"class":170},[14,2002,2003,2004,2007,2008,2012,2013,2017],{},"Enforce the resulting ",[151,2005,2006],{},"Quota"," in the same Redis counter both channels share, following the patterns in ",[18,2009,2011],{"href":2010},"\u002Fgetting-started-with-python-apis-for-builders\u002Fmaking-http-requests-with-requests-library\u002Fbest-practices-for-api-rate-limiting\u002F","API rate limiting best practices",". Record every call to your own store as well, because the platform's dashboard will not tell you which endpoint is eating your margin — ",[18,2014,2016],{"href":2015},"\u002Fbuilding-monetizing-api-driven-micro-saas\u002Ftracking-api-usage-and-analytics\u002Flogging-api-usage-events-to-postgres\u002F","logging usage events to Postgres"," will.",[14,2019,2020],{},"Verify both paths with one script before you publish the listing. If the direct call to your marketplace hostname succeeds without a proxy secret, you have a hole.",[144,2022,2024],{"className":146,"code":2023,"language":148,"meta":149,"style":149},"import asyncio\nimport os\n\nimport httpx\n\n\nasync def probe() -> None:\n    origin = os.getenv(\"ORIGIN_BASE_URL\")\n    gateway = os.getenv(\"RAPIDAPI_GATEWAY_URL\")\n    path = os.getenv(\"PROBE_PATH\", \"\u002Fv1\u002Fstatus\")\n    async with httpx.AsyncClient(timeout=10.0) as client:\n        naked = await client.get(f\"{origin}{path}\")\n        proxied = await client.get(\n            f\"{gateway}{path}\",\n            headers={\n                \"X-RapidAPI-Key\": os.getenv(\"RAPIDAPI_TEST_KEY\", \"\"),\n                \"X-RapidAPI-Host\": os.getenv(\"RAPIDAPI_HOST\", \"\"),\n            },\n        )\n    print(f\"unauthenticated origin -> {naked.status_code} (want 403)\")\n    print(f\"through gateway        -> {proxied.status_code} (want 200)\")\n\n\nif __name__ == \"__main__\":\n    asyncio.run(probe())\n",[151,2025,2026,2033,2039,2043,2050,2054,2058,2074,2088,2102,2120,2146,2179,2191,2213,2223,2241,2257,2262,2266,2289,2312,2316,2320,2332],{"__ignoreMap":149},[154,2027,2028,2030],{"class":74,"line":156},[154,2029,167],{"class":166},[154,2031,2032],{"class":170}," asyncio\n",[154,2034,2035,2037],{"class":74,"line":163},[154,2036,167],{"class":166},[154,2038,171],{"class":170},[154,2040,2041],{"class":74,"line":174},[154,2042,196],{"emptyLinePlaceholder":195},[154,2044,2045,2047],{"class":74,"line":192},[154,2046,167],{"class":166},[154,2048,2049],{"class":170}," httpx\n",[154,2051,2052],{"class":74,"line":199},[154,2053,196],{"emptyLinePlaceholder":195},[154,2055,2056],{"class":74,"line":204},[154,2057,196],{"emptyLinePlaceholder":195},[154,2059,2060,2062,2064,2067,2070,2072],{"class":74,"line":217},[154,2061,1053],{"class":166},[154,2063,1056],{"class":166},[154,2065,2066],{"class":210}," probe",[154,2068,2069],{"class":170},"() -> ",[154,2071,1350],{"class":188},[154,2073,422],{"class":170},[154,2075,2076,2079,2081,2083,2086],{"class":74,"line":245},[154,2077,2078],{"class":170},"    origin ",[154,2080,236],{"class":166},[154,2082,928],{"class":170},[154,2084,2085],{"class":159},"\"ORIGIN_BASE_URL\"",[154,2087,242],{"class":170},[154,2089,2090,2093,2095,2097,2100],{"class":74,"line":250},[154,2091,2092],{"class":170},"    gateway ",[154,2094,236],{"class":166},[154,2096,928],{"class":170},[154,2098,2099],{"class":159},"\"RAPIDAPI_GATEWAY_URL\"",[154,2101,242],{"class":170},[154,2103,2104,2106,2108,2110,2113,2115,2118],{"class":74,"line":255},[154,2105,1702],{"class":170},[154,2107,236],{"class":166},[154,2109,928],{"class":170},[154,2111,2112],{"class":159},"\"PROBE_PATH\"",[154,2114,280],{"class":170},[154,2116,2117],{"class":159},"\"\u002Fv1\u002Fstatus\"",[154,2119,242],{"class":170},[154,2121,2122,2125,2128,2131,2134,2136,2139,2141,2143],{"class":74,"line":266},[154,2123,2124],{"class":166},"    async",[154,2126,2127],{"class":166}," with",[154,2129,2130],{"class":170}," httpx.AsyncClient(",[154,2132,2133],{"class":232},"timeout",[154,2135,236],{"class":166},[154,2137,2138],{"class":188},"10.0",[154,2140,389],{"class":170},[154,2142,1735],{"class":166},[154,2144,2145],{"class":170}," client:\n",[154,2147,2148,2151,2153,2156,2159,2161,2163,2165,2168,2171,2173,2175,2177],{"class":74,"line":289},[154,2149,2150],{"class":170},"        naked ",[154,2152,236],{"class":166},[154,2154,2155],{"class":166}," await",[154,2157,2158],{"class":170}," client.get(",[154,2160,573],{"class":166},[154,2162,588],{"class":159},[154,2164,579],{"class":188},[154,2166,2167],{"class":170},"origin",[154,2169,2170],{"class":188},"}{",[154,2172,729],{"class":170},[154,2174,585],{"class":188},[154,2176,588],{"class":159},[154,2178,242],{"class":170},[154,2180,2181,2184,2186,2188],{"class":74,"line":309},[154,2182,2183],{"class":170},"        proxied ",[154,2185,236],{"class":166},[154,2187,2155],{"class":166},[154,2189,2190],{"class":170}," client.get(\n",[154,2192,2193,2196,2198,2200,2203,2205,2207,2209,2211],{"class":74,"line":334},[154,2194,2195],{"class":166},"            f",[154,2197,588],{"class":159},[154,2199,579],{"class":188},[154,2201,2202],{"class":170},"gateway",[154,2204,2170],{"class":188},[154,2206,729],{"class":170},[154,2208,585],{"class":188},[154,2210,588],{"class":159},[154,2212,1096],{"class":170},[154,2214,2215,2218,2220],{"class":74,"line":339},[154,2216,2217],{"class":232},"            headers",[154,2219,236],{"class":166},[154,2221,2222],{"class":170},"{\n",[154,2224,2225,2228,2231,2234,2236,2238],{"class":74,"line":344},[154,2226,2227],{"class":159},"                \"X-RapidAPI-Key\"",[154,2229,2230],{"class":170},": os.getenv(",[154,2232,2233],{"class":159},"\"RAPIDAPI_TEST_KEY\"",[154,2235,280],{"class":170},[154,2237,936],{"class":159},[154,2239,2240],{"class":170},"),\n",[154,2242,2243,2246,2248,2251,2253,2255],{"class":74,"line":354},[154,2244,2245],{"class":159},"                \"X-RapidAPI-Host\"",[154,2247,2230],{"class":170},[154,2249,2250],{"class":159},"\"RAPIDAPI_HOST\"",[154,2252,280],{"class":170},[154,2254,936],{"class":159},[154,2256,2240],{"class":170},[154,2258,2259],{"class":74,"line":374},[154,2260,2261],{"class":170},"            },\n",[154,2263,2264],{"class":74,"line":397},[154,2265,1816],{"class":170},[154,2267,2268,2270,2272,2274,2277,2279,2282,2284,2287],{"class":74,"line":402},[154,2269,567],{"class":188},[154,2271,570],{"class":170},[154,2273,573],{"class":166},[154,2275,2276],{"class":159},"\"unauthenticated origin -> ",[154,2278,579],{"class":188},[154,2280,2281],{"class":170},"naked.status_code",[154,2283,585],{"class":188},[154,2285,2286],{"class":159}," (want 403)\"",[154,2288,242],{"class":170},[154,2290,2291,2293,2295,2297,2300,2302,2305,2307,2310],{"class":74,"line":407},[154,2292,567],{"class":188},[154,2294,570],{"class":170},[154,2296,573],{"class":166},[154,2298,2299],{"class":159},"\"through gateway        -> ",[154,2301,579],{"class":188},[154,2303,2304],{"class":170},"proxied.status_code",[154,2306,585],{"class":188},[154,2308,2309],{"class":159}," (want 200)\"",[154,2311,242],{"class":170},[154,2313,2314],{"class":74,"line":425},[154,2315,196],{"emptyLinePlaceholder":195},[154,2317,2318],{"class":74,"line":445},[154,2319,196],{"emptyLinePlaceholder":195},[154,2321,2322,2324,2326,2328,2330],{"class":74,"line":469},[154,2323,410],{"class":166},[154,2325,413],{"class":188},[154,2327,416],{"class":166},[154,2329,419],{"class":159},[154,2331,422],{"class":170},[154,2333,2334],{"class":74,"line":488},[154,2335,2336],{"class":170},"    asyncio.run(probe())\n",[29,2338,2340],{"id":2339},"when-to-list-and-when-to-skip","When to list and when to skip",[40,2342,49,2347,49,2350,49,2353,49,2356,49,2363,49,2368,49,2373,49,2378,49,2382,49,2385,49,2388,49,2392,49,2395,49,2398,49,2402,49,2405,49,2409,49,2412,49,2416,49,2422,49,2427,49,2431],{"viewBox":2343,"role":43,"ariaLabelledBy":2344,"xmlns":47,"style":48},"0 0 720 280",[2345,2346],"rapidapi-tree-t","rapidapi-tree-d",[51,2348,2349],{"id":2345},"Decision tree for listing an API on a marketplace",[55,2351,2352],{"id":2346},"Start by asking whether gross margin per call exceeds thirty percent; if not, do not list. If it does, ask whether you already have a working direct funnel: if yes, list as a secondary channel; if no, list to buy distribution.",[59,2354],{"x":61,"y":61,"width":62,"height":2355,"fill":64},"280",[715,2357,717,2358,49],{},[719,2359,727,2361,717],{"id":2360,"viewBox":722,"refX":723,"refY":724,"markerWidth":725,"markerHeight":725,"orient":726},"rapidapi-tree-arrow",[729,2362],{"d":731,"fill":133},[59,2364],{"x":2365,"y":2366,"width":2367,"height":734,"rx":736,"fill":64,"stroke":107,"style":80},"248","24","224",[66,2369,2372],{"x":2370,"y":2371,"fill":70,"style":741},"360","54","Margin per call above 30%?",[729,2374],{"d":2375,"stroke":133,"fill":2376,"style":2377},"M300 72 L300 108 L170 108 L170 130","none","stroke-width:2;marker-end:url(#rapidapi-tree-arrow);",[66,2379,2381],{"x":78,"y":2380,"fill":133,"style":138},"100","no",[729,2383],{"d":2384,"stroke":133,"fill":2376,"style":2377},"M420 72 L420 108 L540 108 L540 130",[66,2386,2387],{"x":1396,"y":2380,"fill":133,"style":138},"yes",[59,2389],{"x":2390,"y":1428,"width":2391,"height":734,"rx":736,"fill":64,"stroke":121,"style":80},"60","220",[66,2393,2394],{"x":745,"y":1443,"fill":70,"style":741},"Do not list — fix pricing",[59,2396],{"x":2397,"y":1428,"width":2391,"height":734,"rx":736,"fill":64,"stroke":107,"style":80},"430",[66,2399,2401],{"x":2400,"y":1443,"fill":70,"style":741},"540","Direct funnel converting?",[729,2403],{"d":2404,"stroke":133,"fill":2376,"style":2377},"M480 182 L480 210 L330 210 L330 226",[66,2406,2387],{"x":2407,"y":2408,"fill":133,"style":138},"404","204",[729,2410],{"d":2411,"stroke":133,"fill":2376,"style":2377},"M600 182 L600 226",[66,2413,2381],{"x":2414,"y":2415,"fill":133,"style":138},"646","208",[59,2417],{"x":2418,"y":2419,"width":2420,"height":2421,"rx":736,"fill":64,"stroke":92,"style":80},"210","230","240","40",[66,2423,2426],{"x":2424,"y":2425,"fill":70,"style":138},"330","255","List as a secondary channel",[59,2428],{"x":2429,"y":2419,"width":2391,"height":2421,"rx":736,"fill":64,"stroke":2430,"style":80},"480","var(--c-yellow)",[66,2432,2434],{"x":2433,"y":2425,"fill":70,"style":138},"590","List to buy distribution",[14,2436,2437,2438,2442],{},"List when your API is a self-explanatory utility that a developer can evaluate in one request — geocoding, currency conversion, document parsing, an enrichment lookup. Marketplace buyers browse by capability and convert without a sales conversation, which suits exactly that shape of product. List when you are pre-launch with no audience and the alternative to a 20% commission is zero revenue. And list when your gross margin per call comfortably exceeds 30%, so the commission still leaves you a business; run the numbers with ",[18,2439,2441],{"href":2440},"\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fdesigning-api-pricing-tiers\u002Fcalculating-cost-per-api-request\u002F","cost per API request"," before you decide.",[14,2444,2445],{},"Skip it when your unit economics are thin — anything that proxies an expensive upstream model or dataset, where a 20% haircut turns a 15% margin negative. Skip it when your product needs onboarding, contracts, or per-customer configuration, because marketplace buyers churn as impulsively as they subscribe. Skip it when you are already converting organic traffic on your own site at a healthy rate: at that point the listing mostly cannibalises full-price signups. And skip it if you cannot afford the cash flow delay, because payout lag punishes anyone running close to the line.",[29,2447,2449],{"id":2448},"migrating-adding-the-listing-without-moving-the-business","Migrating: adding the listing without moving the business",[14,2451,2452],{},"The switch is additive, not a replacement, and it takes an afternoon if you already have key-based auth working.",[2454,2455,2456,2460,2470,2473,2480,2483],"ol",{},[2457,2458,2459],"li",{},"Add a second hostname or route prefix for marketplace traffic. Keep the direct hostname untouched so existing customers see zero change.",[2457,2461,2462,2463,2465,2466,2469],{},"Put ",[151,2464,1346],{}," in front of the shared auth dependency and fall back to your existing bearer-key check when the proxy header is absent. One route, two credentials, one ",[151,2467,2468],{},"Caller"," object downstream.",[2457,2471,2472],{},"Load the plan table from TOML and back-fill your existing direct tiers into the same file so both channels enforce identical numbers.",[2457,2474,2475,2476,698],{},"Publish an accurate OpenAPI document — the marketplace imports it to generate the listing's endpoint list and code samples, so a sloppy schema costs you conversions. Tighten it first with ",[18,2477,2479],{"href":2478},"\u002Fgetting-started-with-python-apis-for-builders\u002Fdocumenting-apis-with-openapi\u002F","OpenAPI documentation",[2457,2481,2482],{},"Set the proxy secret as a two-value list in your deployment environment, run the probe script above, and confirm the naked origin call returns 403.",[2457,2484,2485],{},"Only then flip the listing public, and keep a link back to your own site in the listing description and in every response's documentation URL.",[14,2487,2488],{},"Going the other way — delisting — is easier because you never gave up the primary channel. Freeze new signups on the platform, email the subscribers you can reach through platform support with a discount code for direct signup, keep the gateway route alive for a full billing cycle, then return 410 with a migration link.",[29,2490,2492],{"id":2491},"builder-verdict","Builder verdict",[14,2494,2495,2496,2500],{},"List, but treat it as paid distribution with a fixed budget rather than a home for your business. The winner is the hybrid setup: direct Stripe billing as the primary channel with the marketplace running alongside as a discovery surface, targeting no more than about a third of revenue. That mix costs you roughly 5% of gross in blended commission — $140 a month on the 100-subscriber example versus $466 if you sold everything through the platform — while buying you a stream of developers you would otherwise pay ads to reach. The engineering cost is genuinely small: one dependency, one config file, one probe script, and the same quota counter you already run. The strategic cost is the part to watch. The day the marketplace is more than half your revenue, you are running someone else's channel, subject to their terms and their payout schedule, with no email list to fall back on. Build the ",[18,2497,2499],{"href":2498},"\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fdeploying-apis-to-render-or-vercel\u002Fcreating-a-developer-portal-for-your-api\u002F","developer portal on your own domain"," first, ship the listing second, and keep the ratio deliberate.",[29,2502,2504],{"id":2503},"faq","FAQ",[14,2506,2507,2511],{},[2508,2509,2510],"strong",{},"Is the 20% commission worth it compared with running ads to my own site?","\nUsually yes at small scale. A 20% commission on a $29 plan is $5.80 a month, so a subscriber who stays six months costs you about $35 in commission. Paid acquisition for developer tools rarely lands a converting signup for under $60. The commission only looks expensive once you have organic traffic converting on your own site, because then you are paying it on customers you already earned.",[14,2513,2514,2517],{},[2508,2515,2516],{},"Does listing on a marketplace hurt my direct pricing?","\nIt does if you price the same plan lower on the platform to look competitive. Price identically across both channels, and put the extras — priority support, higher burst limits, an annual discount — only on your direct plans. That gives buyers a reason to come to you without making your marketplace listing look like a bait and switch.",[14,2519,2520,2523,2524,698],{},[2508,2521,2522],{},"What happens to my margin if a marketplace subscriber abuses the free tier?","\nThe platform meters the free plan, but it does not care about your compute bill, so enforce your own counter on marketplace calls exactly as you would on direct ones. Cap concurrency per account, not just monthly volume, and apply the same defences described in ",[18,2525,2527],{"href":2526},"\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fdesigning-api-pricing-tiers\u002Fpreventing-free-tier-abuse\u002F","preventing free tier abuse",[14,2529,2530,2533,2534,2537],{},[2508,2531,2532],{},"How risky is rotating the proxy secret on a live listing?","\nLow risk if you accept a list of secrets rather than one. Add the new value to ",[151,2535,2536],{},"RAPIDAPI_PROXY_SECRETS",", deploy, update the listing in the platform dashboard, wait for in-flight requests to drain, then drop the old value on the next deploy. Rotating with a single-value environment variable causes a 403 storm for however long the deploy takes.",[14,2539,2540,2543,2544,698],{},[2508,2541,2542],{},"Can I ship breaking changes to an API that is listed on a marketplace?","\nOnly with versioned paths. Marketplace subscribers never see your changelog and will not read a deprecation email you cannot send them, so a breaking change on a stable path produces silent failures and one-star reviews. Version the URL, list the new version as a separate endpoint group, and follow the guidance in ",[18,2545,2547],{"href":2546},"\u002Fscaling-and-operating-production-python-apis\u002Fversioning-and-evolving-public-apis\u002F","versioning and evolving public APIs",[29,2549,2551],{"id":2550},"related","Related",[2553,2554,2555,2560,2567,2573,2579],"ul",{},[2457,2556,2557,2559],{},[18,2558,21],{"href":20}," — the parent guide covering marketplace strategy end to end.",[2457,2561,2562,2566],{},[18,2563,2565],{"href":2564},"\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fbuilding-api-marketplaces\u002Fpython-api-subscription-billing-tutorial\u002F","Python API Subscription Billing Tutorial"," — the direct-billing stack this page treats as your primary channel.",[2457,2568,2569,2572],{},[18,2570,2571],{"href":1369},"Designing API Pricing Tiers"," — set the tier boundaries you map marketplace plans onto.",[2457,2574,2575,2578],{},[18,2576,2577],{"href":2440},"Calculating Cost per API Request"," — work out whether a 20% commission still leaves a margin.",[2457,2580,2581,2584],{},[18,2582,2583],{"href":2498},"Creating a Developer Portal for Your API"," — the owned channel that keeps the marketplace optional.",[2586,2587,2588],"style",{},"html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":149,"searchDepth":163,"depth":163,"links":2590},[2591,2592,2593,2594,2595,2596,2597,2598],{"id":31,"depth":163,"text":32},{"id":674,"depth":163,"text":675},{"id":1354,"depth":163,"text":1355},{"id":2339,"depth":163,"text":2340},{"id":2448,"depth":163,"text":2449},{"id":2491,"depth":163,"text":2492},{"id":2503,"depth":163,"text":2504},{"id":2550,"depth":163,"text":2551},"What a RapidAPI listing really costs: revenue share maths, proxy secret gateway auth in FastAPI, mapping marketplace plans to internal quotas, keeping direct billing.","md",{"pageTitle":2602,"type":2603,"datePublished":2604,"dateModified":2604},"Listing Your API on RapidAPI: Costs, Auth and Quotas","article","2026-07-23","\u002Fbuilding-monetizing-api-driven-micro-saas\u002Fbuilding-api-marketplaces\u002Flisting-your-api-on-rapidapi",{"title":5,"description":2599},"building-monetizing-api-driven-micro-saas\u002Fbuilding-api-marketplaces\u002Flisting-your-api-on-rapidapi\u002Findex","hh-3dVCLe6wX7vzTAk53sO1N2S3DHAsLXPFkCtVgBEE",{"@context":2610,"@type":2611,"mainEntity":2612},"https:\u002F\u002Fschema.org","FAQPage",[2613,2618,2621,2624,2627],{"@type":2614,"name":2510,"acceptedAnswer":2615},"Question",{"@type":2616,"text":2617},"Answer","Usually yes at small scale. A 20% commission on a $29 plan is $5.80 a month, so a subscriber who stays six months costs you about $35 in commission. Paid acquisition for developer tools rarely lands a converting signup for under $60. The commission only looks expensive once you have organic traffic converting on your own site, because then you are paying it on customers you already earned.",{"@type":2614,"name":2516,"acceptedAnswer":2619},{"@type":2616,"text":2620},"It does if you price the same plan lower on the platform to look competitive. Price identically across both channels, and put the extras — priority support, higher burst limits, an annual discount — only on your direct plans. That gives buyers a reason to come to you without making your marketplace listing look like a bait and switch.",{"@type":2614,"name":2522,"acceptedAnswer":2622},{"@type":2616,"text":2623},"The platform meters the free plan, but it does not care about your compute bill, so enforce your own counter on marketplace calls exactly as you would on direct ones. Cap concurrency per account, not just monthly volume, and apply the same defences described in preventing free tier abuse.",{"@type":2614,"name":2532,"acceptedAnswer":2625},{"@type":2616,"text":2626},"Low risk if you accept a list of secrets rather than one. Add the new value to RAPIDAPI_PROXY_SECRETS, deploy, update the listing in the platform dashboard, wait for in-flight requests to drain, then drop the old value on the next deploy. Rotating with a single-value environment variable causes a 403 storm for however long the deploy takes.",{"@type":2614,"name":2542,"acceptedAnswer":2628},{"@type":2616,"text":2629},"Only with versioned paths. Marketplace subscribers never see your changelog and will not read a deprecation email you cannot send them, so a breaking change on a stable path produces silent failures and one-star reviews. Version the URL, list the new version as a separate endpoint group, and follow the guidance in versioning and evolving public APIs.",1784887028504]