Hooks, REST and WP-CLI
Actions
redeemid_signed_in,redeemid_linked,redeemid_disconnectedandredeemid_before_logoutredeemid_log, which receives redacted log eventsredeemid_levels_changed(int $user_id, string[] $added, string[] $removed), with level slugs, after a syncredeemid_access_changed(int[] $post_ids),redeemid_access_levels_changedandredeemid_access_locked_changed(int $post_id, bool $locked)redeemid_features_changed(int $user_id, string[] $added, string[] $removed) andredeemid_features_mapping_changed(string[] $slugs)
For example, purge a page cache when an item’s rule changes. An empty list means any item may have changed:
add_action( 'redeemid_access_changed', function ( array $post_ids ) {
if ( ! $post_ids ) {
my_cache_purge_all();
return;
}
foreach ( $post_ids as $post_id ) {
my_cache_purge_url( get_permalink( $post_id ) );
}
} );
Filters
- Sign-in:
redeemid_auth_callback_slug,redeemid_default_redirect,redeemid_customer_admin_redirect,redeemid_sign_in_redirectandredeemid_offer_existing_account - Settings:
redeemid_setting_{key} - Access:
redeemid_access_levelsandredeemid_access_rules(set levels and content rules from code; the admin screens then show them read-only),redeemid_gated_post_types,redeemid_access_context,redeemid_effective_rule,redeemid_teaser_settings,redeemid_paywall_schemaandredeemid_drip_days - Features:
redeemid_features,redeemid_feature_testsandredeemid_feature_decision(see Features) - Commerce:
redeemid_context_country,redeemid_buyer_ipandredeemid_checkout_banner - Display:
redeemid_locked_panelandredeemid_health_checks - Other:
redeemid_official_state,redeemid_reassign_userandredeemid_pre_sync_now
For example, send Shopify the visitor’s real IP from a header your CDN sets. Forwarded headers aren’t read by default, because visitors can forge them:
add_filter( 'redeemid_buyer_ip', function ( string $ip ) {
if ( empty( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
return $ip;
}
return sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_CONNECTING_IP'] ) );
} );
REST routes
The namespace is redeemid/v1. Every write route needs the wp_rest nonce.
| Route | Purpose |
|---|---|
GET /auth/status |
The caller’s own display-safe state |
GET /auth/login |
Redirects to Shopify |
POST /auth/logout |
Returns {redirect}, the Shopify end-session URL |
POST /auth/refresh |
Refreshes the Shopify session; returns status, never tokens |
POST /auth/disconnect |
Unlinks the Shopify customer from the current user |
POST /account/sync |
Re-syncs the current user’s record (rate-limited) |
POST /cart/identity |
Attaches the signed-in customer to Shopify’s plugin cart (rate-limited) |
POST /webhooks/events |
Shopify webhooks (HMAC-verified) |
GET /features |
The caller’s own granted feature slugs |
GET /editor/products?search= |
The Plan Card product picker (editors only) |
For example, refresh the signed-in member’s record from a script, with a nonce from wp_create_nonce( 'wp_rest' ):
await fetch( '/wp-json/redeemid/v1/account/sync', {
method: 'POST',
headers: { 'X-WP-Nonce': restNonce },
} );
Forms that work without JavaScript post to admin-post.php handlers instead (redeemid_login, _logout, _connect, _link_confirm, _sync and _disconnect), which redirect back to a page.
WP-CLI
wp redeemid resync user <id>...
wp redeemid resync all [--foreground]
wp redeemid resync status|pause|resume|cancel
wp redeemid access explain <post> --as=<guest|signed-in|level|tags|user> [--tags=a,b] [--user=<id>] [--format=json]
wp redeemid access recompute
For example, see why a guest can’t read post 42:
wp redeemid access explain 42 --as=guest