Send Emails is built to be extended: PSR-4 classes under the SendEmails namespace, custom indexed tables for all data (nothing in wp_posts/wp_postmeta), a REST API that the admin itself runs on, and hooks at every meaningful point. The Send Emails Pro add-on is built entirely on the extension points below — anything Pro can do, your code can too.
Sending emails programmatically
sende_send_email( array(
'to' => 'someone@example.com',
'subject' => 'Hello from code',
'message' => '<p>HTML body</p>',
) );
Every send — yours, compose, campaigns, automations — flows through one mailer, gets logged, and respects the tracking settings.
Email filters
Modify any outgoing email just before it sends:
| Filter | Filters |
|---|---|
sende_email_to | Recipient address(es) |
sende_email_subject | Subject line |
sende_email_body | Body content |
sende_email_headers | Header array |
sende_email_attachments | Attachments array |
After the result is logged, sende_email_sent or sende_email_failed fires with the log model. The pre-2.6 sendemails_email_*, sendemails_merge_tags and sendemails_form_submitted hook names still fire but are deprecated since 2.6.0.
Merge tags
Add custom tags via sende_merge_tags — see the example on the Merge Tags page. Related: sende_unsubscribe_footer filters the auto-appended footer.
Model lifecycle hooks
Every entity (contact, tag, email, campaign, automation) fires lifecycle actions:
sende_pre_insert_{type}/sende_inserted_{type}sende_pre_update_{type}/sende_updated_{type}sende_pre_delete_{type}/sende_deleted_{type}- Status transition hooks such as
sende_contact_status_transition— the automation engine itself listens to these, e.g. for the contact subscribed trigger.
add_action( 'sende_inserted_contact', function ( $contact ) {
error_log( 'New contact: ' . $contact->email );
} );
Form integrations
sende_form_submitted— action fired for every captured form submission (contact, mapped data, integration).sende_form_integrations— register your own integration class for an unsupported form plugin; extend the abstractFormIntegration, which provides field auto-mapping, opt-in handling, dedupe-by-email, and tag assignment for free.
Automations & commerce
sende_automation_triggers— register custom automation triggers.sende_fire_automation_trigger— fire a trigger from your own code (this is exactly how Pro’s birthday trigger works).sende_purchase— fired by the WooCommerce/EDD integrations on paid orders;sende_attribution_windowfilters the revenue-attribution window (default 7 days).sende_queue_batch_size— campaign queue batch size per cron tick.
Admin & settings extension points
These are the seams the Pro plugin plugs into:
- PHP:
sende_rest_controllers(add REST controllers tosende/v1),sende_settings_fields(register settings keys + sanitizers),sende_admin_app_data(extend the React app’s boot data),sende_admin_screen_ids,sende_manager_capability(change the required capability), and thesend_emails_initaction. - JS:
sende.admin.pages(register admin app pages),sende.admin.settingsPanels(add settings panels),sende.admin.contactFormFields(inject contact form fields) — all via@wordpress/hooks.
Settings are read with sende_get_settings( $key, $default ).
REST API
Namespace: sende/v1. The React admin uses these endpoints exclusively, so they’re first-class and stable. Authenticated routes require the manager capability (cookie + nonce, or application passwords):
| Route | Purpose |
|---|---|
/sende/v1/contacts | Contacts CRUD, search/filter/pagination, bulk delete, CSV import/export endpoints |
/sende/v1/tags | Tags CRUD |
/sende/v1/campaigns | Campaigns CRUD + send/test/pause/resume/recipient-count |
/sende/v1/emails | Send, logs collection/detail, resend, delete, /emails/stats |
/sende/v1/settings | Read/update settings |
/sende/v1/track/open/{token} | Public — open-tracking pixel |
/sende/v1/track/click/{token} | Public — signed click redirect |
/sende/v1/unsubscribe/{uuid} | Public — unsubscribe page (GET) and RFC 8058 one-click (POST) |
curl -u user:app-password "https://example.com/wp-json/sende/v1/contacts?per_page=10&status=subscribed"
Data storage
Tables (all with the WordPress prefix): sende_contacts, sende_contactmeta, sende_tags, sende_contact_tags, sende_emails, sende_emailmeta, sende_campaigns, sende_automations, sende_automation_runs. Settings live in the sende_settings option. Prefer the models/REST API over raw SQL — the model layer maintains its own object cache.