CINXE.COM
API Gateway - Wikitech
<!DOCTYPE html> <html class="client-nojs vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-sticky-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-feature-night-mode-disabled skin-theme-clientpref-day vector-toc-available" lang="en" dir="ltr"> <head> <meta charset="UTF-8"> <title>API Gateway - Wikitech</title> <script>(function(){var className="client-js vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-sticky-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-feature-night-mode-disabled skin-theme-clientpref-day vector-toc-available";var cookie=document.cookie.match(/(?:^|; )labswikimwclientpreferences=([^;]+)/);if(cookie){cookie[1].split('%2C').forEach(function(pref){className=className.replace(new RegExp('(^| )'+pref.replace(/-clientpref-\w+$|[^\w-]+/g,'')+'-clientpref-\\w+( |$)'),'$1'+pref+'$2');});}document.documentElement.className=className;}());RLCONF={"wgBreakFrames":false,"wgSeparatorTransformTable":["",""],"wgDigitTransformTable":["",""],"wgDefaultDateFormat": "dmy","wgMonthNames":["","January","February","March","April","May","June","July","August","September","October","November","December"],"wgRequestId":"88fed81e-91c4-470d-b682-47d873cc001f","wgCanonicalNamespace":"","wgCanonicalSpecialPageName":false,"wgNamespaceNumber":0,"wgPageName":"API_Gateway","wgTitle":"API Gateway","wgCurRevisionId":2232424,"wgRevisionId":2232424,"wgArticleId":446572,"wgIsArticle":true,"wgIsRedirect":false,"wgAction":"view","wgUserName":null,"wgUserGroups":["*"],"wgCategories":["Services"],"wgPageViewLanguage":"en","wgPageContentLanguage":"en","wgPageContentModel":"wikitext","wgRelevantPageName":"API_Gateway","wgRelevantArticleId":446572,"wgIsProbablyEditable":false,"wgRelevantPageIsProbablyEditable":false,"wgRestrictionEdit":[],"wgRestrictionMove":[],"wgNoticeProject":"wikitech","wgCiteReferencePreviewsActive":true,"wgMediaViewerOnClick":true,"wgMediaViewerEnabledByDefault":true,"wgVisualEditor":{"pageLanguageCode":"en","pageLanguageDir":"ltr", "pageVariantFallbacks":"en"},"wgMFDisplayWikibaseDescriptions":{"search":true,"watchlist":true,"tagline":false,"nearby":true},"wgWMESchemaEditAttemptStepOversample":false,"wgWMEPageLength":20000,"wgCentralAuthMobileDomain":false,"wgEditSubmitButtonLabelPublish":true,"wgDiscussionToolsFeaturesEnabled":{"replytool":true,"newtopictool":true,"sourcemodetoolbar":true,"topicsubscription":false,"autotopicsub":false,"visualenhancements":false,"visualenhancements_reply":false,"visualenhancements_pageframe":false},"wgDiscussionToolsFallbackEditMode":"visual","wgULSPosition":"personal","wgULSisCompactLinksEnabled":false,"wgVector2022LanguageInHeader":true,"wgULSisLanguageSelectorEmpty":false,"wgCheckUserClientHintsHeadersJsApi":["brands","architecture","bitness","fullVersionList","mobile","model","platform","platformVersion"],"wgSiteNoticeId":"2.0"};RLSTATE={"ext.globalCssJs.user.styles":"ready","site.styles":"ready","user.styles":"ready","ext.globalCssJs.user":"ready","user":"ready", "user.options":"loading","ext.pygments":"ready","ext.discussionTools.init.styles":"ready","oojs-ui-core.styles":"ready","oojs-ui.styles.indicators":"ready","mediawiki.widgets.styles":"ready","oojs-ui-core.icons":"ready","skins.vector.search.codex.styles":"ready","skins.vector.styles":"ready","skins.vector.icons":"ready","ext.wikimediamessages.styles":"ready","ext.visualEditor.desktopArticleTarget.noscript":"ready","ext.uls.pt":"ready","ext.dismissableSiteNotice.styles":"ready"};RLPAGEMODULES=["ext.pygments.view","mediawiki.page.media","site","mediawiki.page.ready","mediawiki.toc","skins.vector.js","ext.centralNotice.geoIP","ext.centralNotice.startUp","ext.gadget.site","ext.urlShortener.toolbar","ext.centralauth.centralautologin","mmv.bootstrap","ext.visualEditor.desktopArticleTarget.init","ext.visualEditor.targetLoader","ext.echo.centralauth","ext.discussionTools.init","ext.eventLogging","ext.wikimediaEvents","ext.uls.interface","ext.checkUser.clientHints","ext.dismissableSiteNotice"];</script> <script>(RLQ=window.RLQ||[]).push(function(){mw.loader.impl(function(){return["user.options@12s5i",function($,jQuery,require,module){mw.user.tokens.set({"patrolToken":"+\\","watchToken":"+\\","csrfToken":"+\\"}); }];});});</script> <link rel="stylesheet" href="/w/load.php?lang=en&modules=ext.discussionTools.init.styles%7Cext.dismissableSiteNotice.styles%7Cext.pygments%7Cext.uls.pt%7Cext.visualEditor.desktopArticleTarget.noscript%7Cext.wikimediamessages.styles%7Cmediawiki.widgets.styles%7Coojs-ui-core.icons%2Cstyles%7Coojs-ui.styles.indicators%7Cskins.vector.icons%2Cstyles%7Cskins.vector.search.codex.styles&only=styles&skin=vector-2022"> <script async="" src="/w/load.php?lang=en&modules=startup&only=scripts&raw=1&skin=vector-2022"></script> <meta name="ResourceLoaderDynamicStyles" content=""> <link rel="stylesheet" href="/w/load.php?lang=en&modules=site.styles&only=styles&skin=vector-2022"> <meta name="generator" content="MediaWiki 1.44.0-wmf.4"> <meta name="referrer" content="origin"> <meta name="referrer" content="origin-when-cross-origin"> <meta name="robots" content="max-image-preview:standard"> <meta name="format-detection" content="telephone=no"> <meta name="viewport" content="width=1120"> <meta property="og:title" content="API Gateway - Wikitech"> <meta property="og:type" content="website"> <link rel="preconnect" href="//upload.wikimedia.org"> <link rel="icon" href="/static/favicon/wikitech.ico"> <link rel="search" type="application/opensearchdescription+xml" href="/w/rest.php/v1/search" title="Wikitech (en)"> <link rel="EditURI" type="application/rsd+xml" href="//wikitech.wikimedia.org/w/api.php?action=rsd"> <link rel="canonical" href="https://wikitech.wikimedia.org/wiki/API_Gateway"> <link rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"> <link rel="alternate" type="application/atom+xml" title="Wikitech Atom feed" href="/w/index.php?title=Special:RecentChanges&feed=atom"> <link rel="dns-prefetch" href="//meta.wikimedia.org" /> <link rel="dns-prefetch" href="//login.wikimedia.org"> </head> <body class="ext-discussiontools-replytool-enabled ext-discussiontools-newtopictool-enabled ext-discussiontools-sourcemodetoolbar-enabled skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-API_Gateway rootpage-API_Gateway skin-vector-2022 action-view"><a class="mw-jump-link" href="#bodyContent">Jump to content</a> <div class="vector-header-container"> <header class="vector-header mw-header"> <div class="vector-header-start"> <nav class="vector-main-menu-landmark" aria-label="Site"> <div id="vector-main-menu-dropdown" class="vector-dropdown vector-main-menu-dropdown vector-button-flush-left vector-button-flush-right" > <input type="checkbox" id="vector-main-menu-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-main-menu-dropdown" class="vector-dropdown-checkbox " aria-label="Main menu" > <label id="vector-main-menu-dropdown-label" for="vector-main-menu-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only " aria-hidden="true" ><span class="vector-icon mw-ui-icon-menu mw-ui-icon-wikimedia-menu"></span> <span class="vector-dropdown-label-text">Main menu</span> </label> <div class="vector-dropdown-content"> <div id="vector-main-menu-unpinned-container" class="vector-unpinned-container"> <div id="vector-main-menu" class="vector-main-menu vector-pinnable-element"> <div class="vector-pinnable-header vector-main-menu-pinnable-header vector-pinnable-header-unpinned" data-feature-name="main-menu-pinned" data-pinnable-element-id="vector-main-menu" data-pinned-container-id="vector-main-menu-pinned-container" data-unpinned-container-id="vector-main-menu-unpinned-container" > <div class="vector-pinnable-header-label">Main menu</div> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.vector-main-menu.pin">move to sidebar</button> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.vector-main-menu.unpin">hide</button> </div> <div id="p-navigation" class="vector-menu mw-portlet mw-portlet-navigation" > <div class="vector-menu-heading"> Navigation </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="n-mainpage-description" class="mw-list-item"><a href="/wiki/Main_Page" title="Visit the main page [z]" accesskey="z"><span>Main page</span></a></li><li id="n-recentchanges" class="mw-list-item"><a href="/wiki/Special:RecentChanges" title="A list of recent changes in the wiki [r]" accesskey="r"><span>Recent changes</span></a></li><li id="n-Server-admin-log:-Prod" class="mw-list-item"><a href="/wiki/Server_Admin_Log"><span>Server admin log: Prod</span></a></li><li id="n-Admin-log:-RelEng" class="mw-list-item"><a href="/wiki/Release_Engineering/SAL"><span>Admin log: RelEng</span></a></li><li id="n-Incident-status" class="mw-list-item"><a href="/wiki/Incident_status"><span>Incident status</span></a></li><li id="n-Deployments" class="mw-list-item"><a href="/wiki/Deployments"><span>Deployments</span></a></li><li id="n-SRE-Team-Help" class="mw-list-item"><a href="/wiki/SRE/SRE_Team_requests"><span>SRE Team Help</span></a></li> </ul> </div> </div> <div id="p-Cloud_VPS_&_Toolforge" class="vector-menu mw-portlet mw-portlet-Cloud_VPS_Toolforge" > <div class="vector-menu-heading"> Cloud VPS & Toolforge </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="n-Cloud-VPS-portal" class="mw-list-item"><a href="/wiki/Portal:Cloud_VPS"><span>Cloud VPS portal</span></a></li><li id="n-Toolforge-portal" class="mw-list-item"><a href="/wiki/Portal:Toolforge"><span>Toolforge portal</span></a></li><li id="n-Request-VPS-project" class="mw-list-item"><a href="https://phabricator.wikimedia.org/project/view/2875/"><span>Request VPS project</span></a></li><li id="n-Admin-log:-Cloud-VPS" class="mw-list-item"><a href="/wiki/Cloud_VPS_Server_Admin_Log"><span>Admin log: Cloud VPS</span></a></li> </ul> </div> </div> </div> </div> </div> </div> </nav> <a href="/wiki/Main_Page" class="mw-logo"> <img class="mw-logo-icon" src="/static/images/icons/wikitech.svg" alt="" aria-hidden="true" height="50" width="50"> <span class="mw-logo-container skin-invert"> <img class="mw-logo-wordmark" alt="Wikitech" src="/static/images/mobile/copyright/wikitech-wordmark.svg" style="width: 8.75em; height: 1.6875em;"> </span> </a> </div> <div class="vector-header-end"> <div id="p-search" role="search" class="vector-search-box-vue vector-search-box-collapses vector-search-box-show-thumbnail vector-search-box-auto-expand-width vector-search-box"> <a href="/wiki/Special:Search" class="cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only search-toggle" title="Search Wikitech [f]" accesskey="f"><span class="vector-icon mw-ui-icon-search mw-ui-icon-wikimedia-search"></span> <span>Search</span> </a> <div class="vector-typeahead-search-container"> <div class="cdx-typeahead-search cdx-typeahead-search--show-thumbnail cdx-typeahead-search--auto-expand-width"> <form action="/w/index.php" id="searchform" class="cdx-search-input cdx-search-input--has-end-button"> <div id="simpleSearch" class="cdx-search-input__input-wrapper" data-search-loc="header-moved"> <div class="cdx-text-input cdx-text-input--has-start-icon"> <input class="cdx-text-input__input" type="search" name="search" placeholder="Search Wikitech" aria-label="Search Wikitech" autocapitalize="sentences" title="Search Wikitech [f]" accesskey="f" id="searchInput" > <span class="cdx-text-input__icon cdx-text-input__start-icon"></span> </div> <input type="hidden" name="title" value="Special:Search"> </div> <button class="cdx-button cdx-search-input__end-button">Search</button> </form> </div> </div> </div> <nav class="vector-user-links vector-user-links-wide" aria-label="Personal tools"> <div class="vector-user-links-main"> <div id="p-vector-user-menu-preferences" class="vector-menu mw-portlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="ca-uls" class="mw-list-item active user-links-collapsible-item"><a data-mw="interface" href="#" class="uls-trigger cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet"><span class="vector-icon mw-ui-icon-wikimedia-language mw-ui-icon-wikimedia-wikimedia-language"></span> <span>English</span></a> </li> </ul> </div> </div> <div id="p-vector-user-menu-userpage" class="vector-menu mw-portlet emptyPortlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> </ul> </div> </div> <nav class="vector-appearance-landmark" aria-label="Appearance"> <div id="vector-appearance-dropdown" class="vector-dropdown " title="Change the appearance of the page's font size, width, and color" > <input type="checkbox" id="vector-appearance-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-appearance-dropdown" class="vector-dropdown-checkbox " aria-label="Appearance" > <label id="vector-appearance-dropdown-label" for="vector-appearance-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only " aria-hidden="true" ><span class="vector-icon mw-ui-icon-appearance mw-ui-icon-wikimedia-appearance"></span> <span class="vector-dropdown-label-text">Appearance</span> </label> <div class="vector-dropdown-content"> <div id="vector-appearance-unpinned-container" class="vector-unpinned-container"> </div> </div> </div> </nav> <div id="p-vector-user-menu-notifications" class="vector-menu mw-portlet emptyPortlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> </ul> </div> </div> <div id="p-vector-user-menu-overflow" class="vector-menu mw-portlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="pt-sitesupport-2" class="user-links-collapsible-item mw-list-item user-links-collapsible-item"><a data-mw="interface" href="https://donate.wikimedia.org/?utm_source=donate&utm_medium=sidebar&utm_campaign=spontaneous&uselang=en" class=""><span>Donate</span></a> </li> <li id="pt-login-2" class="user-links-collapsible-item mw-list-item user-links-collapsible-item"><a data-mw="interface" href="/w/index.php?title=Special:UserLogin&returnto=API+Gateway" title="You are encouraged to log in; however, it is not mandatory [o]" accesskey="o" class=""><span>Log in</span></a> </li> </ul> </div> </div> </div> <div id="vector-user-links-dropdown" class="vector-dropdown vector-user-menu vector-button-flush-right vector-user-menu-logged-out user-links-collapsible-item" title="More options" > <input type="checkbox" id="vector-user-links-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-user-links-dropdown" class="vector-dropdown-checkbox " aria-label="Personal tools" > <label id="vector-user-links-dropdown-label" for="vector-user-links-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only " aria-hidden="true" ><span class="vector-icon mw-ui-icon-ellipsis mw-ui-icon-wikimedia-ellipsis"></span> <span class="vector-dropdown-label-text">Personal tools</span> </label> <div class="vector-dropdown-content"> <div id="p-personal" class="vector-menu mw-portlet mw-portlet-personal user-links-collapsible-item" title="User menu" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="pt-sitesupport" class="user-links-collapsible-item mw-list-item"><a href="https://donate.wikimedia.org/?utm_source=donate&utm_medium=sidebar&utm_campaign=spontaneous&uselang=en"><span>Donate</span></a></li><li id="pt-login" class="user-links-collapsible-item mw-list-item"><a href="/w/index.php?title=Special:UserLogin&returnto=API+Gateway" title="You are encouraged to log in; however, it is not mandatory [o]" accesskey="o"><span class="vector-icon mw-ui-icon-logIn mw-ui-icon-wikimedia-logIn"></span> <span>Log in</span></a></li> </ul> </div> </div> </div> </div> </nav> </div> </header> </div> <div class="mw-page-container"> <div class="mw-page-container-inner"> <div class="vector-sitenotice-container"> <div id="siteNotice"><div id="mw-dismissablenotice-anonplace"></div><script>(function(){var node=document.getElementById("mw-dismissablenotice-anonplace");if(node){node.outerHTML="\u003Cdiv class=\"mw-dismissable-notice\"\u003E\u003Cdiv class=\"mw-dismissable-notice-close\"\u003E[\u003Ca tabindex=\"0\" role=\"button\"\u003Edismiss\u003C/a\u003E]\u003C/div\u003E\u003Cdiv class=\"mw-dismissable-notice-body\"\u003E\u003C!-- CentralNotice --\u003E\u003Cdiv id=\"localNotice\" data-nosnippet=\"\"\u003E\u003Cdiv class=\"sitenotice\" lang=\"en\" dir=\"ltr\"\u003E\u003Ctable style=\"width: 75%; background-color: var(--background-color-warning-subtle, #fdf2d5); border: var(--border-subtle, 1px solid #987027); color: var(--color-base, #202122); border-radius: 10px; padding: 5px; margin: 0 auto;\"\u003E\n\u003Ctbody\u003E\u003Ctr\u003E\n\u003Ctd style=\"width:40px; height:40px; text-align:center; vertical-align:middle; padding: 2px;\"\u003E\u003Cspan typeof=\"mw:File\"\u003E\u003Ca href=\"/wiki/File:OOjs_UI_icon_alert-warning.svg\" class=\"mw-file-description\"\u003E\u003Cimg src=\"//upload.wikimedia.org/wikipedia/commons/thumb/3/3b/OOjs_UI_icon_alert-warning.svg/30px-OOjs_UI_icon_alert-warning.svg.png\" decoding=\"async\" width=\"30\" height=\"30\" class=\"mw-file-element\" srcset=\"//upload.wikimedia.org/wikipedia/commons/thumb/3/3b/OOjs_UI_icon_alert-warning.svg/45px-OOjs_UI_icon_alert-warning.svg.png 1.5x, //upload.wikimedia.org/wikipedia/commons/thumb/3/3b/OOjs_UI_icon_alert-warning.svg/60px-OOjs_UI_icon_alert-warning.svg.png 2x\" data-file-width=\"20\" data-file-height=\"20\" /\u003E\u003C/a\u003E\u003C/span\u003E\n\u003C/td\u003E\n\u003Ctd style=\"text-align:center; vertical-align: middle; padding: 4px; max-height: 60px;\"\u003E\u003Cb\u003EWe are migrating Wikitech to \u003Ca href=\"/wiki/Wikitech/SUL-migration\" title=\"Wikitech/SUL-migration\"\u003ESUL\u003C/a\u003E!\u003C/b\u003E\n\u003Cp\u003E\u003Cb\u003EAction may be required for your \u003Ca href=\"/wiki/Wikitech/SUL-migration#What_You_Should_Do\" title=\"Wikitech/SUL-migration\"\u003E account\u003C/a\u003E!\u003C/b\u003E\n\u003C/p\u003E\u003Cp\u003E\u003Cb\u003ETrouble logging in? Please visit \u003Ca href=\"https://phabricator.wikimedia.org/T376267\" class=\"extiw\" title=\"phab:T376267\"\u003ET376267\u003C/a\u003E\u003C/b\u003E\n\u003C/p\u003E\n\u003C/td\u003E\u003C/tr\u003E\u003C/tbody\u003E\u003C/table\u003E\u003C/div\u003E\u003C/div\u003E\u003C/div\u003E\u003C/div\u003E";}}());</script></div> </div> <div class="vector-column-start"> <div class="vector-main-menu-container"> <div id="mw-navigation"> <nav id="mw-panel" class="vector-main-menu-landmark" aria-label="Site"> <div id="vector-main-menu-pinned-container" class="vector-pinned-container"> </div> </nav> </div> </div> <div class="vector-sticky-pinned-container"> <nav id="mw-panel-toc" aria-label="Contents" data-event-name="ui.sidebar-toc" class="mw-table-of-contents-container vector-toc-landmark"> <div id="vector-toc-pinned-container" class="vector-pinned-container"> <div id="vector-toc" class="vector-toc vector-pinnable-element"> <div class="vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned" data-feature-name="toc-pinned" data-pinnable-element-id="vector-toc" > <h2 class="vector-pinnable-header-label">Contents</h2> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.vector-toc.pin">move to sidebar</button> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.vector-toc.unpin">hide</button> </div> <ul class="vector-toc-contents" id="mw-panel-toc-list"> <li id="toc-mw-content-text" class="vector-toc-list-item vector-toc-level-1"> <a href="#" class="vector-toc-link"> <div class="vector-toc-text">Beginning</div> </a> </li> <li id="toc-What_it_does" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#What_it_does"> <div class="vector-toc-text"> <span class="vector-toc-numb">1</span> <span>What it does</span> </div> </a> <ul id="toc-What_it_does-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-How_it_works" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#How_it_works"> <div class="vector-toc-text"> <span class="vector-toc-numb">2</span> <span>How it works</span> </div> </a> <button aria-controls="toc-How_it_works-sublist" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only vector-toc-toggle"> <span class="vector-icon mw-ui-icon-wikimedia-expand"></span> <span>Toggle How it works subsection</span> </button> <ul id="toc-How_it_works-sublist" class="vector-toc-list"> <li id="toc-Rate_limiting" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Rate_limiting"> <div class="vector-toc-text"> <span class="vector-toc-numb">2.1</span> <span>Rate limiting</span> </div> </a> <ul id="toc-Rate_limiting-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Routing" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Routing"> <div class="vector-toc-text"> <span class="vector-toc-numb">2.2</span> <span>Routing</span> </div> </a> <ul id="toc-Routing-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-JSON_Web_Tokens" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#JSON_Web_Tokens"> <div class="vector-toc-text"> <span class="vector-toc-numb">2.3</span> <span>JSON Web Tokens</span> </div> </a> <ul id="toc-JSON_Web_Tokens-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-API_Portal" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#API_Portal"> <div class="vector-toc-text"> <span class="vector-toc-numb">2.4</span> <span>API Portal</span> </div> </a> <ul id="toc-API_Portal-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Logs_and_analytics" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Logs_and_analytics"> <div class="vector-toc-text"> <span class="vector-toc-numb">2.5</span> <span>Logs and analytics</span> </div> </a> <ul id="toc-Logs_and_analytics-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-Where_it_runs" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#Where_it_runs"> <div class="vector-toc-text"> <span class="vector-toc-numb">3</span> <span>Where it runs</span> </div> </a> <ul id="toc-Where_it_runs-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-How_to_design_your_API" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#How_to_design_your_API"> <div class="vector-toc-text"> <span class="vector-toc-numb">4</span> <span>How to design your API</span> </div> </a> <button aria-controls="toc-How_to_design_your_API-sublist" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only vector-toc-toggle"> <span class="vector-icon mw-ui-icon-wikimedia-expand"></span> <span>Toggle How to design your API subsection</span> </button> <ul id="toc-How_to_design_your_API-sublist" class="vector-toc-list"> <li id="toc-Before_you_build" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Before_you_build"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.1</span> <span>Before you build</span> </div> </a> <ul id="toc-Before_you_build-sublist" class="vector-toc-list"> <li id="toc-Style" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Style"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.1.1</span> <span>Style</span> </div> </a> <ul id="toc-Style-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Authentication_and_authorization" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Authentication_and_authorization"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.1.2</span> <span>Authentication and authorization</span> </div> </a> <ul id="toc-Authentication_and_authorization-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Rate_limits" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Rate_limits"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.1.3</span> <span>Rate limits</span> </div> </a> <ul id="toc-Rate_limits-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-Criteria:_URL_structure" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Criteria:_URL_structure"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.2</span> <span>Criteria: URL structure</span> </div> </a> <ul id="toc-Criteria:_URL_structure-sublist" class="vector-toc-list"> <li id="toc-Namespace" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Namespace"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.2.1</span> <span>Namespace</span> </div> </a> <ul id="toc-Namespace-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Version" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Version"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.2.2</span> <span>Version</span> </div> </a> <ul id="toc-Version-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Supported_projects" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Supported_projects"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.2.3</span> <span>Supported projects</span> </div> </a> <ul id="toc-Supported_projects-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Supported_subdomains" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Supported_subdomains"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.2.4</span> <span>Supported subdomains</span> </div> </a> <ul id="toc-Supported_subdomains-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-Criteria:_Conditional_requests" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Criteria:_Conditional_requests"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.3</span> <span>Criteria: Conditional requests</span> </div> </a> <ul id="toc-Criteria:_Conditional_requests-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Next_steps" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Next_steps"> <div class="vector-toc-text"> <span class="vector-toc-numb">4.4</span> <span>Next steps</span> </div> </a> <ul id="toc-Next_steps-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-How_it's_configured" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#How_it's_configured"> <div class="vector-toc-text"> <span class="vector-toc-numb">5</span> <span>How it's configured</span> </div> </a> <button aria-controls="toc-How_it's_configured-sublist" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only vector-toc-toggle"> <span class="vector-icon mw-ui-icon-wikimedia-expand"></span> <span>Toggle How it's configured subsection</span> </button> <ul id="toc-How_it's_configured-sublist" class="vector-toc-list"> <li id="toc-Rate_limiting_internals" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Rate_limiting_internals"> <div class="vector-toc-text"> <span class="vector-toc-numb">5.1</span> <span>Rate limiting internals</span> </div> </a> <ul id="toc-Rate_limiting_internals-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-How_to_add_an_API_route" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#How_to_add_an_API_route"> <div class="vector-toc-text"> <span class="vector-toc-numb">5.2</span> <span>How to add an API route</span> </div> </a> <ul id="toc-How_to_add_an_API_route-sublist" class="vector-toc-list"> <li id="toc-Appserver_API_routes" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Appserver_API_routes"> <div class="vector-toc-text"> <span class="vector-toc-numb">5.2.1</span> <span>Appserver API routes</span> </div> </a> <ul id="toc-Appserver_API_routes-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Other_API_routes" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Other_API_routes"> <div class="vector-toc-text"> <span class="vector-toc-numb">5.2.2</span> <span>Other API routes</span> </div> </a> <ul id="toc-Other_API_routes-sublist" class="vector-toc-list"> <li id="toc-Discovery_services" class="vector-toc-list-item vector-toc-level-4"> <a class="vector-toc-link" href="#Discovery_services"> <div class="vector-toc-text"> <span class="vector-toc-numb">5.2.2.1</span> <span>Discovery services</span> </div> </a> <ul id="toc-Discovery_services-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-Versioning" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Versioning"> <div class="vector-toc-text"> <span class="vector-toc-numb">5.2.3</span> <span>Versioning</span> </div> </a> <ul id="toc-Versioning-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Documentation" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Documentation"> <div class="vector-toc-text"> <span class="vector-toc-numb">5.2.4</span> <span>Documentation</span> </div> </a> <ul id="toc-Documentation-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> </ul> </li> <li id="toc-How_to_deploy_changes" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#How_to_deploy_changes"> <div class="vector-toc-text"> <span class="vector-toc-numb">6</span> <span>How to deploy changes</span> </div> </a> <button aria-controls="toc-How_to_deploy_changes-sublist" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only vector-toc-toggle"> <span class="vector-icon mw-ui-icon-wikimedia-expand"></span> <span>Toggle How to deploy changes subsection</span> </button> <ul id="toc-How_to_deploy_changes-sublist" class="vector-toc-list"> <li id="toc-How_to_roll_back_changes" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#How_to_roll_back_changes"> <div class="vector-toc-text"> <span class="vector-toc-numb">6.1</span> <span>How to roll back changes</span> </div> </a> <ul id="toc-How_to_roll_back_changes-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-How_to_test_changes" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#How_to_test_changes"> <div class="vector-toc-text"> <span class="vector-toc-numb">7</span> <span>How to test changes</span> </div> </a> <button aria-controls="toc-How_to_test_changes-sublist" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only vector-toc-toggle"> <span class="vector-icon mw-ui-icon-wikimedia-expand"></span> <span>Toggle How to test changes subsection</span> </button> <ul id="toc-How_to_test_changes-sublist" class="vector-toc-list"> <li id="toc-In_development" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#In_development"> <div class="vector-toc-text"> <span class="vector-toc-numb">7.1</span> <span>In development</span> </div> </a> <ul id="toc-In_development-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-In_staging" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#In_staging"> <div class="vector-toc-text"> <span class="vector-toc-numb">7.2</span> <span>In staging</span> </div> </a> <ul id="toc-In_staging-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-How_to_debug_it" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#How_to_debug_it"> <div class="vector-toc-text"> <span class="vector-toc-numb">8</span> <span>How to debug it</span> </div> </a> <button aria-controls="toc-How_to_debug_it-sublist" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only vector-toc-toggle"> <span class="vector-icon mw-ui-icon-wikimedia-expand"></span> <span>Toggle How to debug it subsection</span> </button> <ul id="toc-How_to_debug_it-sublist" class="vector-toc-list"> <li id="toc-Logs" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#Logs"> <div class="vector-toc-text"> <span class="vector-toc-numb">8.1</span> <span>Logs</span> </div> </a> <ul id="toc-Logs-sublist" class="vector-toc-list"> <li id="toc-Logstash" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Logstash"> <div class="vector-toc-text"> <span class="vector-toc-numb">8.1.1</span> <span>Logstash</span> </div> </a> <ul id="toc-Logstash-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Kubernetes" class="vector-toc-list-item vector-toc-level-3"> <a class="vector-toc-link" href="#Kubernetes"> <div class="vector-toc-text"> <span class="vector-toc-numb">8.1.2</span> <span>Kubernetes</span> </div> </a> <ul id="toc-Kubernetes-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-WikimediaDebug" class="vector-toc-list-item vector-toc-level-2"> <a class="vector-toc-link" href="#WikimediaDebug"> <div class="vector-toc-text"> <span class="vector-toc-numb">8.2</span> <span>WikimediaDebug</span> </div> </a> <ul id="toc-WikimediaDebug-sublist" class="vector-toc-list"> </ul> </li> </ul> </li> <li id="toc-How_to_monitor_it" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#How_to_monitor_it"> <div class="vector-toc-text"> <span class="vector-toc-numb">9</span> <span>How to monitor it</span> </div> </a> <ul id="toc-How_to_monitor_it-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-How_to_assign_a_client_to_rate_limit_tier" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#How_to_assign_a_client_to_rate_limit_tier"> <div class="vector-toc-text"> <span class="vector-toc-numb">10</span> <span>How to assign a client to rate limit tier</span> </div> </a> <ul id="toc-How_to_assign_a_client_to_rate_limit_tier-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Known_issues" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#Known_issues"> <div class="vector-toc-text"> <span class="vector-toc-numb">11</span> <span>Known issues</span> </div> </a> <ul id="toc-Known_issues-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Related" class="vector-toc-list-item vector-toc-level-1"> <a class="vector-toc-link" href="#Related"> <div class="vector-toc-text"> <span class="vector-toc-numb">12</span> <span>Related</span> </div> </a> <ul id="toc-Related-sublist" class="vector-toc-list"> </ul> </li> </ul> </div> </div> </nav> </div> </div> <div class="mw-content-container"> <main id="content" class="mw-body"> <header class="mw-body-header vector-page-titlebar"> <nav aria-label="Contents" class="vector-toc-landmark"> <div id="vector-page-titlebar-toc" class="vector-dropdown vector-page-titlebar-toc vector-button-flush-left" > <input type="checkbox" id="vector-page-titlebar-toc-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-page-titlebar-toc" class="vector-dropdown-checkbox " aria-label="Toggle the table of contents" > <label id="vector-page-titlebar-toc-label" for="vector-page-titlebar-toc-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only " aria-hidden="true" ><span class="vector-icon mw-ui-icon-listBullet mw-ui-icon-wikimedia-listBullet"></span> <span class="vector-dropdown-label-text">Toggle the table of contents</span> </label> <div class="vector-dropdown-content"> <div id="vector-page-titlebar-toc-unpinned-container" class="vector-unpinned-container"> </div> </div> </div> </nav> <h1 id="firstHeading" class="firstHeading mw-first-heading"><span class="mw-page-title-main">API Gateway</span></h1> </header> <div class="vector-page-toolbar"> <div class="vector-page-toolbar-container"> <div id="left-navigation"> <nav aria-label="Namespaces"> <div id="p-associated-pages" class="vector-menu vector-menu-tabs mw-portlet mw-portlet-associated-pages" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="ca-nstab-main" class="selected vector-tab-noicon mw-list-item"><a href="/wiki/API_Gateway" title="View the content page [c]" accesskey="c"><span>Page</span></a></li><li id="ca-talk" class="new vector-tab-noicon mw-list-item"><a href="/w/index.php?title=Talk:API_Gateway&action=edit&redlink=1" rel="discussion" class="new" title="Discussion about the content page (page does not exist) [t]" accesskey="t"><span>Discussion</span></a></li> </ul> </div> </div> <div id="vector-variants-dropdown" class="vector-dropdown emptyPortlet" > <input type="checkbox" id="vector-variants-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-variants-dropdown" class="vector-dropdown-checkbox " aria-label="Change language variant" > <label id="vector-variants-dropdown-label" for="vector-variants-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet" aria-hidden="true" ><span class="vector-dropdown-label-text">English</span> </label> <div class="vector-dropdown-content"> <div id="p-variants" class="vector-menu mw-portlet mw-portlet-variants emptyPortlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> </ul> </div> </div> </div> </div> </nav> </div> <div id="right-navigation" class="vector-collapsible"> <nav aria-label="Views"> <div id="p-views" class="vector-menu vector-menu-tabs mw-portlet mw-portlet-views" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="ca-view" class="selected vector-tab-noicon mw-list-item"><a href="/wiki/API_Gateway"><span>Read</span></a></li><li id="ca-viewsource" class="vector-tab-noicon mw-list-item"><a href="/w/index.php?title=API_Gateway&action=edit" title="This page is protected. You can view its source [e]" accesskey="e"><span>View source</span></a></li><li id="ca-history" class="vector-tab-noicon mw-list-item"><a href="/w/index.php?title=API_Gateway&action=history" title="Past revisions of this page [h]" accesskey="h"><span>View history</span></a></li> </ul> </div> </div> </nav> <nav class="vector-page-tools-landmark" aria-label="Page tools"> <div id="vector-page-tools-dropdown" class="vector-dropdown vector-page-tools-dropdown" > <input type="checkbox" id="vector-page-tools-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-page-tools-dropdown" class="vector-dropdown-checkbox " aria-label="Tools" > <label id="vector-page-tools-dropdown-label" for="vector-page-tools-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet" aria-hidden="true" ><span class="vector-dropdown-label-text">Tools</span> </label> <div class="vector-dropdown-content"> <div id="vector-page-tools-unpinned-container" class="vector-unpinned-container"> <div id="vector-page-tools" class="vector-page-tools vector-pinnable-element"> <div class="vector-pinnable-header vector-page-tools-pinnable-header vector-pinnable-header-unpinned" data-feature-name="page-tools-pinned" data-pinnable-element-id="vector-page-tools" data-pinned-container-id="vector-page-tools-pinned-container" data-unpinned-container-id="vector-page-tools-unpinned-container" > <div class="vector-pinnable-header-label">Tools</div> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.vector-page-tools.pin">move to sidebar</button> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.vector-page-tools.unpin">hide</button> </div> <div id="p-cactions" class="vector-menu mw-portlet mw-portlet-cactions emptyPortlet vector-has-collapsible-items" title="More options" > <div class="vector-menu-heading"> Actions </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="ca-more-view" class="selected vector-more-collapsible-item mw-list-item"><a href="/wiki/API_Gateway"><span>Read</span></a></li><li id="ca-more-viewsource" class="vector-more-collapsible-item mw-list-item"><a href="/w/index.php?title=API_Gateway&action=edit"><span>View source</span></a></li><li id="ca-more-history" class="vector-more-collapsible-item mw-list-item"><a href="/w/index.php?title=API_Gateway&action=history"><span>View history</span></a></li> </ul> </div> </div> <div id="p-tb" class="vector-menu mw-portlet mw-portlet-tb" > <div class="vector-menu-heading"> General </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="t-whatlinkshere" class="mw-list-item"><a href="/wiki/Special:WhatLinksHere/API_Gateway" title="A list of all wiki pages that link here [j]" accesskey="j"><span>What links here</span></a></li><li id="t-recentchangeslinked" class="mw-list-item"><a href="/wiki/Special:RecentChangesLinked/API_Gateway" rel="nofollow" title="Recent changes in pages linked from this page [k]" accesskey="k"><span>Related changes</span></a></li><li id="t-specialpages" class="mw-list-item"><a href="/wiki/Special:SpecialPages" title="A list of all special pages [q]" accesskey="q"><span>Special pages</span></a></li><li id="t-permalink" class="mw-list-item"><a href="/w/index.php?title=API_Gateway&oldid=2232424" title="Permanent link to this revision of this page"><span>Permanent link</span></a></li><li id="t-info" class="mw-list-item"><a href="/w/index.php?title=API_Gateway&action=info" title="More information about this page"><span>Page information</span></a></li><li id="t-cite" class="mw-list-item"><a href="/w/index.php?title=Special:CiteThisPage&page=API_Gateway&id=2232424&wpFormIdentifier=titleform" title="Information on how to cite this page"><span>Cite this page</span></a></li><li id="t-urlshortener" class="mw-list-item"><a href="/w/index.php?title=Special:UrlShortener&url=https%3A%2F%2Fwikitech.wikimedia.org%2Fwiki%2FAPI_Gateway"><span>Get shortened URL</span></a></li><li id="t-urlshortener-qrcode" class="mw-list-item"><a href="/w/index.php?title=Special:QrCode&url=https%3A%2F%2Fwikitech.wikimedia.org%2Fwiki%2FAPI_Gateway"><span>Download QR code</span></a></li> </ul> </div> </div> <div id="p-coll-print_export" class="vector-menu mw-portlet mw-portlet-coll-print_export" > <div class="vector-menu-heading"> Print/export </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="coll-create_a_book" class="mw-list-item"><a href="/w/index.php?title=Special:Book&bookcmd=book_creator&referer=API+Gateway"><span>Create a book</span></a></li><li id="coll-download-as-rl" class="mw-list-item"><a href="/w/index.php?title=Special:DownloadAsPdf&page=API_Gateway&action=show-download-screen"><span>Download as PDF</span></a></li><li id="t-print" class="mw-list-item"><a href="/w/index.php?title=API_Gateway&printable=yes" title="Printable version of this page [p]" accesskey="p"><span>Printable version</span></a></li> </ul> </div> </div> </div> </div> </div> </div> </nav> </div> </div> </div> <div class="vector-column-end"> <div class="vector-sticky-pinned-container"> <nav class="vector-page-tools-landmark" aria-label="Page tools"> <div id="vector-page-tools-pinned-container" class="vector-pinned-container"> </div> </nav> <nav class="vector-appearance-landmark" aria-label="Appearance"> <div id="vector-appearance-pinned-container" class="vector-pinned-container"> <div id="vector-appearance" class="vector-appearance vector-pinnable-element"> <div class="vector-pinnable-header vector-appearance-pinnable-header vector-pinnable-header-pinned" data-feature-name="appearance-pinned" data-pinnable-element-id="vector-appearance" data-pinned-container-id="vector-appearance-pinned-container" data-unpinned-container-id="vector-appearance-unpinned-container" > <div class="vector-pinnable-header-label">Appearance</div> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.vector-appearance.pin">move to sidebar</button> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.vector-appearance.unpin">hide</button> </div> </div> </div> </nav> </div> </div> <div id="bodyContent" class="vector-body" aria-labelledby="firstHeading" data-mw-ve-target-container> <div class="vector-body-before-content"> <div class="mw-indicators"> </div> <div id="siteSub" class="noprint">From Wikitech</div> </div> <div id="contentSub"><div id="mw-content-subtitle"></div></div> <div id="mw-content-text" class="mw-body-content"><div class="mw-content-ltr mw-parser-output" lang="en" dir="ltr"><p>The API Gateway is a service that runs in <a href="/wiki/Kubernetes" title="Kubernetes">Kubernetes</a> based on <a href="/wiki/Envoy" title="Envoy">Envoy</a>. The service implements many features central to serving the unified API and the API portal. </p> <meta property="mw:PageProp/toc"/> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="What_it_does" data-mw-thread-id="h-What_it_does"><span data-mw-comment-start="" id="h-What_it_does"></span>What it does<span data-mw-comment-end="h-What_it_does"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-What_it_does","replies":[]}}--></div> <p>The API Gateway serves pages for <a class="external text" href="https://api.wikimedia.org">api.wikimedia.org</a>. It does this by rewriting requests for the unified API to URIs that are understood by the respective APIs on the application servers, and also by serving pages for the API Portal wiki in the same way other wikis would be served. The API Gateway also uses metadata from <a href="https://en.wikipedia.org/wiki/JSON_Web_Token" class="extiw" title="en:JSON Web Token">JSON Web Tokens</a> (JWTs) to apply rate limits to clients using the APIs. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="How_it_works" data-mw-thread-id="h-How_it_works"><span data-mw-comment-start="" id="h-How_it_works"></span>How it works<span data-mw-comment-end="h-How_it_works"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_it_works","replies":["h-Rate_limiting-How_it_works","h-Routing-How_it_works","h-JSON_Web_Tokens-How_it_works","h-API_Portal-How_it_works","h-Logs_and_analytics-How_it_works"]}}--></div> <figure class="mw-default-size" typeof="mw:File/Thumb"><a href="/wiki/File:Wikimedia-API-Gateway-architecture-v1.png" class="mw-file-description"><img src="//upload.wikimedia.org/wikipedia/commons/thumb/c/cd/Wikimedia-API-Gateway-architecture-v1.png/220px-Wikimedia-API-Gateway-architecture-v1.png" decoding="async" width="220" height="172" class="mw-file-element" srcset="//upload.wikimedia.org/wikipedia/commons/thumb/c/cd/Wikimedia-API-Gateway-architecture-v1.png/330px-Wikimedia-API-Gateway-architecture-v1.png 1.5x, //upload.wikimedia.org/wikipedia/commons/thumb/c/cd/Wikimedia-API-Gateway-architecture-v1.png/440px-Wikimedia-API-Gateway-architecture-v1.png 2x" data-file-width="1129" data-file-height="883"/></a><figcaption>Wikimedia API Gateway architecture diagram</figcaption></figure> <p>Envoy is more or less functioning as any other API router/reverse proxy does. The proxy answers requests for the configured domain, does some selective manipulation and then asks appservers via their LVS endpoint for page content. </p> <div class="mw-heading mw-heading3"><h3 id="Rate_limiting" data-mw-thread-id="h-Rate_limiting-How_it_works"><span data-mw-comment-start="" id="h-Rate_limiting-How_it_works"></span>Rate limiting<span data-mw-comment-end="h-Rate_limiting-How_it_works"></span></h3></div> <p>The API Gateway applies rate limits to clients based upon the JWT provided (or not) by the client. During beta unauthenticated clients are currently limited to 500 requests an hour, and authenticated clients that pass a valid JWT are limited to 5000 requests. These values are entirely temporary and will be changed as the platform moves towards general release. Clients issue JWTs by requesting OAuth 2.0 clients on <a class="external text" href="https://meta.wikimedia.org">Meta</a> and in future, on the <a class="external text" href="https://api.wikimedia.org/">API Portal</a>. </p><p>The API Gateway also supports setting rate limits on a per-domain basis via <a href="https://gerrit.wikimedia.org/r/plugins/gitiles/operations/software/envoyproxy/ratelimiter" class="extiw" title="gerrit:plugins/gitiles/operations/software/envoyproxy/ratelimiter">envoyproxy/ratelimiter</a> and on a per-service basis via <a href="/wiki/DNS/Discovery" title="DNS/Discovery">discovery records</a>, using <a href="https://gerrit.wikimedia.org/r/plugins/gitiles/operations/deployment-charts/%2B/refs/heads/master/charts/api-gateway/values.yaml#97" class="extiw" title="gerrit:plugins/gitiles/operations/deployment-charts/+/refs/heads/master/charts/api-gateway/values.yaml">values.yaml</a>. </p> <div class="mw-heading mw-heading3"><h3 id="Routing" data-mw-thread-id="h-Routing-How_it_works"><span data-mw-comment-start="" id="h-Routing-How_it_works"></span>Routing<span data-mw-comment-end="h-Routing-How_it_works"></span></h3></div> <p>The API Gateway maps API URIs passed to the Gateway's hostname (api.wikimedia.org) to the relevant APIs understood by the application servers. For example, <a class="external free" href="https://api.wikimedia.org/core/v1/wikipedia/en/page/pizza">https://api.wikimedia.org/core/v1/wikipedia/en/page/pizza</a> is mapped to <a class="external free" href="https://en.wikipedia.org/w/rest.php/v1/page/pizza">https://en.wikipedia.org/w/rest.php/v1/page/pizza</a> by the Gateway's <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/charts/api-gateway/values.yaml$83" class="extiw" title="phab:source/operations-deployment-charts/browse/master/charts/api-gateway/values.yaml$83">configuration language</a>. As of September 2020, it is required to use a relatively complex rewriting method using Lua and multiple definitions of URL patterns seen in the values.yaml file, but this will be fixed in Envoy 1.16.0. Currently all APIs that are offered by the API Gateway are also directly accessible via the traditional API routes on their per-service level. </p> <div class="mw-heading mw-heading3"><h3 id="JSON_Web_Tokens" data-mw-thread-id="h-JSON_Web_Tokens-How_it_works"><span data-mw-comment-start="" id="h-JSON_Web_Tokens-How_it_works"></span>JSON Web Tokens<span data-mw-comment-end="h-JSON_Web_Tokens-How_it_works"></span></h3></div> <p>The API Gateway verifies the signatures of JWT Authorisation headers included alongside requests. If a JWT is valid, a different limit is applied. This limit can be configured via the Helm values file per environment (<code>Values.main_app.ratelimiter.default_limit.unit</code> for valid JWTs and <code>Values.main_app.ratelimiter.anon_limit.unit</code> for anonymous users). </p> <div class="mw-heading mw-heading3"><h3 id="API_Portal" data-mw-thread-id="h-API_Portal-How_it_works"><span data-mw-comment-start="" id="h-API_Portal-How_it_works"></span>API Portal<span data-mw-comment-end="h-API_Portal-How_it_works"></span></h3></div> <p>The API Gateway is the means by which all clients access the <a href="/wiki/API_Portal" title="API Portal">API Portal</a>. The API Portal is simply a customised Mediawiki instance and the API Gateway serves requests to it by proxying requests to the appservers. Unlike other wikis however, the API Portal is <i>only</i> accessible via the API Gateway. </p> <div class="mw-heading mw-heading3"><h3 id="Logs_and_analytics" data-mw-thread-id="h-Logs_and_analytics-How_it_works"><span data-mw-comment-start="" id="h-Logs_and_analytics-How_it_works"></span>Logs and analytics<span data-mw-comment-end="h-Logs_and_analytics-How_it_works"></span></h3></div> <p>Logs are shipped from the API Gateway to <a href="/wiki/Event_Platform/EventGate" title="Event Platform/EventGate">EventGate</a> using fluentd. Fluentd runs in its own container, continuously parsing JSON request log output and reposting these logs to Eventgate. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="Where_it_runs" data-mw-thread-id="h-Where_it_runs"><span data-mw-comment-start="" id="h-Where_it_runs"></span>Where it runs<span data-mw-comment-end="h-Where_it_runs"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Where_it_runs","replies":[]}}--></div> <p>The API Gateway runs in <a href="/wiki/Kubernetes" title="Kubernetes">Kubernetes</a> in staging, eqiad and codfw. The instance in staging does not receive external traffic but can be accessed internally at <a rel="nofollow" class="external free" href="https://api-gateway.svc.eqiad.wmnet:8087">https://api-gateway.svc.eqiad.wmnet:8087</a>. Changes should be deployed to staging and tested via curl on this endpoint. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="How_to_design_your_API" data-mw-thread-id="h-How_to_design_your_API"><span data-mw-comment-start="" id="h-How_to_design_your_API"></span>How to design your API<span data-mw-comment-end="h-How_to_design_your_API"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_design_your_API","replies":["h-Before_you_build-How_to_design_your_API","h-Criteria:_URL_structure-How_to_design_your_API","h-Criteria:_Conditional_requests-How_to_design_your_API","h-Next_steps-How_to_design_your_API"]}}--></div> <p>This section is for teams who want to add their API to the API gateway and API Portal. </p> <div class="mw-heading mw-heading3"><h3 id="Before_you_build" data-mw-thread-id="h-Before_you_build-How_to_design_your_API"><span data-mw-comment-start="" id="h-Before_you_build-How_to_design_your_API"></span>Before you build<span data-mw-comment-end="h-Before_you_build-How_to_design_your_API"></span></h3></div> <div class="mw-heading mw-heading4"><h4 id="Style" data-mw-thread-id="h-Style-Before_you_build"><span data-mw-comment-start="" id="h-Style-Before_you_build"></span>Style<span data-mw-comment-end="h-Style-Before_you_build"></span></h4></div> <p>All APIs in the API gateway follow a <a href="https://en.wikipedia.org/wiki/Representational_state_transfer" class="extiw" title="en:Representational state transfer">RESTful</a> architectural style. For general guidance on our interpretation of REST and recommended API best practices, visit the <a href="https://www.mediawiki.org/wiki/Core_Platform_Team/Initiative/Core_REST_API_in_Mediawiki/Design_principles" class="extiw" title="mw:Core Platform Team/Initiative/Core REST API in Mediawiki/Design principles">design principles</a>. </p> <div class="mw-heading mw-heading4"><h4 id="Authentication_and_authorization" data-mw-thread-id="h-Authentication_and_authorization-Before_you_build"><span data-mw-comment-start="" id="h-Authentication_and_authorization-Before_you_build"></span>Authentication and authorization<span data-mw-comment-end="h-Authentication_and_authorization-Before_you_build"></span></h4></div> <p>The API gateway supports <a class="external text" href="https://en.wikipedia.org/wiki/OAuth#OAuth_2.0">OAuth 2.0</a> as the sole method for authentication and authorization. The gateway requires that write requests include an OAuth token, effectively prohibiting writes without a registered consumer. </p><p>At this time, the API Portal supports only the MediaWiki rights covered by the <a href="https://meta.wikimedia.org/wiki/Special:ListGrants#basic" class="extiw" title="metawiki:Special:ListGrants">basic</a>, <a href="https://meta.wikimedia.org/wiki/Special:ListGrants#createeditmovepage" class="extiw" title="metawiki:Special:ListGrants">createeditmovepage</a>, and <a href="https://meta.wikimedia.org/wiki/Special:ListGrants#editprotected" class="extiw" title="metawiki:Special:ListGrants">editprotected</a> grants. To add a grant, open a task in Phabricator tagged with <a href="https://phabricator.wikimedia.org/tag/api-portal/" class="extiw" title="phab:tag/api-portal/">#API-Portal</a>. </p> <div class="mw-heading mw-heading4"><h4 id="Rate_limits" data-mw-thread-id="h-Rate_limits-Before_you_build"><span data-mw-comment-start="" id="h-Rate_limits-Before_you_build"></span>Rate limits<span data-mw-comment-end="h-Rate_limits-Before_you_build"></span></h4></div> <p>Requests to api.wikimedia.org are subject to centrally defined rate limits. Rate limits are based on the type of OAuth 2.0 workflow used by the consumer. Requests without an OAuth 2.0 token are subject to a significantly lower rate limit. Visit the <a class="external text" href="https://api.wikimedia.org/wiki/Documentation/Getting_started/Rate_limits">documentation</a> for specific rate limits. </p> <div class="mw-heading mw-heading3"><h3 id="Criteria:_URL_structure" data-mw-thread-id="h-Criteria:_URL_structure-How_to_design_your_API"><span data-mw-comment-start="" id="h-Criteria:_URL_structure-How_to_design_your_API"></span>Criteria: URL structure<span data-mw-comment-end="h-Criteria:_URL_structure-How_to_design_your_API"></span></h3></div> <p>API gateway endpoints follow a consistent URL structure: </p> <div class="mw-highlight mw-highlight-lang-text mw-content-ltr" dir="ltr"><pre><span></span># Base URL https://api.wikimedia.org # Structure {base URL}/{namespace}/v{version number}/{project name}/{subdomain}/{endpoint} # Example: Get the Earth article from English Wikipedia https://api.wikimedia.org/core/v1/wikipedia/en/page/Earth </pre></div> <div class="mw-heading mw-heading4"><h4 id="Namespace" data-mw-thread-id="h-Namespace-Criteria:_URL_structure"><span data-mw-comment-start="" id="h-Namespace-Criteria:_URL_structure"></span>Namespace<span data-mw-comment-end="h-Namespace-Criteria:_URL_structure"></span></h4></div> <p>Endpoints MUST be grouped under a namespace as the initial URL element after the base URL. The namespace should represent a logical grouping of endpoints by function or origin. For a list of namespaces currently in use, visit the API Portal. </p> <table class="wikitable"> <tbody><tr> <td>This pattern in currently in use but should be reconsidered and/or discontinued per <a href="https://phabricator.wikimedia.org/T280087" class="extiw" title="phab:T280087">phab:T280087</a> </td></tr> <tr> <td>For APIs originating outside of MediaWiki, the namespace may include both the general /service namespace and a service-specific subnamespace (for example: /service/linkrecommendation). For more information about this pattern, see the <a href="#Other_API_routes">other API routes section</a>. </td></tr></tbody></table> <div class="mw-heading mw-heading4"><h4 id="Version" data-mw-thread-id="h-Version-Criteria:_URL_structure"><span data-mw-comment-start="" id="h-Version-Criteria:_URL_structure"></span>Version<span data-mw-comment-end="h-Version-Criteria:_URL_structure"></span></h4></div> <p>Following the namespace, endpoints MUST include a version in the URL. Experimental or unstable APIs MUST use v0. Endpoints using v1 and above MUST follow the <a class="external text" href="https://api.wikimedia.org/wiki/Documentation/Best_practices/Stability_policy">stability policy</a>. </p> <div class="mw-heading mw-heading4"><h4 id="Supported_projects" data-mw-thread-id="h-Supported_projects-Criteria:_URL_structure"><span data-mw-comment-start="" id="h-Supported_projects-Criteria:_URL_structure"></span>Supported projects<span data-mw-comment-end="h-Supported_projects-Criteria:_URL_structure"></span></h4></div> <p>Out of the <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/charts/api-gateway/values.yaml$129" class="extiw" title="phab:source/operations-deployment-charts/browse/master/charts/api-gateway/values.yaml$129">projects supported by the gateway pathing map</a>, endpoints MUST address project routing (Wikipedia, Wiktionary, etc.) through a URL element following the version, using the unabbreviated project name. If your API has limited project support, you MUST document (either in the API Portal, error message, or other location) which projects are supported by your API. </p> <div class="mw-heading mw-heading4"><h4 id="Supported_subdomains" data-mw-thread-id="h-Supported_subdomains-Criteria:_URL_structure"><span data-mw-comment-start="" id="h-Supported_subdomains-Criteria:_URL_structure"></span>Supported subdomains<span data-mw-comment-end="h-Supported_subdomains-Criteria:_URL_structure"></span></h4></div> <p>Endpoints MUST address subdomain routing (en, zh, etc.) per project through a URL element following the project, using the <a class="external text" href="https://api.wikimedia.org/wiki/Special:SiteMatrix">subdomain</a>. These subdomains are usually ISO-standard language codes, but there are <a href="https://meta.wikimedia.org/wiki/Special_language_codes" class="extiw" title="metawiki:Special language codes">exceptions</a>. </p><p>If your API has limited subdomain support, you MUST document (either in the API Portal, error message, or other location) which subdomains are supported for each project (Wikipedia, Wiktionary, etc.). Note that multilingual projects (commons, mediawiki, meta, wikidata, and wikispecies) do not accept a subdomain parameter. </p> <div class="mw-heading mw-heading3"><h3 id="Criteria:_Conditional_requests" data-mw-thread-id="h-Criteria:_Conditional_requests-How_to_design_your_API"><span data-mw-comment-start="" id="h-Criteria:_Conditional_requests-How_to_design_your_API"></span>Criteria: Conditional requests<span data-mw-comment-end="h-Criteria:_Conditional_requests-How_to_design_your_API"></span></h3></div> <p>Your API MUST support <a class="external text" href="https://api.wikimedia.org/wiki/Documentation/Best_practices/Conditional_requests">conditional requests</a> using etag or last-modified headers. </p> <div class="mw-heading mw-heading3"><h3 id="Next_steps" data-mw-thread-id="h-Next_steps-How_to_design_your_API"><span data-mw-comment-start="" id="h-Next_steps-How_to_design_your_API"></span>Next steps<span data-mw-comment-end="h-Next_steps-How_to_design_your_API"></span></h3></div> <ul><li><a class="mw-selflink-fragment" href="#How_to_add_an_API_route">Adding an API to the API gateway</a></li> <li><a href="/wiki/API_Portal#Adding_an_API" title="API Portal">Adding an API to the API Portal</a></li></ul> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="How_it's_configured" data-mw-thread-id="h-How_it's_configured"><span id="How_it.27s_configured"></span><span data-mw-comment-start="" id="h-How_it's_configured"></span>How it's configured<span data-mw-comment-end="h-How_it's_configured"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_it's_configured","replies":["h-Rate_limiting_internals-How_it's_configured","h-How_to_add_an_API_route-How_it's_configured"]}}--></div> <p>The API Gateway uses the reserved port 8087 internally and is registered in <a href="/wiki/Service_ports" class="mw-redirect" title="Service ports">Service ports</a>. </p><p>The core configuration for the API Gateway helm chart is documented in the <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/charts/api-gateway/values.yaml" class="extiw" title="phab:source/operations-deployment-charts/browse/master/charts/api-gateway/values.yaml">default values.yaml</a> file. Note that there are configuration overrides for <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/helmfile.d/services/api-gateway/values-production.yaml" class="extiw" title="phab:source/operations-deployment-charts/browse/master/helmfile.d/services/api-gateway/values-production.yaml">production in general</a>, and also for <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/helmfile.d/services/api-gateway/values-eqiad.yaml" class="extiw" title="phab:source/operations-deployment-charts/browse/master/helmfile.d/services/api-gateway/values-eqiad.yaml">eqiad</a> and <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/helmfile.d/services/api-gateway/values-codfw.yaml" class="extiw" title="phab:source/operations-deployment-charts/browse/master/helmfile.d/services/api-gateway/values-codfw.yaml">codfw</a> specifically (and <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/helmfile.d/services/api-gateway/values-staging.yaml" class="extiw" title="phab:source/operations-deployment-charts/browse/master/helmfile.d/services/api-gateway/values-staging.yaml">staging</a>, which does not serve public requests). </p><p>JWT tokens are verified using the public key of the keypair used to sign OAuth tokens on meta.wikimedia.org. This key has been converted to the <a href="//tools.ietf.org/html/rfc7517" class="extiw" title="rfc:7517">JWKS format</a> required for support using JWTs and is distributed as a secret via puppet. </p> <div class="mw-heading mw-heading3"><h3 id="Rate_limiting_internals" data-mw-thread-id="h-Rate_limiting_internals-How_it's_configured"><span data-mw-comment-start="" id="h-Rate_limiting_internals-How_it's_configured"></span>Rate limiting internals<span data-mw-comment-end="h-Rate_limiting_internals-How_it's_configured"></span></h3></div> <p>A rate limit table entry is based on three factors, which make up what Envoy calls a "descriptor". A descriptor is essentially a key that represents something that should be counted and potentially rate limited. The API gateway considers two different kinds of rate limit - authenticated and unauthenticated requests where authentication is done via JWT tokens. Authenticated requests are keyed by the client ID and user IDs extracted from the JWT itself (via <code>aud</code> and <code>sub</code> respectively). Unauthenticated requests are keyed by the <code>X-Client-IP</code> header, which is passed to the gateway by our <a href="/wiki/Varnish" title="Varnish">Varnish</a> layer. These descriptions are generalisations of the internal logic - see the <a href="https://gerrit.wikimedia.org/r/plugins/gitiles/operations/deployment-charts/%2B/refs/heads/master/charts/api-gateway/templates/_config.yaml" class="extiw" title="gerrit:plugins/gitiles/operations/deployment-charts/+/refs/heads/master/charts/api-gateway/templates/ config.yaml">config.yaml template</a> in the service chart for more specific explanations. </p><p>In addition to the above, if not otherwise specified, all endpoints are rate limited as one bucket. This means that for a rate limit of 100 requests in an hour, doing 99 requests over the course of an hour to one API and then two requests to any other API will result in the client being returned a 429. To avoid this behaviour, a discovery service can specify a custom <code>ratelimit_config</code> to override the existing rate limits and also create a custom bucket for the service itself, separating the rate limits from the global rate limits. </p> <div class="mw-heading mw-heading3"><h3 id="How_to_add_an_API_route" data-mw-thread-id="h-How_to_add_an_API_route-How_it's_configured"><span data-mw-comment-start="" id="h-How_to_add_an_API_route-How_it's_configured"></span>How to add an API route<span data-mw-comment-end="h-How_to_add_an_API_route-How_it's_configured"></span></h3></div> <div class="mw-heading mw-heading4"><h4 id="Appserver_API_routes" data-mw-thread-id="h-Appserver_API_routes-How_to_add_an_API_route"><span data-mw-comment-start="" id="h-Appserver_API_routes-How_to_add_an_API_route"></span>Appserver API routes<span data-mw-comment-end="h-Appserver_API_routes-How_to_add_an_API_route"></span></h4></div> <p>API routes for services running on Mediawiki application servers are defined in the <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/charts/api-gateway/values.yaml$104" class="extiw" title="phab:source/operations-deployment-charts/browse/master/charts/api-gateway/values.yaml$104">values file</a> for the API Gateway chart under the pathing_map. </p> <ul><li>The keys for the dictionary per cluster are the path served on api.wikimedia.org - this line will be interpreted as a regular expression with support for group matching</li> <li>The sub-dictionary keys of <code>path</code> and <code>host</code> are the rewritten path and HTTP Host header used to make the request to the corresponding backend. Any groups matched in the upper API path regex will be substituted in these parameters - see <a href="https://gerrit.wikimedia.org/r/plugins/gitiles/operations/deployment-charts/%2B/refs/heads/master/helmfile.d/services/api-gateway/values.yaml#56" class="extiw" title="gerrit:plugins/gitiles/operations/deployment-charts/+/refs/heads/master/helmfile.d/services/api-gateway/values.yaml">the existing pathing_map</a> for examples.</li></ul> <p>Currently requests are routed to different locations depending on the path requested. </p> <ul><li>All requests under /core/ with the exception of queries ending “description” are routed to appservers.</li> <li>/core/ requests ending in “description” are routed to the mobileapps service for the <a href="https://www.mediawiki.org/wiki/Extension:ShortDescription" class="extiw" title="mw:Extension:ShortDescription">description</a> API.</li> <li>Requests for paths starting with /service/ are routed to service discovery endpoints. This relation is defined in the Helmfile configuration for the gateway.</li></ul> <div class="mw-heading mw-heading4"><h4 id="Other_API_routes" data-mw-thread-id="h-Other_API_routes-How_to_add_an_API_route"><span data-mw-comment-start="" id="h-Other_API_routes-How_to_add_an_API_route"></span>Other API routes<span data-mw-comment-end="h-Other_API_routes-How_to_add_an_API_route"></span></h4></div> <div class="mw-heading mw-heading5"><h5 id="Discovery_services" data-mw-thread-id="h-Discovery_services-Other_API_routes"><span data-mw-comment-start="" id="h-Discovery_services-Other_API_routes"></span>Discovery services<span data-mw-comment-end="h-Discovery_services-Other_API_routes"></span></h5></div> <p>Routing to a custom service is a little more involved than adding an Appserver API route. Currently only services with a <a href="/wiki/DNS/Discovery" title="DNS/Discovery">discovery</a> configuration can be routed to. The host is added to the <code>discovery_endpoints</code> dictionary in configuration by its discovery hostname, a port is specified and endpoint configured. The service will be accessible at <a class="external free" href="https://api.wikimedia.org/services/my_endpoint">https://api.wikimedia.org/services/my_endpoint</a>. See the <a href="https://gerrit.wikimedia.org/r/plugins/gitiles/operations/deployment-charts/%2B/master/helmfile.d/services/api-gateway/values.yaml#47" class="extiw" title="gerrit:plugins/gitiles/operations/deployment-charts/+/master/helmfile.d/services/api-gateway/values.yaml">existing dictionary</a> for pointers. </p> <div class="mw-heading mw-heading4"><h4 id="Versioning" data-mw-thread-id="h-Versioning-How_to_add_an_API_route"><span data-mw-comment-start="" id="h-Versioning-How_to_add_an_API_route"></span>Versioning<span data-mw-comment-end="h-Versioning-How_to_add_an_API_route"></span></h4></div> <p>Unstable APIs that may undergo backwards-incompatible changes should be added to the API Gateway with /v0/ in the path. Stable APIs that can comply with the API Gateway <a class="external text" href="https://api.wikimedia.org/wiki/Documentation/Best_practices/Stability_policy">versioning policy</a> should be added with /v1/ in the path. </p> <div class="mw-heading mw-heading4"><h4 id="Documentation" data-mw-thread-id="h-Documentation-How_to_add_an_API_route"><span data-mw-comment-start="" id="h-Documentation-How_to_add_an_API_route"></span>Documentation<span data-mw-comment-end="h-Documentation-How_to_add_an_API_route"></span></h4></div> <p>To add API routes to the API Portal, see the <a href="/wiki/API_Portal#Adding_an_API" title="API Portal">API Portal page</a>. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="How_to_deploy_changes" data-mw-thread-id="h-How_to_deploy_changes"><span data-mw-comment-start="" id="h-How_to_deploy_changes"></span>How to deploy changes<span data-mw-comment-end="h-How_to_deploy_changes"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_deploy_changes","replies":["h-How_to_roll_back_changes-How_to_deploy_changes"]}}--></div> <p>The API Gateway's configurable components all live within the <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/" class="extiw" title="phab:source/operations-deployment-charts/browse/master/">deployment-charts repository</a>. The components that are of interest are the <a href="https://phabricator.wikimedia.org/source/operations-deployment-charts/browse/master/charts/api-gateway/" class="extiw" title="phab:source/operations-deployment-charts/browse/master/charts/api-gateway/">api-gateway chart itself</a> and the aforementioned helmfile.d configuration for the service. <i>Note: when changing configuration in the API Gateway chart, make sure to bump the version in Chart.yaml. Not bumping this value will lead to your changes not being deployed.</i> </p><p>Changes to the API Gateway chart or configuration files follow a standard code review process. Once you have received a +1 in Gerrit, submitting a +2 will trigger the auto-merge process for the deployment-charts repository. Once the change is merged, <b>always deploy it to staging first</b> and then deploy to the production environments using the <a href="/wiki/Deployments_on_kubernetes#Code_deployment/configuration_changes" class="mw-redirect" title="Deployments on kubernetes">standard deployment process</a>. </p><p>There are currently no specific deployment windows for the API Gateway but if deploying a change ad hoc without PET's knowledge, it is best to both <code>!log</code> liberally and make sure that someone from the team is on hand if you're doing something risky. </p> <div class="mw-heading mw-heading3"><h3 id="How_to_roll_back_changes" data-mw-thread-id="h-How_to_roll_back_changes-How_to_deploy_changes"><span data-mw-comment-start="" id="h-How_to_roll_back_changes-How_to_deploy_changes"></span>How to roll back changes<span data-mw-comment-end="h-How_to_roll_back_changes-How_to_deploy_changes"></span></h3></div> <p>Follow the <a href="/wiki/Deployments_on_kubernetes#Rolling_back_changes" class="mw-redirect" title="Deployments on kubernetes">standard rollback procedures.</a> If a change is affecting user experience in any way (increases in error codes served, timeouts etc - always refer to the dashboards when deploying), use the emergency procedure to limit the public impact of a change. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="How_to_test_changes" data-mw-thread-id="h-How_to_test_changes"><span data-mw-comment-start="" id="h-How_to_test_changes"></span>How to test changes<span data-mw-comment-end="h-How_to_test_changes"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_test_changes","replies":["h-In_development-How_to_test_changes","h-In_staging-How_to_test_changes"]}}--></div> <div class="mw-heading mw-heading3"><h3 id="In_development" data-mw-thread-id="h-In_development-How_to_test_changes"><span data-mw-comment-start="" id="h-In_development-How_to_test_changes"></span>In development<span data-mw-comment-end="h-In_development-How_to_test_changes"></span></h3></div> <p>Given the API Gateway's interactions with the appservers, testing changes locally can be difficult. However, there exists limited support for testing changes - if you have a local setup like <a rel="nofollow" class="external text" href="https://kubernetes.io/docs/setup/learning-environment/minikube/">minikube</a> or similar, you can install a local version of the API Gateway by running <code>helm install -f api-gateway/values-devel.yaml api-gateway</code> in the <code>charts</code> directory. Once your install is complete and you have forwarded the requisite ports, requests will be passed to a fake backend service that will return the headers and parameters of requests and responses to any requests. This can be used to ensure that basic behaviour changes are in keeping with what you're expecting, that Envoy syntax checks out and that URL mappings are behaving as expected, amongst other things. </p> <div class="mw-heading mw-heading3"><h3 id="In_staging" data-mw-thread-id="h-In_staging-How_to_test_changes"><span data-mw-comment-start="" id="h-In_staging-How_to_test_changes"></span>In staging<span data-mw-comment-end="h-In_staging-How_to_test_changes"></span></h3></div> <p>When changes have been deployed to staging, they can be tested using curl from any internal host. This can make it difficult to test changes that rely on Mediawiki changes, but it is unlikely that helm will be used to change the API Portal's behaviour in lieu of the standard mediawiki-config deployment process. </p><p>For example, to test a change to the API routing, run <code>curl -k https://staging.svc.eqiad.wmnet:8087/core/v1/wikipedia/ga/page/Veigeat%C3%B3ireachas -v</code>. When deploying new changes to staging, it should be verified that the change has had no impact on the API in general and specifically any API paths that have been modified or added. The normal operation of the API Portal should be tested - nothing too extensive but make sure that the <a class="external text" href="https://api.wikimedia.org/wiki/Main_Page">main page</a> loads okay. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="How_to_debug_it" data-mw-thread-id="h-How_to_debug_it"><span data-mw-comment-start="" id="h-How_to_debug_it"></span>How to debug it<span data-mw-comment-end="h-How_to_debug_it"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_debug_it","replies":["h-Logs-How_to_debug_it","h-WikimediaDebug-How_to_debug_it"]}}--></div> <div class="mw-heading mw-heading3"><h3 id="Logs" data-mw-thread-id="h-Logs-How_to_debug_it"><span data-mw-comment-start="" id="h-Logs-How_to_debug_it"></span>Logs<span data-mw-comment-end="h-Logs-How_to_debug_it"></span></h3></div> <div class="mw-heading mw-heading4"><h4 id="Logstash" data-mw-thread-id="h-Logstash-Logs"><span data-mw-comment-start="" id="h-Logstash-Logs"></span>Logstash<span data-mw-comment-end="h-Logstash-Logs"></span></h4></div> <p>The easiest way to look at logs for the API gateway is via <a href="/wiki/Logstash" title="Logstash">Logstash</a> - simply filter for the <code>kubernetes.namespace_name</code> attribute of <code>api-gateway</code> or view the <a class="external text" href="https://logstash.wikimedia.org/app/dashboards#/view/AXO_Z8ZNNoG2jwpwm2vv?_g=h@03cd538&_a=h@65dbc91">api-gateway</a> dashboard. </p> <div class="mw-heading mw-heading4"><h4 id="Kubernetes" data-mw-thread-id="h-Kubernetes-Logs"><span data-mw-comment-start="" id="h-Kubernetes-Logs"></span>Kubernetes<span data-mw-comment-end="h-Kubernetes-Logs"></span></h4></div> <p>To read and follow the logs for a API Gateway instance (useful if you want to debug a specific instance while logged into the deploy server but usually more hassle than using Logstash directly) (codfw in this example): </p> <pre>hnowlan@deploy1001:~$ kube_env "api-gateway" "codfw" hnowlan@deploy1001:~$ kubectl get pods | grep Running api-gateway-production-5cd8c54ddb-rcg77 5/5 Running 0 5d5h tiller-deploy-77f47486d6-fxhpx 1/1 Running 0 6d3h nowlan@deploy1001:~$ kubectl logs api-gateway-production-5cd8c54ddb-rcg77 api-gateway-production --tail 10 -f </pre><p>This will show the last 10 lines of the logs and then follow output. </p><p>Note that Envoy's log format is extremely verbose and dumping whole logs may take a few seconds. Following logs may be challenging at times as they can seem non-linear as many requests may be interpolated amongst each one another - one aid in sorting through logs is following the [Cxxxxx] fields in the logs which are unique connection IDs that can be used to follow requests as they are received and answered. </p><p>The above example can also be used to monitor the ratelimit service - in place of <code>api-gateway-production</code> simply subsitute <code>production-ratelimit</code>. This pattern applies to the other services within the pod but their log output is not always useful. </p> <div class="mw-heading mw-heading3"><h3 id="WikimediaDebug" data-mw-thread-id="h-WikimediaDebug-How_to_debug_it"><span data-mw-comment-start="" id="h-WikimediaDebug-How_to_debug_it"></span>WikimediaDebug<span data-mw-comment-end="h-WikimediaDebug-How_to_debug_it"></span></h3></div> <p>The <a href="/wiki/WikimediaDebug" title="WikimediaDebug">WikimediaDebug</a> plugin is supported for accessing the API Portal. It is not currently supported for routing API requests. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="How_to_monitor_it" data-mw-thread-id="h-How_to_monitor_it"><span data-mw-comment-start="" id="h-How_to_monitor_it"></span>How to monitor it<span data-mw-comment-end="h-How_to_monitor_it"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_monitor_it","replies":[]}}--></div> <p>There is a <a class="external text" href="https://grafana.wikimedia.org/d/UOH-5IDMz/api-gateway?">Grafana dashboard available</a> that monitors many features of the API Gateway. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="How_to_assign_a_client_to_rate_limit_tier" data-mw-thread-id="h-How_to_assign_a_client_to_rate_limit_tier"><span data-mw-comment-start="" id="h-How_to_assign_a_client_to_rate_limit_tier"></span>How to assign a client to rate limit tier<span data-mw-comment-end="h-How_to_assign_a_client_to_rate_limit_tier"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_assign_a_client_to_rate_limit_tier","replies":[]}}--></div> <p>All clients are assigned to the default ratelimit tier. To change the tier, use the <code>setClientTierName.php</code> maintenance script. </p><p>Log in to the mwmaint host in the active datacenter, usually <a href="/wiki/Mwmaint1002" class="mw-redirect" title="Mwmaint1002">mwmaint1002</a>, and execute: </p> <div class="mw-highlight mw-highlight-lang-bash mw-content-ltr" dir="ltr"><pre><span></span>mwscript<span class="w"> </span>extensions/OAuthRateLimiter/maintenance/setClientTierName.php<span class="w"> </span>--wiki<span class="w"> </span>metawiki<span class="w"> </span>--client<span class="w"> </span><client_id><span class="w"> </span>--tier<span class="w"> </span><tier_name> </pre></div><p>At the time of writing 3 tiers exist: </p><ul><li><b>Default</b> rate limit class: 5000 API calls/hour per client ID/user ID pair (with null user ID counting as a pair here)</li> <li><b>Preferred</b> rate limit class: 25,000 API calls/hour per client ID/user ID pair</li> <li><b>Internal</b> rate limit class: 100,000 API calls/hour per client ID/user ID pair</li> <li><b>WME</b> rate limit class: 250,000 API calls/hour per client ID/user ID pair (this is only to be used for Wikimedia Enterprise tokens)</li></ul> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="Known_issues" data-mw-thread-id="h-Known_issues"><span data-mw-comment-start="" id="h-Known_issues"></span>Known issues<span data-mw-comment-end="h-Known_issues"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Known_issues","replies":[]}}--></div> <ul><li>If a user receives an error of <code>{"httpCode":401,"httpReason":"Jwt issuer is not configured"}</code> it is because the "iss" field in the token does not match the one configured on the API Gateway. Depending on what has been changed this could be a misconfiguration of the OAuth token creation process or of the Gateway itself. Envoy is very strict about issuer being set (<a rel="nofollow" class="external text" href="https://github.com/envoyproxy/envoy/pull/12744">although this is changing</a>) and a mismatch will lead to tokens being rejected.</li></ul> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="Related" data-mw-thread-id="h-Related"><span data-mw-comment-start="" id="h-Related"></span>Related<span data-mw-comment-end="h-Related"></span></h2><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Related","replies":[]}}--></div> <ul><li><a href="https://www.mediawiki.org/wiki/Core_Platform_Team/Initiatives/API_Gateway" class="extiw" title="mw:Core Platform Team/Initiatives/API Gateway">The initiative documentation for the API Gateway's initial design</a></li></ul> <!-- NewPP limit report Parsed by mw‐web.codfw.main‐74dc4d995d‐4s4hm Cached time: 20241102235421 Cache expiry: 2592000 Reduced expiry: false Complications: [show‐toc] DiscussionTools time usage: 0.015 seconds CPU time usage: 0.050 seconds Real time usage: 0.197 seconds Preprocessor visited node count: 191/1000000 Post‐expand include size: 0/2097152 bytes Template argument size: 0/2097152 bytes Highest expansion depth: 2/100 Expensive parser function count: 2/500 Unstrip recursion depth: 0/20 Unstrip post‐expand size: 1336/5000000 bytes --> <!-- Transclusion expansion time report (%,ms,calls,template) 100.00% 0.000 1 -total --> <!-- Saved in parser cache with key labswiki:pcache:idhash:446572-0!canonical and timestamp 20241102235421 and revision id 2232424. Rendering was triggered because: page-view --> </div><!--esi <esi:include src="/esitest-fa8a495983347898/content" /> --><noscript><img src="https://login.wikimedia.org/wiki/Special:CentralAutoLogin/start?type=1x1" alt="" width="1" height="1" style="border: none; position: absolute;"></noscript> <div class="printfooter" data-nosnippet="">Retrieved from "<a dir="ltr" href="https://wikitech.wikimedia.org/w/index.php?title=API_Gateway&oldid=2232424">https://wikitech.wikimedia.org/w/index.php?title=API_Gateway&oldid=2232424</a>"</div></div> <div id="catlinks" class="catlinks" data-mw="interface"><div id="mw-normal-catlinks" class="mw-normal-catlinks"><a href="/wiki/Special:Categories" title="Special:Categories">Category</a>: <ul><li><a href="/wiki/Category:Services" title="Category:Services">Services</a></li></ul></div></div> </div> </main> </div> <div class="mw-footer-container"> <footer id="footer" class="mw-footer" > <ul id="footer-info"> <li id="footer-info-lastmod"> This page was last edited on 3 October 2024, at 12:17.</li> <li id="footer-info-copyright">Text is available under the <a rel="nofollow" class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">Creative Commons Attribution-ShareAlike License</a>; additional terms may apply. See <a class="external text" href="https://foundation.wikimedia.org/wiki/Special:MyLanguage/Policy:Terms_of_Use">Terms of Use</a> for details.</li> </ul> <ul id="footer-places"> <li id="footer-places-privacy"><a href="https://foundation.wikimedia.org/wiki/Special:MyLanguage/Policy:Privacy_policy">Privacy policy</a></li> <li id="footer-places-about"><a href="/wiki/Main_Page">About Wikitech</a></li> <li id="footer-places-disclaimers"><a href="https://foundation.wikimedia.org/wiki/General_disclaimer">Disclaimers</a></li> <li id="footer-places-wm-codeofconduct"><a href="https://www.mediawiki.org/wiki/Special:MyLanguage/Code_of_Conduct">Code of Conduct</a></li> <li id="footer-places-developers"><a href="https://developer.wikimedia.org">Developers</a></li> <li id="footer-places-statslink"><a href="https://stats.wikimedia.org/#/wikitech.wikimedia.org">Statistics</a></li> <li id="footer-places-cookiestatement"><a href="https://foundation.wikimedia.org/wiki/Special:MyLanguage/Policy:Cookie_statement">Cookie statement</a></li> <li id="footer-places-mobileview"><a href="//wikitech.wikimedia.org/w/index.php?title=API_Gateway&mobileaction=toggle_view_mobile" class="noprint stopMobileRedirectToggle">Mobile view</a></li> </ul> <ul id="footer-icons" class="noprint"> <li id="footer-copyrightico"><a href="https://wikimediafoundation.org/" class="cdx-button cdx-button--fake-button cdx-button--size-large cdx-button--fake-button--enabled"><img src="/static/images/footer/wikimedia-button.svg" width="84" height="29" alt="Wikimedia Foundation" loading="lazy"></a></li> <li id="footer-poweredbyico"><a href="https://www.mediawiki.org/" class="cdx-button cdx-button--fake-button cdx-button--size-large cdx-button--fake-button--enabled"><img src="/w/resources/assets/poweredby_mediawiki.svg" alt="Powered by MediaWiki" width="88" height="31" loading="lazy"></a></li> </ul> </footer> </div> </div> </div> <div class="vector-settings" id="p-dock-bottom"> <ul></ul> </div><script>(RLQ=window.RLQ||[]).push(function(){mw.config.set({"wgHostname":"mw-web.codfw.main-5cd4cd96d5-wwhrx","wgBackendResponseTime":88,"wgDiscussionToolsPageThreads":[{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-What_it_does","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_it_works","replies":[{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Rate_limiting-How_it_works","replies":[]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Routing-How_it_works","replies":[]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-JSON_Web_Tokens-How_it_works","replies":[]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-API_Portal-How_it_works","replies":[]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Logs_and_analytics-How_it_works","replies":[]}]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Where_it_runs","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_design_your_API","replies":[{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Before_you_build-How_to_design_your_API","replies":[{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Style-Before_you_build","replies":[]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Authentication_and_authorization-Before_you_build","replies":[]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Rate_limits-Before_you_build","replies":[]}]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Criteria:_URL_structure-How_to_design_your_API","replies":[{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Namespace-Criteria:_URL_structure","replies":[]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Version-Criteria:_URL_structure","replies":[]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Supported_projects-Criteria:_URL_structure","replies":[]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Supported_subdomains-Criteria:_URL_structure","replies":[]}]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Criteria:_Conditional_requests-How_to_design_your_API","replies":[]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Next_steps-How_to_design_your_API","replies":[]}]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_it's_configured","replies":[{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Rate_limiting_internals-How_it's_configured","replies":[]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-How_to_add_an_API_route-How_it's_configured","replies":[{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Appserver_API_routes-How_to_add_an_API_route","replies":[]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Other_API_routes-How_to_add_an_API_route","replies":[{"headingLevel":5,"name":"h-","type":"heading","level":0,"id":"h-Discovery_services-Other_API_routes","replies":[]}]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Versioning-How_to_add_an_API_route","replies":[]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Documentation-How_to_add_an_API_route","replies":[]}]}]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_deploy_changes","replies":[{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-How_to_roll_back_changes-How_to_deploy_changes","replies":[]}]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_test_changes","replies":[{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-In_development-How_to_test_changes","replies":[]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-In_staging-How_to_test_changes","replies":[]}]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_debug_it","replies":[{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-Logs-How_to_debug_it","replies":[{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Logstash-Logs","replies":[]},{"headingLevel":4,"name":"h-","type":"heading","level":0,"id":"h-Kubernetes-Logs","replies":[]}]},{"headingLevel":3,"name":"h-","type":"heading","level":0,"id":"h-WikimediaDebug-How_to_debug_it","replies":[]}]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_monitor_it","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-How_to_assign_a_client_to_rate_limit_tier","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Known_issues","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Related","replies":[]}],"wgPageParseReport":{"discussiontools":{"limitreport-timeusage":"0.015"},"limitreport":{"cputime":"0.050","walltime":"0.197","ppvisitednodes":{"value":191,"limit":1000000},"postexpandincludesize":{"value":0,"limit":2097152},"templateargumentsize":{"value":0,"limit":2097152},"expansiondepth":{"value":2,"limit":100},"expensivefunctioncount":{"value":2,"limit":500},"unstrip-depth":{"value":0,"limit":20},"unstrip-size":{"value":1336,"limit":5000000},"timingprofile":["100.00% 0.000 1 -total"]},"cachereport":{"origin":"mw-web.codfw.main-74dc4d995d-4s4hm","timestamp":"20241102235421","ttl":2592000,"transientcontent":false}}});});</script> </body> </html>