wp2shell: more than a month later. Confirm 6.8.6, 6.9.5, 7.0.2. Patched is not clean.

Read the advisory

WordPress API integration for beginners

How to call external APIs from WordPress safely: REST basics, wp_remote_get, storing keys, rate limits, and what Security Ninja does and does not do.

Topics Beginner guides

Lars Koudal

Lars Koudal

Updated Published

APIs let WordPress talk to other services: weather, payments, CRMs, maps, stock data. Done well, your site shows live data without hand-editing pages. Done badly, you leak API keys, hammer third-party quotas, or trust unvalidated JSON on the front end.

WordPress API integration

What an API is (in practice)

An application programming interface is a contract: you send a request to an endpoint, you get structured data back (usually JSON). You do not need the other company’s source code. You need their docs, auth method, and rate limits.

Common shapes:

  • REST APIs: HTTP methods (GET, POST, and so on) against URLs
  • WordPress REST API: WordPress’s own HTTP API for posts, users, settings, custom routes
  • Third-party APIs: Stripe, Google Maps, social platforms, and similar

WordPress also exposes an HTTP client so your PHP code can call those endpoints without reinventing sockets.

WordPress REST API vs external APIs

Do not mix the two in your head:

  • The WordPress REST API is how other apps (and your own JS) talk to WordPress.
  • An external API is how WordPress talks out to another service.

You often use both: a custom REST route on your site that, server-side, calls Stripe or a weather provider and returns a cleaned response to the browser.

Calling an API from PHP

Prefer the WordPress HTTP API over raw curl unless you have a specific need.

$response = wp_remote_get(
	'https://api.example.com/v1/status',
	array(
		'timeout' => 15,
		'headers' => array(
			'Authorization' => 'Bearer ' . EXAMPLE_API_TOKEN,
		),
	)
);

if ( is_wp_error( $response ) ) {
	// Log and fail closed.
	return;
}

$code = wp_remote_retrieve_response_code( $response );
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );

wp_remote_post() follows the same pattern for writes. Put reusable logic in a small custom plugin, not only in the theme’s functions.php, so the integration survives theme switches.

For front-end updates without full page reloads, use the REST API or admin-ajax carefully, still keeping secrets on the server.

Walkthrough: shortcode that shows remote status

Goal: show a short status string from https://api.example.com/v1/status without exposing the API token to browsers.

  1. Store the secret in wp-config.php (or the host env), not in the database options screen:
define( 'EXAMPLE_API_TOKEN', 'replace-me' );
  1. Fetch on the server inside a small plugin, cache the result, and fail closed:
function example_get_remote_status() {
	$cached = get_transient( 'example_api_status' );
	if ( false !== $cached ) {
		return $cached;
	}

	$response = wp_remote_get(
		'https://api.example.com/v1/status',
		array(
			'timeout' => 15,
			'headers' => array(
				'Authorization' => 'Bearer ' . EXAMPLE_API_TOKEN,
			),
		)
	);

	if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
		return '';
	}

	$data = json_decode( wp_remote_retrieve_body( $response ), true );
	if ( ! is_array( $data ) || empty( $data['status'] ) ) {
		return '';
	}

	$status = sanitize_text_field( $data['status'] );
	set_transient( 'example_api_status', $status, 5 * MINUTE_IN_SECONDS );
	return $status;
}
  1. Print with escaping in a shortcode:
add_shortcode(
	'example_status',
	function () {
		$status = example_get_remote_status();
		if ( '' === $status ) {
			return '<p>Status unavailable.</p>';
		}
		return '<p>Status: ' . esc_html( $status ) . '</p>';
	}
);
  1. Optional REST wrapper if JavaScript needs the value: register a custom route that calls the same helper and returns JSON. Still keep EXAMPLE_API_TOKEN only in PHP. Check capabilities if the data is not public.

  2. Operate it: log failures, watch provider rate limits, rotate the token when people leave, and delete the plugin when the integration dies.

Swap in your real endpoint and field names. The security shape stays the same: secret on the server, validate JSON, escape HTML, cache when you can.

Plugins vs custom code

No-code API plugins (for example WPGetAPI-style tools) help non-developers map endpoints in wp-admin. Custom code gives you control, tests, and clearer security review.

Either way:

  1. Read the provider’s auth and rate-limit docs
  2. Store credentials outside the theme repo when you can
  3. Cache responses that do not need to be live every page view
  4. Validate and sanitize anything you print

Secure integration habits

Protect keys. Do not hardcode secrets in public repos or paste them into page content. wp-config.php constants, environment variables, or a secrets store beat committing tokens to Git.

Least privilege. Use scoped API keys. Revoke keys you no longer need. See least privilege.

Validate responses. Never trust remote JSON blindly. Check HTTP status codes. Escape output when rendering HTML.

Rate limit and cache. Call APIs on cron or on demand with transients, not on every anonymous page hit, unless the provider and your host can take it.

Error handling. Failed calls should degrade gracefully, not white-screen the site.

Where WP Security Ninja fits

WP Security Ninja helps with site security posture: tests, hardening guidance, monitoring modules, and related tools. It is not an API connector builder and it does not “auto-integrate” Stripe or weather feeds for you.

Use Security Ninja to keep the WordPress install harder to abuse while your integration code (or a dedicated API plugin) handles the external calls. Broader baseline: WordPress security checklist.

Quick start checklist

  1. Pick the API and confirm auth, HTTPS endpoints, and quotas
  2. Decide plugin UI vs custom plugin code
  3. Store the key securely; never expose it to the browser unless the provider designed public tokens
  4. Fetch with wp_remote_get / wp_remote_post, parse JSON, handle errors
  5. Cache, display safely, and monitor failures in logs
  6. Re-test after WordPress and plugin updates

APIs make WordPress more useful. Treat every key like a password and every remote payload like untrusted input, and most integration pain stays boring.

Found this useful? Share it.

Larger screenshot