benecaster_manual_grant_expired
Fires at the end of ManualGrantExpiryCron::expire_one() after a manual-grant token has been revoked and the manual_grant_expired email has been enqueued. This action fires only for grants that had a non-null manual_expiry_at and whose expiry datetime has elapsed — the hourly cron evaluates the condition and calls the expiry path.
Use this hook to clean up external state that was set up when the grant was created via benecaster_manual_subscriber_created: remove a WordPress role, revoke a Discord role, untag a CRM contact, or notify an external system that access has ended.
This action fires from a WP-Cron context, not from an admin request. Outbound HTTP calls in callbacks will not block any user-facing action, but WP-Cron reliability depends on site traffic. On low-traffic sites, expiry may lag by up to an hour after the grant’s datetime has passed.
This action does not fire when an admin manually revokes a grant before its expiry — that path fires benecaster_token_revoked. Hook both if you need blanket cleanup on all revocations.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
$user_id |
int |
— | WordPress user ID of the subscriber whose grant has expired |
$show_id |
int |
— | WordPress post ID of the show the grant was associated with |
Examples
Remove a WordPress role when a comped subscriber's access expires
add_action( 'benecaster_manual_grant_expired', function( int $user_id, int $show_id ): void {
$user = get_userdata( $user_id );
if ( $user ) {
$user->remove_role( 'beta_tester' );
}
}, 10, 2 );
Untag the subscriber in an external CRM on expiry
add_action( 'benecaster_manual_grant_expired', function( int $user_id, int $show_id ): void {
$user = get_userdata( $user_id );
if ( ! $user ) {
return;
}
wp_remote_post( 'https://crm.example.com/api/untag', [
'body' => wp_json_encode( [
'email' => $user->user_email,
'tag' => 'benecaster-comp',
'show_id' => $show_id,
] ),
] );
}, 10, 2 );
Notes
Pair with benecaster_manual_subscriber_created to keep external state coherent across the full manual-grant lifecycle. See the tag-manual-grants-with-user-role recipe for a complete worked example.