WordPress add_rewrite_endpoint Example: Add a Custom URL Endpoint Safely
Use add_rewrite_endpoint() for cleaner pretty-URL extensions without relying on raw rewrite regexes or per-request flushes.
Published
May 2, 2026
Reading Time
2 min read
Updated
May 3, 2026

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
Editorial Focus
Build Pattern: Extension points, code paths, and implementation choices that should survive contact with production. Updated on May 3, 2026.
Full Report
Last reviewed: May 3, 2026
Pretty URLs often need one extra structured segment for downloads, alternate render modes, or export flows. add_rewrite_endpoint() is the core helper for attaching that segment to supported permalink structures without jumping straight to raw rewrite regexes.
This guide shows how to register an endpoint safely and avoid the two classic mistakes: flushing on every request and forgetting to handle the generated query variable.
Register the endpoint on init
<?php
add_action( 'init', 'vulnwp_register_export_endpoint' );
function vulnwp_register_export_endpoint() {
add_rewrite_endpoint( 'export', EP_PERMALINK | EP_PAGES );
}
The endpoint name becomes a query variable by default, and the endpoint mask controls which permalink structures will receive it.
Handle the new query variable deliberately
add_action( 'template_redirect', 'vulnwp_handle_export_endpoint' );
function vulnwp_handle_export_endpoint() {
$export_mode = get_query_var( 'export', null );
if ( null === $export_mode ) {
return;
}
wp_die( 'Export endpoint hit: ' . esc_html( $export_mode ) );
}
The endpoint only gives routing. Application logic still needs to decide what the new URL should do.
Flush rewrite rules only on lifecycle events
The WordPress reference explicitly says to flush rewrite rules on activation or deactivation. Do not flush them on every request just because an endpoint exists.
Always use the EP_* constants
The documentation warns that the underlying endpoint values are not meant to be hardcoded. Use the named constants directly.
Production checklist
- Register endpoints on
init. - Use the correct
EP_*mask for the intended URL structures. - Handle the generated query variable explicitly.
- Flush rewrite rules only on activation or deactivation.
- Test the endpoint across the site’s active permalink structure.
- Document the endpoint contract if other systems depend on it.
Common mistakes
- Flushing rewrite rules on every request. That is a classic performance mistake.
- Registering the endpoint but never handling it. Routing alone is not behavior.
- Using raw integer masks. The constants are the supported interface.
- Attaching the endpoint to the wrong structures. The mask should reflect the real routing target.
- Skipping activation and deactivation testing. Rewrite changes need lifecycle verification.
Related reading
If the routing need is broader than one extra endpoint, pair this with the rewrite rules guide. If the endpoint is really becoming an API surface, continue with the register_rest_route article.


