Independent Editorial DeskWordPress Releases, Builds, and Operations
Back to Archive
Implementation Notes

WordPress Rewrite Rules Example: Add a Custom URL Endpoint Safely

Add custom WordPress rewrite rules safely with query vars, activation flushing, route validation, 404 handling, and collision prevention.

Published

April 20, 2026

Reading Time

3 min read

Updated

April 20, 2026

Abstract URL routing path with nodes representing WordPress rewrite rule matching.
Build PatternImplementation Notes

Implementation Notes

Extension points, code paths, and implementation choices that should survive contact with production.

Best For

WordPress developers, agencies, and technical teams building custom plugin or theme functionality with cleaner operational defaults.

Primary Topics

Implementation Notes

Editorial Focus

Build Pattern: Extension points, code paths, and implementation choices that should survive contact with production. Updated on April 20, 2026.

Full Report

Last reviewed: April 20, 2026

Custom URLs in WordPress are powerful, but rewrite rules can break a production site quickly when they are registered incorrectly. A bad rule can shadow existing URLs, create confusing 404s, or require repeated manual permalink flushing.

This guide shows a practical Rewrite API example for adding a custom URL endpoint. The pattern keeps the rule inside a plugin, registers query vars, flushes rules only on activation, and renders a controlled response.

Who this guide is for

This article is for WordPress developers building custom landing pages, tracking endpoints, documentation routes, simple public tools, or plugin-owned URL surfaces that do not fit normal posts or pages.

When to use rewrite rules

Use rewrite rules when WordPress needs to understand a pretty URL and route it to plugin logic. Do not use rewrite rules just to avoid creating a page, custom post type, REST route, or template. Pick the API that matches the feature.

Plugin example: public report URL

<?php
/**
 * Plugin Name: VulnWP Report Route
 * Description: Adds a custom pretty URL for public reports.
 * Version: 1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

add_action( 'init', 'vulnwp_register_report_rewrite' );
add_filter( 'query_vars', 'vulnwp_register_report_query_vars' );
add_action( 'template_redirect', 'vulnwp_render_report_route' );

function vulnwp_register_report_rewrite() {
	add_rewrite_rule(
		'^security-report/([a-z0-9-]+)/?$',
		'index.php?vulnwp_report_slug=$matches[1]',
		'top'
	);
}

function vulnwp_register_report_query_vars( $vars ) {
	$vars[] = 'vulnwp_report_slug';
	return $vars;
}

function vulnwp_render_report_route() {
	$slug = get_query_var( 'vulnwp_report_slug' );

	if ( '' === $slug ) {
		return;
	}

	$slug = sanitize_key( $slug );

	status_header( 200 );
	nocache_headers();

	wp_send_json(
		array(
			'slug'   => $slug,
			'status' => 'available',
		)
	);
}

This creates URLs like /security-report/example-slug/. The plugin sanitizes the slug and returns a controlled JSON response.

Flush rules on activation only

register_activation_hook(
	__FILE__,
	function () {
		vulnwp_register_report_rewrite();
		flush_rewrite_rules();
	}
);

register_deactivation_hook(
	__FILE__,
	function () {
		flush_rewrite_rules();
	}
);

Do not call flush_rewrite_rules() on every request. It is expensive and unnecessary. Register the rules on every request, but flush only when rules change, usually on activation and deactivation.

Test the route

curl -i https://example.com/security-report/demo-report/
wp rewrite list --match=/security-report/demo-report/

The first command checks the HTTP response. The second helps inspect which rewrite rule matches when WP-CLI is available.

Avoid route collisions

Choose a unique prefix that belongs to the plugin or feature. Generic prefixes such as /report/, /api/, or /download/ are more likely to collide with pages, plugins, or future site structure. If the route is public, document it like any other URL contract.

Return 404 for invalid resources

A rewrite rule means WordPress can route the URL. It does not mean every matched URL is valid. If the requested resource does not exist, return a real 404 instead of a blank success response.

if ( ! vulnwp_report_exists( $slug ) ) {
	status_header( 404 );
	nocache_headers();
	include get_query_template( '404' );
	exit;
}

This matters for SEO. Search engines should not index unlimited fake URLs that happen to match the rewrite pattern.

Private endpoints

If the custom route exposes private data, add authentication and authorization before rendering. Rewrite rules are not security controls. They only map a URL to request variables.

if ( ! is_user_logged_in() || ! current_user_can( 'read_private_posts' ) ) {
	auth_redirect();
}

For machine-readable APIs, a REST route with a permission_callback is often cleaner than a custom rewrite endpoint.

Production checklist

  • Register rewrite rules on init.
  • Register custom query vars.
  • Flush rewrite rules only on activation, deactivation, or controlled migrations.
  • Use a unique URL prefix to avoid collisions.
  • Sanitize values extracted from the URL.
  • Return proper status codes for missing or invalid resources.
  • Test with existing pages and post slugs before launch.

Common mistakes

  • Flushing on every request. This creates unnecessary overhead.
  • Forgetting query vars. WordPress may strip unknown variables.
  • Using overly broad regex. Broad rules can shadow existing content.
  • No activation flush. New URLs may 404 until permalinks are refreshed.
  • Treating URL values as trusted. Rewrite matches still come from user requests.

Related reading

For API-style JSON output, compare this with our register_rest_route example. For URL changes across a site, read the search-replace safety checklist.

References and further reading

Popular Guides

Popular WordPress guides to read next.

These articles connect recurring production concerns: implementation details, updates, troubleshooting, recovery paths, and operational cleanup.

Continue Reading

More from the archive.

Diagnostic dashboard scene representing a WordPress Site Health review before major updates.
01Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Site Health Check Before Major Updates: What to Review First

A pre-update WordPress Site Health checklist covering loopbacks, connectivity, debug settings, and environment readiness.

Structured data and route review scene representing permalink validation after a WordPress migration.
02Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Permalink Checklist After Migration: Catch URL Problems Early

A post-migration WordPress permalink checklist for checking rewrite rules, post URLs, archives, and redirect noise.

Technical media workspace representing image preparation and optimization before upload to WordPress.
03Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Image Optimization Checklist: What to Fix Before Upload

A practical WordPress image optimization checklist covering dimensions, compression, formats, and Media settings before upload.