Attendees and sign-up hooks

Available in:Free

These hooks follow a sign-up from the RSVP form to the door. Use them to add fields to the form, refuse or limit a registration and add columns to the Attendees screen. Others react when someone registers, cancels, changes date or is deleted.

For the site owner’s side, see setting up an RSVP form and managing attendees. New to hooks? Start with Extending HappenBoard with hooks.

Dates, seats and translations

A sign-up for a recurring event is for one date. The attendee row stores that date’s sequence number in the series (occurrence_seq, 0 for the first date); it is null for a one-off event.

The event’s capacity applies to each date. Only going attendees hold seats: waitlist, declined and cancelled hold none.

With WPML or Polylang, the translations of an event share their seats. Every translation’s registrations count against the capacity of the default language’s translation, and one email registers only once. Each row keeps the translation it was made on, which sets the language of the attendee’s emails.

Which hook fires when

What happensHook
Someone registers (RSVP form, ticket order, import)happenboard_rsvp_submitted
The attendee cancels with their link, or a refund cancels the tickethappenboard_rsvp_cancelled
An operator changes the status, Cancel includedhappenboard_attendee_status_changed
An operator edits the name, email or seatshappenboard_attendee_updated
An operator moves the attendee to another datehappenboard_attendee_date_changed
The attendee is deleted for good, alone or with their eventhappenboard_attendee_deleted
A ticket is scanned at the door (Pro)happenboard_pro_attendee_checked_in

happenboard_rsvp_form_fields

Filter Free and Pro src/Block/RsvpForm/Block.php

Adds your own inputs to the RSVP Form, after the email field and before the number of seats. HappenBoard Pro’s Ticket Picker prints the same fields, so ticket buyers are asked them too.

Signature

apply_filters( 'happenboard_rsvp_form_fields', string $html, int $post_id )

Parameters

$html string
HTML to print. Empty by default.
$post_id int
The event.

Return value

string HTML printed as is: escape everything you build.

Example

add_filter(
    'happenboard_rsvp_form_fields',
    function ( string $html, int $post_id ): string {
        // The form sends only inputs named happenboard_cf_<key>.
        $html .= sprintf(
            '<label class="wp-block-happenboard-rsvp-form__field"><span>%s</span><input type="text" name="happenboard_cf_diet" maxlength="190"></label>',
            esc_html__( 'Dietary requirements', 'my-plugin' )
        );
        return $html;
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • Append to $html: HappenBoard Pro prints its custom fields through this filter too.
  • Name each input happenboard_cf_<key>. The form sends only those, keyed <key>, and skips disabled ones. A value is stored only if happenboard_rsvp_custom_fields keeps it.
  • It runs only when the form is shown: not for an event that is cancelled, postponed, over, undated, full or locked by a password. HappenBoard Pro replaces the form with the Ticket Picker on an event that has tickets.

happenboard_rsvp_custom_fields

Filter Free and Pro src/Service/Attendees/RsvpService.php

Checks the extra answers sent with a sign-up and returns the ones to store on the attendee. It is the other half of happenboard_rsvp_form_fields: that filter prints the input, this one keeps the value.

Signature

apply_filters( 'happenboard_rsvp_custom_fields', array<string,mixed> $fields, array<string,string|array<int,string>> $raw, int $event_id )

Parameters

$fields array<string,mixed>
Answers kept so far. Empty by default.
$raw array<string,string|array<int,string>>
What was sent, keyed by field key (the input name without happenboard_cf_). Keys went through sanitize_key() and values through sanitize_text_field(), which is not validation.
$event_id int
The event.

Return value

array<string,mixed>|WP_Error The answers to store, or a WP_Error to refuse the sign-up with its message. Any other value stores nothing.

Example

add_filter(
    'happenboard_rsvp_custom_fields',
    function ( $fields, array $raw, int $event_id ) {
        $fields = is_array( $fields ) ? $fields : array();
        $diet   = sanitize_text_field( (string) ( $raw['diet'] ?? '' ) );
        if ( '' === $diet ) {
            // The RSVP Form shows this message to the visitor.
            return new WP_Error( 'my_diet_required', __( 'Please tell us about your dietary requirements.', 'my-plugin' ), array( 'status' => 400 ) );
        }
        $fields['diet'] = $diet;
        return $fields;
    },
    20,
    3
);

Notes

  • Three arguments: register with 10, 3, at priority 20 or later when HappenBoard Pro is active. Pro checks its own fields at 10 and, when the event has some, returns only those.
  • Merge into $fields rather than replacing it. The result is stored as JSON, so keep to strings and arrays of strings.
  • It runs for every sign-up through HappenBoard’s RSVP service (the form, the create-rsvp ability, Pro’s CSV import and its dry runs), after the date, duplicate and capacity checks. Pro’s Ticket Picker checkout applies it too; WooCommerce orders do not.

happenboard_rsvp_allowed

Filter Free src/Service/Attendees/RsvpService.php

Decides whether an event takes free sign-ups at all. Return a WP_Error to refuse the sign-up with your own code, message and HTTP status.

Signature

apply_filters( 'happenboard_rsvp_allowed', true|WP_Error $allowed, int $event_id, array<string,mixed> $input )

Parameters

$allowed true|WP_Error
true, or the WP_Error of an earlier callback.
$event_id int
The event, already known to be published and still taking sign-ups.
$input array<string,mixed>
The registration: event_id, email, display_name, quantity, occurrence (the date asked for), raw_fields, and from operator tools user_id, status, bypass_capacity, validate_only or Pro’s comp.

Return value

true|WP_Error true to go on, or a WP_Error returned to the caller as is. Any other value refuses with happenboard_rsvp_not_allowed (HTTP 403).

Example

add_filter(
    'happenboard_rsvp_allowed',
    function ( $allowed, int $event_id, array $input ) {
        if ( is_wp_error( $allowed ) ) {
            return $allowed;
        }
        // Staff-only events take staff addresses only.
        $staff = str_ends_with( strtolower( (string) ( $input['email'] ?? '' ) ), '@example.com' );
        if ( has_term( 'staff-only', 'happenboard_category', $event_id ) && ! $staff ) {
            return new WP_Error( 'my_staff_only', __( 'This event is open to staff only.', 'my-plugin' ), array( 'status' => 403 ) );
        }
        return $allowed;
    },
    20,
    3
);

Notes

  • Three arguments: register with 10, 3.
  • Pass an incoming WP_Error on untouched. The check is strict: 1 or 'yes' refuses.
  • It runs for every caller of HappenBoard’s RSVP service, after the event checks (published, not cancelled, postponed or over) and before the date, duplicate, capacity and field checks.
  • HappenBoard Pro uses it at priority 10 to refuse plain sign-ups on any event that has tickets, free or paid (happenboard_pro_ticket_required), unless its CSV import marks the row comp.

happenboard_rsvp_max_quantity

Filter Free src/Service/Attendees/RsvpQuantityLimit.php

Filters the most seats one sign-up may ask for through the public RSVP route. HappenBoard reads it from the RSVP Form blocks on the event’s page, so a request cannot ask for more than the form offers.

Signature

apply_filters( 'happenboard_rsvp_max_quantity', int $limit, int $event_id )

Parameters

$limit int
The largest limit among the RSVP Form blocks in the event’s content and single-event template. A form allows 1 seat without Allow multi-seat RSVP, else its Maximum seats per RSVP (4 by default). 20 when no form is found.
$event_id int
The event.

Return value

int The limit, kept between 1 and 20 after the filter.

Example

add_filter(
    'happenboard_rsvp_max_quantity',
    function ( int $limit, int $event_id ): int {
        // Workshop forms sit in a synced pattern HappenBoard cannot see: they allow 6 seats.
        if ( has_term( 'workshops', 'happenboard_category', $event_id ) ) {
            return 6;
        }
        return $limit;
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • Forms inside a synced pattern or a template part are not seen. On a classic theme, the form HappenBoard adds after the content counts as a one-seat form.
  • It limits the public POST /happenboard/v1/rsvp route only: a larger request is refused with happenboard_quantity_too_high (HTTP 400). It does not change the number the form offers, and operator tools (the create-rsvp ability, the CSV import) ignore it.

happenboard_rsvp_client_ip

Filter Free and Pro src/REST/Rsvp.php

Filters the visitor address the sign-up throttle counts on (5 sign-ups per address per minute). HappenBoard reads REMOTE_ADDR and ignores X-Forwarded-For, so behind a proxy or CDN every visitor shares one address until you filter it.

Signature

apply_filters( 'happenboard_rsvp_client_ip', string $ip )

Parameters

$ip string
REMOTE_ADDR if it is a valid IP, else an empty string.

Return value

string The address to count on. Return $ip when you cannot do better.

Example

// Behind Cloudflare: count each visitor's real address.
add_filter(
    'happenboard_rsvp_client_ip',
    fn( $ip ) => filter_var( $_SERVER['HTTP_CF_CONNECTING_IP'] ?? '', FILTER_VALIDATE_IP ) ?: $ip
);

// Booking forms have their own filter: add the same there.
add_filter(
    'happenboard_booking_client_ip',
    fn( $ip ) => filter_var( $_SERVER['HTTP_CF_CONNECTING_IP'] ?? '', FILTER_VALIDATE_IP ) ?: $ip
);

Notes

  • One argument.
  • Trust only a header your own proxy sets, and only if the site cannot be reached without the proxy: otherwise anyone can send the header and change it at will. With X-Forwarded-For, take the address your proxy added, not the first one, which the visitor controls.
  • HappenBoard Pro’s throttles use the same filter: free Ticket Picker carts (in the RSVP budget), paid checkouts (see happenboard_pro_checkout_limits) and event submissions (3 per address every 10 minutes).
  • The address is also sent to Turnstile and Akismet. An empty string turns the per-address limit off; the per-email limit (3 per hour), the honeypot and the minimum fill time still apply.

happenboard_rsvp_submitted

Action Free and Pro src/Service/Attendees/RsvpService.php

Fires right after an attendee row is created, for a free sign-up or a ticket order. Use it for anything that must happen when someone registers.

Signature

do_action( 'happenboard_rsvp_submitted', int $attendee_id, array{event_id:int,occurrence_seq:?int,email:string,display_name:string,quantity:int,cancel_token:string} $data )

Parameters

$attendee_id int
The new attendee.
$data array<string,mixed>
event_id, occurrence_seq (the date of a recurring event, else null), email, display_name, quantity and cancel_token. Pro’s ticket paths add paid, source (stripe, woocommerce or free_ticket) and session_id or order_id.

Example

add_action(
    'happenboard_rsvp_submitted',
    function ( int $attendee_id, array $data ): void {
        // Log every new registration.
        error_log( sprintf(
            'Attendee %d registered for event %d with %d seat(s).',
            $attendee_id,
            (int) $data['event_id'],
            (int) $data['quantity']
        ) );
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • It fires from HappenBoard’s RSVP service: the form, the create-rsvp ability, Pro’s CSV import (not its dry runs). Pro also fires it from its Stripe webhook, WooCommerce orders and free ticket carts, once per ticket line, so one order can fire it several times.
  • $data has no status: read the row when you need it, since an import can record waitlisted or declined rows. HappenBoard sends its confirmation email at priority 10, to going attendees only.
  • cancel_token is the secret behind the attendee’s cancel link. Never log it, show it or send it to a third party.

happenboard_rsvp_cancelled

Action Free and Pro src/REST/Rsvp.php

Fires when a sign-up is cancelled by the attendee (the cancel link in their emails, or DELETE /happenboard/v1/rsvp/{token}) or by a refund in HappenBoard Pro. The row is kept with the status cancelled and its seats are free again.

Signature

do_action( 'happenboard_rsvp_cancelled', int $attendee_id )

Parameters

$attendee_id int
The attendee whose sign-up was cancelled.

Example

add_action(
    'happenboard_rsvp_cancelled',
    function ( int $attendee_id ): void {
        // The row still exists, with the status cancelled.
        $attendee = ( new \HappenBoard\Service\Attendees\Repository() )->find_by_id( $attendee_id );
        if ( null !== $attendee ) {
            error_log( 'Seat released for ' . $attendee['email'] );
        }
    }
);

Notes

  • One argument.
  • HappenBoard Pro fires it for each line a Stripe refund cancels (from the Orders screen or the charge.refunded webhook) and for a WooCommerce order that is refunded, cancelled or failed. Your callback may then run in a webhook request with no user signed in.
  • A partial Stripe refund cancels only the lines it pays back in full or the operator chose. A repeated cancellation fires nothing.
  • An operator’s cancellation (Attendees screen, cancel-rsvp ability) fires happenboard_attendee_status_changed instead. HappenBoard sends the cancellation email in both cases.

happenboard_attendee_status_changed

Action Free src/Service/Attendees/AttendeeStatusService.php

Fires when an operator changes an attendee’s status: on the Attendees screen (its Cancel action included), through PATCH /happenboard/v1/attendees/{id}, or with the update-attendee-status and cancel-rsvp abilities.

Signature

do_action( 'happenboard_attendee_status_changed', int $attendee_id, string $new_status, string $old_status )

Parameters

$attendee_id int
The attendee.
$new_status string
The new status: going, waitlist, cancelled or declined.
$old_status string
The status before. Empty string when the row had none.

Example

add_action(
    'happenboard_attendee_status_changed',
    function ( int $attendee_id, string $new_status, string $old_status ): void {
        // Someone got a seat from the waitlist.
        if ( 'going' === $new_status && 'waitlist' === $old_status ) {
            error_log( sprintf( 'Attendee %d promoted from the waitlist.', $attendee_id ) );
        }
    },
    10,
    3
);

Notes

  • Three arguments: register with 10, 3. The new status comes before the old one.
  • It fires after a successful write, and only when the status really changes. A move to going whose seats do not fit in the capacity is refused before anything is written, unless the operator confirms it over capacity, so it does not fire.
  • HappenBoard emails the attendee from it: the confirmation when they come off the waitlist, the cancellation when they are cancelled. HappenBoard Pro gives back or takes ticket seats here, since only going holds seats.

happenboard_attendee_updated

Action Free src/REST/Attendees.php

Fires when an operator edits an attendee’s name, email or number of seats through PATCH /happenboard/v1/attendees/{id} (the Attendees screen). It receives the before and after of each field that changed.

Signature

do_action( 'happenboard_attendee_updated', int $attendee_id, array<string,array{from:mixed,to:mixed}> $changes )

Parameters

$attendee_id int
The attendee.
$changes array<string,array{from:mixed,to:mixed}>
Keyed by column (display_name, email, quantity), each with from and to.

Example

add_action(
    'happenboard_attendee_updated',
    function ( int $attendee_id, array $changes ): void {
        if ( ! isset( $changes['email'] ) ) {
            return;
        }
        // Keep our mailing list in step with the new address.
        my_plugin_sync_contact( (string) $changes['email']['from'], (string) $changes['email']['to'] );
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • The keys are column names, not the camelCase names of the request. A request that changes nothing still fires it with an empty array: return early.
  • A status change in the same request fires happenboard_attendee_status_changed after this one. Raising the seats of a going attendee is checked first (happenboard_attendee_seats_left); a refused request fires nothing.

happenboard_attendee_seats_left

Filter Free src/Service/Attendees/SeatCheck.php

Filters how many seats an attendee may hold when an operator raises their number of seats or moves them to going: on the Attendees screen (Mark as Going included) or with the update-attendee-status ability. HappenBoard allows the event’s capacity (the date’s, on a recurring event) less the seats the other going attendees hold.

Signature

apply_filters( 'happenboard_attendee_seats_left', int|null $left, array<string,mixed> $attendee )

Parameters

$left int|null
Seats the attendee may hold, or null when the event has no capacity.
$attendee array<string,mixed>
The attendee row before the change (attendee_id, event_id, occurrence_seq, status, quantity…).

Return value

int|null The most seats allowed, or null for no limit. A larger request is refused with happenboard_capacity_full (HTTP 409).

Example

add_filter(
    'happenboard_attendee_seats_left',
    function ( $left, array $attendee ) {
        // No more than 6 seats per attendee, even on events without a capacity.
        return null === $left ? 6 : min( 6, (int) $left );
    },
    20,
    2
);

Notes

  • Two arguments: register with 10, 2. Return an integer or null: other values are cast to an integer, so false means 0 seats and refuses the change.
  • It runs only when an attendee who is, or becomes, going would hold more seats than now: more seats, or a move to going from another status. Not when the operator confirms the change over capacity. Fewer seats always fit.
  • On a translated event, the capacity is the default language translation’s and every translation’s attendees count. Moving an attendee to another date uses happenboard_attendee_date_seats_left instead.
  • HappenBoard Pro answers at priority 10 for ticket holders: what their ticket has left on their date, plus the seats they already hold. Use a later priority to change its answer, as the example does.

happenboard_attendee_date_changed

Action Free src/Service/Attendees/AttendeeDateService.php

Fires after an operator moved an attendee of a recurring event to another date: with Change date on the Attendees screen, through POST /happenboard/v1/attendees/{id}/date, or with the reschedule-rsvp ability. The row is already on the new date.

Signature

do_action( 'happenboard_attendee_date_changed', int $attendee_id, int $sequence, ?int $from, array<string,mixed> $context )

Parameters

$attendee_id int
The attendee moved.
$sequence int
Sequence of the new date.
$from ?int
Sequence of the old date, null when the row had none.
$context array<string,mixed>
event_id; from_start_utc and from_label (the date left); to_start_utc and to_label; quantity; status; over_capacity; notify. Starts are UTC Y-m-d H:i:s, labels use the site’s date and time formats.

Example

add_action(
    'happenboard_attendee_date_changed',
    function ( int $attendee_id, int $sequence, ?int $from, array $context ): void {
        // Keep a trace of every move.
        error_log( sprintf(
            'Attendee %d moved from "%s" to "%s".',
            $attendee_id,
            (string) $context['from_label'],
            (string) $context['to_label']
        ) );
    },
    10,
    4
);

Notes

  • Four arguments: register with 10, 4.
  • It does not fire when the attendee is already on that date or the move is refused. A move is refused for a date skipped, over or not in the series, or one the same email is already registered on. A date without room for a going attendee is refused unless the operator confirms (over_capacity is then true).
  • notify is true when the attendee is going and the operator left the email on. HappenBoard then emails the new date with a calendar file at priority 20 and moves the reminder.
  • HappenBoard Pro moves the ticket seats to the new date at priority 5, before other callbacks read them.

happenboard_attendee_date_seats_left

Filter Free src/Service/Attendees/AttendeeDateService.php

Filters the seats left for one attendee on the dates of a recurring event they could be moved to. HappenBoard counts the event’s capacity against the seats going attendees hold on each date.

Signature

apply_filters( 'happenboard_attendee_date_seats_left', array<int,?int> $left, array<string,mixed> $attendee, array<int,int> $sequences )

Parameters

$left array<int,?int>
Seats left, keyed by sequence; null where nothing limits them.
$attendee array<string,mixed>
The attendee row.
$sequences array<int,int>
The dates asked about.

Return value

array<int,?int> Seats left by sequence, null for no limit. A return that is not an array is ignored.

Example

add_filter(
    'happenboard_attendee_date_seats_left',
    function ( $left, array $attendee, array $sequences ) {
        // Keep two seats in reserve on every limited date.
        foreach ( (array) $left as $sequence => $seats ) {
            if ( null !== $seats ) {
                $left[ $sequence ] = max( 0, $seats - 2 );
            }
        }
        return $left;
    },
    20,
    3
);

Notes

  • Three arguments: register with 10, 3.
  • It runs once for the whole list of dates (up to 200 upcoming dates), then again for the chosen date when a going attendee is moved. Read what you need for all the dates in one query.
  • A move is refused when the attendee’s seats exceed the figure for the date, unless the operator confirms. Return null for a date to lift the limit.
  • HappenBoard Pro answers at priority 10 for ticket holders: the ticket’s capacity on each date less what is sold and held there.

happenboard_attendee_dates_assigned

Action Free src/Service/Attendees/AttendeeDates.php

Fires after attendees of a recurring event who had no date were given one. Each gets the date that was current when they registered: the first not over at that time, else the last.

Signature

do_action( 'happenboard_attendee_dates_assigned', int $event_id, array<int,int> $attendee_ids )

Parameters

$event_id int
The recurring event.
$attendee_ids array<int,int>
The attendees who were given a date.

Example

add_action(
    'happenboard_attendee_dates_assigned',
    function ( int $event_id, array $attendee_ids ): void {
        // Forget the dates we cached for these attendees.
        foreach ( $attendee_ids as $attendee_id ) {
            delete_transient( 'my_attendee_date_' . $attendee_id );
        }
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • Undated rows are sign-ups made before HappenBoard 0.2.0, rows of an event that has since become recurring, and rows inserted with a null date. Placing runs once when the attendees table is upgraded, then on every happenboard_occurrences_changed (priority 20).
  • It fires once per event, only when at least one row was placed. A row older than the first date a long series still stores keeps no date.
  • HappenBoard arms a reminder for the placed attendees whose date is ahead. HappenBoard Pro moves their ticket sales to the same dates.

happenboard_attendee_deleted

Action Free src/Service/Attendees/AttendeeDeletion.php

Fires after an attendee was deleted for good: with Delete permanently on the Attendees screen (DELETE /happenboard/v1/attendees/{id}), or with their event when it is deleted for good. Use it to drop what you store about the attendee.

Signature

do_action( 'happenboard_attendee_deleted', int $attendee_id )

Parameters

$attendee_id int
ID of the row that was deleted.

Example

add_action(
    'happenboard_attendee_deleted',
    function ( int $attendee_id ): void {
        global $wpdb;
        // Delete the badges we printed for this attendee.
        $wpdb->delete( $wpdb->prefix . 'my_badges', array( 'attendee_id' => $attendee_id ), array( '%d' ) );
    }
);

Notes

  • One argument. The row is already gone: capture what you need earlier, for example on happenboard_event_deleting, which still sees the rows.
  • When the event is being deleted, its post and meta can still be read. Cancelling a sign-up deletes nothing and does not fire it.
  • HappenBoard clears the attendee’s pending reminder here. HappenBoard Pro releases the ticket seats, deletes the sale and the attendee’s journal, and sends the attendee.deleted webhook.

happenboard_rest_attendees_prefetch

Action Free src/REST/Attendees.php

Fires once with all the attendee rows a list or export response is about to send, before happenboard_rest_attendee_response runs on each row. Load your data for the whole set here, in one query.

Signature

do_action( 'happenboard_rest_attendees_prefetch', array<int,array<string,mixed>> $rows, WP_REST_Request $request )

Parameters

$rows array<int,array<string,mixed>>
Raw rows in response order (snake_case columns, custom_fields still JSON). An event’s list includes the attendees of its translations.
$request WP_REST_Request
The list (GET /happenboard/v1/attendees) or an export (GET /happenboard/v1/attendees/export).

Example

$my_tiers = array();

add_action(
    'happenboard_rest_attendees_prefetch',
    function ( array $rows ) use ( &$my_tiers ): void {
        // One query for the whole page, keyed by attendee ID.
        $my_tiers = my_plugin_tiers_for( array_map( 'intval', array_column( $rows, 'attendee_id' ) ) );
    }
);
add_filter(
    'happenboard_rest_attendee_response',
    function ( array $serialized, array $row ) use ( &$my_tiers ): array {
        $id = (int) $row['attendee_id'];
        // Single-row responses are not announced: fall back to one query.
        $serialized['myTier'] = $my_tiers[ $id ] ?? ( my_plugin_tiers_for( array( $id ) )[ $id ] ?? '' );
        return $serialized;
    },
    10,
    2
);

Notes

  • Two arguments. A callback that needs only the rows can keep the default of one.
  • A list page holds up to 200 rows and an export up to 10,000: a query in the per-row filter would run that many times.
  • Single-row responses (GET and PATCH /attendees/{id}, POST /attendees/{id}/date) do not fire it, so the filter still needs a fallback. Keep only the current response’s data.

happenboard_rest_attendee_response

Filter Free src/REST/Attendees.php

Filters one attendee as the REST API sends it to the Attendees screen and its exports. Use it to add your own columns.

Signature

apply_filters( 'happenboard_rest_attendee_response', array<string,mixed> $serialized, array<string,mixed> $row )

Parameters

$serialized array<string,mixed>
id, eventId, eventTitle, language, occurrenceId, occurrenceSeq, occurrenceStartUtc, occurrenceLabel, occurrenceStatus, bookedStartUtc, userId, email, displayName, status, quantity, customFields, createdUtc, updatedUtc.
$row array<string,mixed>
The raw database row, so you do not have to query it again.

Return value

array<string,mixed> The attendee with your keys added. It is cast with (array): always return the array.

Example

add_filter(
    'happenboard_rest_attendee_response',
    function ( array $serialized, array $row ): array {
        // Add the event's tier to each attendee.
        $serialized['myTier'] = (string) get_post_meta( (int) $row['event_id'], '_my_tier', true );
        return $serialized;
    },
    10,
    2
);

Notes

  • Two arguments: register with 10, 2.
  • Add keys; do not rebuild the array, or you drop HappenBoard’s fields and those of earlier callbacks (HappenBoard Pro adds checkinCount and lastCheckinUtc).
  • A key you add reaches the JSON export. The CSV export keeps its own columns (plus one cf: column per custom field) and the vCard export ignores extra keys.
  • It runs once per row: load your data on happenboard_rest_attendees_prefetch.

happenboard_pro_attendee_checked_in

Action Pro src/Service/Checkin/Repository.php

Fires after a check-in is recorded at the door: a scan on the check-in screen (POST /happenboard/v1/pro/checkin/mark) or Pro’s check-in-attendee ability. Use it to print a badge, notify a team or refresh a live list.

Signature

do_action( 'happenboard_pro_attendee_checked_in', int $checkin_id, int $attendee_id, int $event_id )

Parameters

$checkin_id int
ID of the check-in row just recorded (not the attendee ID).
$attendee_id int
The attendee who was scanned.
$event_id int
The event of the attendee’s registration (on a translated event, the translation they registered on).

Example

add_action(
    'happenboard_pro_attendee_checked_in',
    function ( int $checkin_id, int $attendee_id, int $event_id ): void {
        // Log every entry at the door.
        error_log( sprintf( 'Scan %d: attendee %d entered event %d.', $checkin_id, $attendee_id, $event_id ) );
    },
    10,
    3
);

Notes

  • Three arguments: register with 10, 3.
  • It fires for every recorded scan, re-scans included, each with a new check-in ID. Deduplicate if you want only the first entry.
  • A ticket turned away (no seat, another date or another event) fires happenboard_pro_attendee_checkin_refused, and an undone scan fires happenboard_pro_attendee_checkin_undone. Both are documented with the check-in hooks.

Next steps