Frozen public contracts reference

Summary

mam-main has explicit frozen public APIs. Customer mobile apps and ~2K enrolled customer sites depend on them. Internal abstractions wrap them, but their public-facing names and shapes do not change.

When in doubt: wrap, don’t rename.

This article catalogs every frozen contract in one place.


AJAX actions

Action Auth Subsystem Why frozen
local_app_get_phone_data both app-connect Primary mobile API — every deployed mobile client calls this name
mam_get_phone_data both app-connect Modern alias — already in field
mam_user_roles_cred_handler both user-roles Legacy login — older mobile clients call this name
mam_setcron_processor both setcron-manager FastCron pings this URL
local_app_get_data logged-in app-settings Generic admin read
local_app_save_file logged-in app-settings Generic admin save
local_app_save_plist_file logged-in app-settings iOS plist write
local_app_update_button_data logged-in app-settings Button blob update
local_app_update_image logged-in app-settings Image upload
local_app_resize_image logged-in app-settings Server-side resize
local_app_generate_launch_screen logged-in app-settings iOS launch-screen plist generator

⚠️ Endpoints prefixed local_app_* are public-contract names — mobile clients and admin JS depend on them. Internal handler renames are safe; action names are not.


Option keys

Option Owner Why frozen
local-app-account_code MAM_Account_Code_Manager Customer enrollment ID — ~2K sites have a value
local-app-button-array* app-settings Customer-defined button arrays — years of accumulated configs
local-app-onboarding-status setup-wizard Wizard progress tracker
local-app-ios-app-name publish-app iOS app name
local-app-ios-app-channel publish-app TestFlight channel routing
local-app-images-app-icon app-settings App icon asset
local-app-app-icon-bg app-settings App icon background
local-app-images-launch-screen-1 publish-app Launch screen 1
local-app-images-launch-screen-2 publish-app Launch screen 2
ios_pn_app_bundle_id publish-app iOS bundle id — predates mam_* rename; submitted to App Store
ios_pn_team_id publish-app Apple team id
ios_pn_key_id push-notification-manager APNs key id
ios_app_camera_message / ios_app_gps_message / ios_app_contacts_message publish-app Info.plist usage descriptions
android_pn_app_bundle_id publish-app Android package name — submitted to Play Store
mam_ios_version_number / mam_android_version_number publish-app App version
mam_ios_build_number / mam_android_build_number publish-app Build numbers (must increment per submission)
ios_app_google_plist publish-app Firebase config for iOS
ios_app_google_places_api publish-app Google Places API key
ios_app_launch_screen_bg publish-app Launch screen background

The local-app-* keys date to before the mam_* rename convention. Renames require a coordinated migration of every site.

The ios_* / android_* keys are tied to App Store / Play Store submissions — renaming risks orphaning customer apps.


Hooks (filters fired)

Hook Subscribers Why frozen
mam_get_phone_data_before_send ~70 Primary phone-data extension point
mam_local_app_data 0 (active) Short-circuit — contract preserved even with no current subscribers
mam_notification_send_message 1 (action) + 1 (legacy filter) Primary notification entry; legacy filter retained per SC #175
mam_notification_send_pn 1 Push channel hook
mam_notification_list 68+ Notification-type registry
mam_app_settings_get_setting 100+ call sites Settings cascade
mam_app_settings_set_setting many call sites Settings write
mam_app_settings_get_buttons many Per-role button definitions
mam_tab_manager ~43 Per-button enrichment
mam_main_add_tab_bar_item_{slug} per-button Dynamic tab-bar dispatch
mam_main_skip_tab_bar_button various Tab-bar visibility filter
mam_final_button_settings various Final per-button override
mam_cron_manager 25+ Cron registry
mam_main_check_initial_form various Form-state validation pass
mam_main_check_nonce various Nonce check pre-pipeline
mam_fastlane_settings per-plugin Publish payload extension
mam_user_logged_in various Post-login hook
mam_login_handler various Login phase hook
mam_user_roles_after_create_user various Post-registration hook
mam_user_roles_save_addl_user_profile_field_{key} per-field Per-field profile save
mam_add_fields_to_user_profile various Profile-field injection
mam_plugin_entitlement per-plugin Per-plugin licensing
mam_form_manager_get_forms_from_plugins per-plugin Custom form registration
mam_form_manager_process_field_type_{type} per-field-type Custom field-type translation
mam_form_manager_send_notifications various Form-to-notification bridge
mam_for_gravity_forms_form_result_form_{form-id} per-form Per-form result envelope
mam_for_gravity_forms_form_submitted_{form-id} per-form Per-form submission handler

DB tables

All 6 owned tables. Renamed from wp_tsl_* to wp_mam_* in PR #31, with backward-compat aliasing through MAM_Migration_Tasks::rename_table(). Renaming any of these in place would break every read against the old name — always use the migration framework.

Current name Owner repository Purpose
wp_mam_mail_queue MAM_Mail_Queue_Repository Outbound email queue
wp_mam_mail_attachments MAM_Mail_Attachments_Repository Email attachment storage
wp_mam_sms_queue MAM_Sms_Queue_Repository Unified PN+SMS queue
wp_mam_notification_history MAM_Notification_History_Repository In-app notification delivery log
wp_mam_phone_tokens MAM_Phone_Token_Repository Device registration tokens
wp_mam_debug_items MAM_Debug_Items_Repository Debug tracer storage

What “frozen” means in practice

You can… You cannot…
Refactor the implementation behind a frozen contract Rename the contract
Wrap a frozen option in a manager class (e.g., MAM_Account_Code_Manager) Move a frozen option to a custom DB table without migration
Add new fields to a frozen JSON shape (additive) Remove or rename existing fields
Add new hooks alongside frozen ones Rename or remove a frozen hook
Rename internal handler classes Rename the AJAX action they’re bound to
Rename a frozen DB table via MAM_Migration_Tasks::rename_table() with aliasing Rename a frozen DB table with ALTER TABLE directly

Migration framework

When a rename is unavoidable, use MAM_Migration_Tasks (includes/migrations/):

MAM_Migration_Tasks::register_option_alias( 'old-key', 'new-key' );
MAM_Migration_Tasks::register_option_renames( array(
    'old-key-1' => 'new-key-1',
    'old-key-2' => 'new-key-2',
) );
MAM_Migration_Tasks::rename_option( 'old', 'new' );
MAM_Migration_Tasks::rename_table( 'wp_old_table', 'wp_new_table' );

Aliases install pre_option / pre_update_option filter pairs so legacy callers (in unmaintained customer-site plugin copies) continue to read the old keys forever.


  • Plugin: mam-main
  • Architecture overview
  • Settings cascade overview
  • AJAX action: local_app_get_phone_data
  • Hook: mam_get_phone_data_before_send
  • Hook: mam_notification_send_message
  • Hook: mam_app_settings_get_setting

Metadata

Field Value
Article type JSON Key Reference
Plugin slug mam-main
Applies to plugin version 2.1.11+
Category App Settings Reference
Audience PHP developer
Last verified 2026-05-02
Contents

    Need Support?

    Can’t find the answer you’re looking for? Don’t worry we’re here to help!