Skip to content

Developer Overview

PrimoCRM is built to be extended. This section documents the public hooks, the REST API, and the registries you use to add functionality without editing core.

  • Admin UI: a React single-page app that talks to PHP REST controllers. There is one admin page with client-side routing.
  • REST controllers: each module registers its routes under the primocrm/v1 namespace on rest_api_init. See REST API.
  • Background engine: all long-running work (campaign sends, sequence drips, automation steps, imports) runs through self-rescheduling, time-budgeted cron workers, never in the page request. When you add anything that hits an external API or processes many rows, follow the same queue pattern rather than a blocking call.
  • Registries and filters: triggers, actions, form fields, migration sources, and email senders are all collected through WordPress filters, so add-ons register into them with zero core edits. See Extending PrimoCRM.

PrimoCRM ships as two plugins. The Free plugin is the whole CRM and works standalone. The Pro add-on defines a constant that unlocks premium capabilities and registers additional triggers, actions, and senders through the same public filters your own code would use.

Because Pro uses the public extension points, the patterns in this section are exactly how first-party Pro features are built. If Pro can add a WooCommerce trigger through primocrm_automation_triggers, so can you.

  • Contacts carry standard fields plus custom fields stored as contact meta, and a status that controls mailability.
  • Lists and tags group contacts through pivot tables.
  • Campaigns, sequences, and automations each own their tables and are driven by the background engine.

Custom-field values are readable in emails as {{contact.meta.KEY}} and writable by automations, which is the seam the Pro AI action uses. See Personalization and Smart Codes.

  • Namespacing: prefix your hooks, options, and keys so they do not collide. PrimoCRM uses the primocrm_ prefix for PHP hooks and primocrm/v1 for REST.
  • Capabilities: REST endpoints check a capability in their permission callback. Respect the same model in anything you add.
  • Fail closed: anything not on the Free allowlist is treated as Pro. If you register a new trigger or action, decide deliberately whether it should be free by filtering primocrm_free_triggers or primocrm_free_actions.