---
title: How to Replace WordPress Update API for Core, Plugins and Themes
date: 2024-10-01T06:15:40+00:00
modified: 2025-05-13T08:28:31+00:00
permalink: https://wpelevator.com/guides/replace-wordpress-update-apis
post_type: page
author:
  name: Kaspars
  avatar: https://secure.gravatar.com/avatar/92bfcd3a8c3a21a033a6484d32c25a40b113ec6891f674336081513d5c98ef76?s=96&d=robohash&r=g
---

# How to Replace WordPress Update API for Core, Plugins and Themes

In order to route all requests to `api.wordpress.org` APIs to a custom service, we first need to [mirror the WordPress core, plugin and theme SVN repositories](https://wpelevator.com/guides/mirror-wordpress-svn-repositories).

WP.org hosts the API at `api.wordpress.org` ([documented in the old wiki](https://codex.wordpress.org/WordPress.org_API)) which is accessed by WP installations via `HTTP` on older servers that [can’t do latest HTTPS crypto](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-includes/http.php#L386-L404) or upgraded to `HTTPS` requests on all other server.

## API Source Code

Most of the source code for the `api.wordpress.org` endpoints is available in the [“meta” SVN repository](https://meta.svn.wordpress.org/sites/trunk/) which is also [mirrored on GitHub](https://github.com/WordPress/wordpress.org).

## API Endpoints

WordPress contains the following hard-coded API endpoints in the source code. All of the update endpoints use `POST` requests with a very dynamic payload for each site (hard to cache) that includes all of the installed components (i.e. themes, plugins, translations) and their versions along with the site URL and other meta data.

### Core API Endpoints

Source for the main `core/version-check` endpoint is **not public**!

- `core/credits/1.1/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/credits.php#L35))
- `core/browse-happy/1.1/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/dashboard.php#L1814))
- `core/serve-happy/1.0/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/misc.php#L1607))
- `core/importers/1.1/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/import.php#L149))
- `core/checksums/1.0/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/update.php#L132))
- `core/version-check/1.7/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-includes/update.php#L182)) `POST` request with `wp_install` (network site URL or home URL) and `wp_blog` (home URL) headers.

### Plugin API Endpoints

Served by [`plugin-directory` plugin](https://github.com/WordPress/wordpress.org/tree/3e6399450cea4e6682babb8d755389b59824da99/wordpress.org/public_html/wp-content/plugins/plugin-directory).

- `plugins/info/1.2/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/plugin-install.php#L149))
- `plugins/update-check/1.1/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-includes/update.php#L430)) `POST` request.

### Theme API Endpoints

- `themes/info/1.2/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/theme.php#L545))
- `themes/update-check/1.1/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-includes/update.php#L709))

### Translations API Endpoints

- `translations/plugins/1.0/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/translation-install.php#L53))
- `translations/themes/1.0/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/translation-install.php#L53))
- `translations/core/1.0/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/translation-install.php#L53))

### Patterns API Endpoints

- `patterns/1.0/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php#L90-L120)) `GET` request.

### Miscellaneous API Endpoints

- `secret-key/1.1/salt/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/setup-config.php#L361) and [source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/network.php#L557)) — `GET` request with no payload.
- `events/1.0/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/includes/class-wp-community-events.php#L101-L109)) — `GET` request with WP version `user-agent` and location arguments.
- `core/handbook/1.0/` ([source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/theme-editor.php#L327) and [source](https://github.com/WordPress/WordPress/blob/a8af90bcd1c323cf792c156f355db87767b9f7ab/wp-admin/plugin-editor.php#L298)) front-end only (not called by the server)

## How to Rewrite WordPress.org API Requests

Use the [`http_api_curl` filter](https://developer.wordpress.org/reference/hooks/http_api_curl/) to rewrite the URLs of the WP.org API requests to your own custom endpoint:

```
add_action(
	'http_api_curl',
	function ( $handle, $parsed_args, $url ) {
		$hostname_map = [
			// REPLACE these with your own hostnames.
			'api.wordpress.org' => 'reverse.example.net/wp-api',
			'downloads.wordpress.org' => 'reverse.example.net/wp-downloads',
		];

		// Attempt to rewrite the request hostname.
		$url_replaced = str_replace(
			array_keys( $hostname_map ),
			array_values( $hostname_map ),
			$url
		);

		if ( $url_replaced !== $url ) {
			curl_setopt( $handle, CURLOPT_URL, $url_replaced );
		}
	},
	1000,
	3
);
```

This can be placed in a custom plugin or must-use plugin to get applied globally.