Page MenuHomePhabricator

[SPIKE] Determine the most heavily installed and used extensions across Wikimedia installations with REST endpoints
Closed, ResolvedPublic3 Estimated Story Points

Description

Description

This quarter, we are experimenting with creating MW REST API modules for installed extensions. To inform the migration priority, we need to better understand which extensions are used most commonly and heavily across Wikimedia hosted projects.

Conditions of acceptance

  • Audit MediaWiki extensions that expose MW REST API endpoints to uncover:
    • How many Wikimedia hosted wikis they are installed and active on
    • Usage/traffic measurement. This can be as simple as the total traffic to the base route, traffic per endpoint, or other ideas that may act as a better proxy for utilization.
    • If there is any nuance or potential blockers for API module creation.
  • Create a document that reflects this information and can be shared with the team.
  • For the extensions, review and update (if necessary) proposed ownership in the API Maintainer's list: https://docs.google.com/spreadsheets/d/1-fcgVYgM0elpTizqN93VEsBINgcs88Gp_6Kw-wrczIs/edit?gid=0#gid=0
  • Finalize priority order for team-specific follow ups and module creation with Halley.

Implementation details

The following extension APIs are currently surfaced in the test wiki and are considered in scope/prioritized for API module creation. This is a non-exhaustive list, and additional extensions may be surfaced based on other wiki configurations.

  • math
  • securepoll
  • oAuth
  • reportincident
  • checkuser
  • ipinfo
  • eventbus
  • growthexperiments
  • wikifunctions
  • campaignevents
  • wikimediacampaignevents

Event Timeline

aaron triaged this task as Medium priority.Jan 13 2026, 9:15 PM

Here's some raw data to get started (this can go in sorted google doc spreadsheet or something):

Module traffic:

sum (
  rate(mediawiki_rest_api_latency_seconds_count{path=~"<MODULE_PREFIX>_.+"}[7d])
) * 3600

module                          reqs/hour (last 7 days @ 2026-01-16 22:29:19)
/campaignevents/v0/             3775.3515997123045
/checkuser/v0/                  10562.12175650855
/eventbus/v0/                   0
/flaggedrevs/                   309.7060776469798
/growthexperiments/v0/          1069.3577700144103
/ipinfo/v0/                     135.9644734510599
/math/v0/                       61.43430874574075
/oauth2/                        537.1668295860337
/reportincident/v0/             0.09524680026660708
/searchvue/v0/                  840.1684037739666
/securepoll/                    0
/wikibase/v1/                   72317.66208653011
/wikibase/v0/                   1686.9341311436897
/wikifunctions/v0/              11.828398418060486
/wikimediacampaignevents/v0/    0
/wikistories/v0/                11.46530718708287

Wikis with the parent extension of modules enabled

module                          # of wikis
/campaignevents/v0/             18
/checkuser/v0/                  (all))
/eventbus/v0/                   (all)
/flaggedrevs/                   48
/growthexperiments/v0/          316
/ipinfo/v0/                     (all)
/math/v0/                       (all but 2)
/oauth2/                        1
/reportincident/v0/             3
/searchvue/v0/                  9
/securepoll/                    (all but 2)
/wikibase/v1/                   4 (repo mode, which has the endpoints); 953 (client mode)
/wikibase/v0/                   4 (repo mode, which has the endpoints); 953 (client mode)
/wikifunctions/v0/              1 (repo mode, which has the endpoints); 163 (client mode)
/wikimediacampaignevents/v0/    18
/wikistories/v0/                1

Endpoints per module:

aaron@aaron-Aspire-S5-371T:~/PhpstormProjects/mediawiki/extensions$ ./grep-wmf --include \*.json --exclude openapi.json '"path": "/' | grep -oP '(?<=")/[^"/]+/(v\d+/)?' | uniq -c
     19 /campaignevents/v0/
      6 /checkuser/v0/
      1 /eventbus/v0/
      2 /flaggedrevs/
      9 /growthexperiments/v0/
      4 /ipinfo/v0/
      1 /math/v0/
     12 /oauth2/
      1 /reportincident/v0/
      2 /searchvue/v0/
      1 /securepoll/
     61 /wikibase/v1/
      4 /wikibase/v0/
      4 /wikifunctions/v0/
      3 /wikimediacampaignevents/v0/
      1 /wikistories/v0/

REST endpoints from WMF-enabled extensions:

aaron@aaron-Aspire-S5-371T:~/PhpstormProjects/mediawiki/extensions$ ./grep-wmf --include \*.json --exclude openapi.json '"path": "/'
CampaignEvents:
521:                    "path": "/campaignevents/v0/event_registration",
538:                    "path": "/campaignevents/v0/event_registration/{id}",
547:                    "path": "/campaignevents/v0/event_registration/{id}",
556:                    "path": "/campaignevents/v0/event_registration/{id}/participants/self",
568:                    "path": "/campaignevents/v0/event_registration/{id}/participants/self",
577:                    "path": "/campaignevents/v0/event_registration/{id}/participants/self",
588:                    "path": "/campaignevents/v0/event_registration/{id}",
606:                    "path": "/campaignevents/v0/event_registration/{id}/organizers",
618:                    "path": "/campaignevents/v0/event_registration/{id}/organizers",
627:                    "path": "/campaignevents/v0/event_registration/{id}/participants",
643:                    "path": "/campaignevents/v0/organizer/{userid}/event_registrations",
652:                    "path": "/campaignevents/v0/participant/{userid}/event_registrations",
661:                    "path": "/campaignevents/v0/participant/self/events_for_edit",
670:                    "path": "/campaignevents/v0/event_registration/{id}/participants",
679:                    "path": "/campaignevents/v0/event_registration/{id}/email",
690:                    "path": "/campaignevents/v0/participant_questions",
700:                    "path": "/campaignevents/v0/formatted_time/{languageCode}/{start}/{end}",
709:                    "path": "/campaignevents/v0/event_registration/{id}/edits/{wiki}/{revid}",
719:                    "path": "/campaignevents/v0/event_contributions/{id}",
CheckUser:
284:                    "path": "/checkuser/v0/suggestedinvestigations/case/{caseId}/update",
295:                    "path": "/checkuser/v0/userinfo",
304:                    "path": "/checkuser/v0/temporaryaccount/{name}",
322:                    "path": "/checkuser/v0/temporaryaccount/ip/{ip}",
340:                    "path": "/checkuser/v0/batch-temporaryaccount",
361:                    "path": "/checkuser/v0/useragent-clienthints/{type}/{id}",
EventBus:
123:                    "path": "/eventbus/v0/internal/job/execute",
FlaggedRevs:
72:                     "path": "/flaggedrevs/internal/diffheader/{oldId}/{newId}",
77:                     "path": "/flaggedrevs/internal/review/{target}",
GrowthExperiments:
279:                    "path": "/growthexperiments/v0/quickstarttips/{skin}/{editor}/{tasktypeid}/{uselang}",
288:                    "path": "/growthexperiments/v0/suggestions/addlink/{title}",
296:                    "path": "/growthexperiments/v0/suggestions/addimage/feedback/{title}",
307:                    "path": "/growthexperiments/v0/suggestions/info",
317:                    "path": "/growthexperiments/v0/mentees",
330:                    "path": "/growthexperiments/v0/mentees/prefixsearch/{prefix}",
338:                    "path": "/growthexperiments/v0/newcomertask/complete",
346:                    "path": "/growthexperiments/v0/welcomesurvey/skip",
354:                    "path": "/growthexperiments/v0/user-impact/{user}",
IPInfo:
77:                     "path": "/ipinfo/v0/revision/{id}",
95:                     "path": "/ipinfo/v0/archivedrevision/{id}",
113:                    "path": "/ipinfo/v0/norevision/{username}",
131:                    "path": "/ipinfo/v0/log/{id}",
Math:
3:              "path": "/math/v0/popup/html/{qid}",
OAuth:
3:              "path": "/oauth2/authorize",
7:              "path": "/oauth2/access_token",
12:             "path": "/oauth2/resource/{{type}}",
16:             "path": "/oauth2/client",
21:             "path": "/oauth2/client/{client_key}/reset_secret",
26:             "path": "/oauth2/client",
291:                    "path": "/oauth2/authorize",
295:                    "path": "/oauth2/access_token",
300:                    "path": "/oauth2/resource/{type}",
304:                    "path": "/oauth2/client",
309:                    "path": "/oauth2/client/{client_key}/reset_secret",
314:                    "path": "/oauth2/client",
ReportIncident:
346:                    "path": "/reportincident/v0/report",
SearchVue:
166:                    "path": "/searchvue/v0/page/{page_title}/{snippet_field}",
171:                    "path": "/searchvue/v0/media/{qid}",
SecurePoll:
55:                     "path": "/securepoll/set_translation/{entityid}/{language}",
Wikibase:
340:                    "path": "/wikibase/v1/entities/items/{item_id}",
345:                    "path": "/wikibase/v1/entities/items",
350:                    "path": "/wikibase/v1/entities/items/{item_id}",
355:                    "path": "/wikibase/v1/entities/properties/{property_id}",
360:                    "path": "/wikibase/v1/entities/properties",
365:                    "path": "/wikibase/v1/entities/properties/{property_id}",
370:                    "path": "/wikibase/v1/entities/items/{item_id}/statements",
375:                    "path": "/wikibase/v1/entities/properties/{property_id}/statements",
380:                    "path": "/wikibase/v1/statements/{statement_id}",
385:                    "path": "/wikibase/v1/entities/items/{item_id}/statements/{statement_id}",
390:                    "path": "/wikibase/v1/entities/properties/{property_id}/statements/{statement_id}",
395:                    "path": "/wikibase/v1/entities/items/{item_id}/statements",
400:                    "path": "/wikibase/v1/entities/properties/{property_id}/statements",
405:                    "path": "/wikibase/v1/statements/{statement_id}",
410:                    "path": "/wikibase/v1/entities/items/{item_id}/statements/{statement_id}",
415:                    "path": "/wikibase/v1/entities/properties/{property_id}/statements/{statement_id}",
420:                    "path": "/wikibase/v1/statements/{statement_id}",
425:                    "path": "/wikibase/v1/entities/items/{item_id}/statements/{statement_id}",
430:                    "path": "/wikibase/v1/entities/properties/{property_id}/statements/{statement_id}",
435:                    "path": "/wikibase/v1/statements/{statement_id}",
440:                    "path": "/wikibase/v1/entities/items/{item_id}/statements/{statement_id}",
445:                    "path": "/wikibase/v1/entities/properties/{property_id}/statements/{statement_id}",
450:                    "path": "/wikibase/v1/entities/items/{item_id}/labels",
455:                    "path": "/wikibase/v1/entities/properties/{property_id}/labels",
460:                    "path": "/wikibase/v1/entities/items/{item_id}/labels/{language_code}",
465:                    "path": "/wikibase/v1/entities/items/{item_id}/labels_with_language_fallback/{language_code}",
470:                    "path": "/wikibase/v1/entities/properties/{property_id}/labels/{language_code}",
475:                    "path": "/wikibase/v1/entities/properties/{property_id}/labels_with_language_fallback/{language_code}",
480:                    "path": "/wikibase/v1/entities/items/{item_id}/labels/{language_code}",
485:                    "path": "/wikibase/v1/entities/properties/{property_id}/labels/{language_code}",
490:                    "path": "/wikibase/v1/entities/items/{item_id}/labels",
495:                    "path": "/wikibase/v1/entities/properties/{property_id}/labels",
500:                    "path": "/wikibase/v1/entities/items/{item_id}/labels/{language_code}",
505:                    "path": "/wikibase/v1/entities/properties/{property_id}/labels/{language_code}",
510:                    "path": "/wikibase/v1/entities/items/{item_id}/descriptions",
515:                    "path": "/wikibase/v1/entities/items/{item_id}/descriptions",
520:                    "path": "/wikibase/v1/entities/properties/{property_id}/descriptions",
525:                    "path": "/wikibase/v1/entities/items/{item_id}/descriptions/{language_code}",
530:                    "path": "/wikibase/v1/entities/items/{item_id}/descriptions_with_language_fallback/{language_code}",
535:                    "path": "/wikibase/v1/entities/properties/{property_id}/descriptions/{language_code}",
540:                    "path": "/wikibase/v1/entities/properties/{property_id}/descriptions_with_language_fallback/{language_code}",
545:                    "path": "/wikibase/v1/entities/items/{item_id}/descriptions/{language_code}",
550:                    "path": "/wikibase/v1/entities/properties/{property_id}/descriptions/{language_code}",
555:                    "path": "/wikibase/v1/entities/items/{item_id}/descriptions/{language_code}",
560:                    "path": "/wikibase/v1/entities/properties/{property_id}/descriptions/{language_code}",
565:                    "path": "/wikibase/v1/entities/items/{item_id}/aliases",
570:                    "path": "/wikibase/v1/entities/properties/{property_id}/descriptions",
575:                    "path": "/wikibase/v1/entities/properties/{property_id}/aliases",
580:                    "path": "/wikibase/v1/entities/items/{item_id}/aliases",
585:                    "path": "/wikibase/v1/entities/properties/{property_id}/aliases",
590:                    "path": "/wikibase/v1/entities/items/{item_id}/aliases/{language_code}",
595:                    "path": "/wikibase/v1/entities/properties/{property_id}/aliases/{language_code}",
600:                    "path": "/wikibase/v1/entities/items/{item_id}/aliases/{language_code}",
605:                    "path": "/wikibase/v1/entities/properties/{property_id}/aliases/{language_code}",
610:                    "path": "/wikibase/v1/entities/items/{item_id}/sitelinks",
615:                    "path": "/wikibase/v1/entities/items/{item_id}/sitelinks",
620:                    "path": "/wikibase/v1/entities/items/{item_id}/sitelinks/{site_id}",
625:                    "path": "/wikibase/v1/entities/items/{item_id}/sitelinks/{site_id}",
630:                    "path": "/wikibase/v1/entities/items/{item_id}/sitelinks/{site_id}",
635:                    "path": "/wikibase/v1/openapi.json",
640:                    "path": "/wikibase/v1/property-data-types",
645:                    "path": "/wikibase/v0/search/items",
650:                    "path": "/wikibase/v0/search/properties",
655:                    "path": "/wikibase/v0/suggest/items",
660:                    "path": "/wikibase/v0/suggest/properties",
WikiLambda:
1003:                   "path": "/wikifunctions/v0/fetch/{zids}",
1008:                   "path": "/wikifunctions/v0/fetch/{zids}/{revisions}",
1013:                   "path": "/wikifunctions/v0/call/{zid}/{arguments}",
1021:                   "path": "/wikifunctions/v0/call/{zid}/{arguments}/{parselang}/{renderlang}",
WikimediaCampaignEvents:
106:                    "path": "/wikimediacampaignevents/v0/event_registration/{id}/grant_id",
117:                    "path": "/wikimediacampaignevents/v0/event_registration/{id}/grant_id",
127:                    "path": "/wikimediacampaignevents/v0/event_registration/{id}/grant_id",
Wikistories:
460:                    "path": "/wikistories/v0/page/{title}/stories",
aaron set the point value for this task to 3.Fri, Jan 23, 12:37 AM
aaron renamed this task from [SPIKE] Determine the most heavily installed and used extensions across Wikimedia installations to [SPIKE] Determine the most heavily installed and used extensions across Wikimedia installations with REST endpoints.Mon, Jan 26, 7:40 PM

I added a few missing endpoints to the maintainer sheet. I also copied current maintainers to the usage sheet.

So I suggest an implementation order of:

  1. /growthexperiments/v0/
  2. /searchvue/v0/
  3. /wikibase/v0/
  4. /wikibase/v1/
  5. /ipinfo/v0/
  6. /checkuser/v0/
  7. /wikistories/v0/
  8. /wikifunctions/v0/
  9. /reportincident/v0/
  10. /campaignevents/v0/
  11. /wikimediacampaignevents/v0/

...then some of the trickier ones can be done, where we might need to add versioning, think more about /internal, or would have a module defined across two different files:

  • /math/v0/
  • /eventbus/v0/
  • /flaggedrevs/
  • /securepoll/
  • /oauth2/ (some of these paths might be constrained by OAuth specs)

Thanks, @aaron ! This is very helpful and I've already used the sheet in a few settings. We can consider this work done for now; we will carry forward the maintainer conversations outside of this ticket.

I don't have edit access, but a proposed owner for /flaggedrevs/ might be the moderator team?

Thanks, @aaron ! This is very helpful and I've already used the sheet in a few settings. We can consider this work done for now; we will carry forward the maintainer conversations outside of this ticket.

I don't have edit access, but a proposed owner for /flaggedrevs/ might be the moderator team?

I updated the access. I suggested the Moderator team for flaggedrevs on the REST API maintainer sheet, it seemed like the best choice to me too.