Developer documentation

Orravo Core v2.3.0

The licensing and activation backbone every Orravo plugin needs. License validation, per-site activations, a unified suite shell with a Cmd+K command palette, REST API, and a Mini-Core fallback so paid plugins keep booting even when Core is not installed. Free forever.

WordPress plugin WP 6.0+ · PHP 7.4+ GPL-2.0+ v2.3.0 · stable
01 · Overview

What Orravo Core does

Orravo Core is the runtime that every other Orravo plugin talks to. It owns the license key, tracks per-site activations, ships shared admin chrome, and exposes a clean public API so each plugin can stay small and focused on its own job.

🔑
License client
Activate, deactivate, validate, transfer license keys against the orravo.com licensing API
📍
Per-site activations
Track which sites are using a seat. Dev-site mode for staging and local installs
🧭
Suite shell
Shared topbar, breadcrumb, notification bell, activity drawer across every Orravo plugin
Command palette
Press Cmd+K (or Ctrl+K) for instant filter-as-you-type access to every Orravo command
🔍
Auto-detect plugins
Discovers every installed Orravo product and registers it automatically
⬇️
Updater
Stable, beta, and nightly channels. One-click rollback to a previous plugin version
🔐
Mini-Core fallback
Plugins ship a 40-line shim so paid features keep working even without Core installed
🌐
REST API
Read license, products, system status. Manage webhooks and API keys over HTTPS
🔔
Notifications
Per-user inbox, dismissible. Plugins push items via orravo_notify()
📤
Outbound webhooks
HMAC-signed events to your CRM or analytics. Retry queue with exponential backoff
📦
Snapshots
Snapshot every Orravo plugin’s settings as one JSON blob. Roll back any time
⌨️
WP-CLI
Scriptable license, products, snapshots, doctor commands for CI and deploy hooks
02 · Installation

Get it running

Install Core like any standard WordPress plugin. It self-installs its database tables on activation and schedules its own cron events.

1
Download the latest orravo-core.zip from your Orravo account or from orravo.com/plugins/orravo-core.
2
In wp-admin, go to Plugins → Add New → Upload Plugin, choose the zip, install, and activate.
3
Open Orravo Core in the admin sidebar. Paste your license key into the License tab and click Activate. Core validates against orravo.com/api/licenses and caches the result for six hours.
4
Install your other Orravo plugins. Core auto-detects them and lists them in the Products tab. They start using your active license immediately.
If you do not have a paid Orravo plugin yet, you can still install Core. The License tab will sit empty and the rest of the suite shell, REST API, snapshots, and webhook tooling all work fine.
03 · Quick start

Five-minute setup

The fastest path to a fully wired Orravo install with one license key powering every paid plugin.

wp-cli# 1. Install Core
wp plugin install orravo-core --activate

# 2. Activate your license (one key covers every paid plugin in your tier)
wp orravo license activate ORV-9F3K-7T2X-RV4N-8KQ2

# 3. Install the paid plugins you bought, all at once
wp plugin install omailer oforms oads ofeedback --activate

# 4. Verify Core picked them all up
wp orravo product list
# omailer    3.3.2  stable  licensed
# oforms     1.2.0  stable  licensed
# oads       4.0.1  stable  licensed
# ofeedback  1.4.0  stable  licensed

# 5. Run doctor to confirm everything is healthy
wp orravo doctor
# tables ✓ · cron ✓ · license ✓ · 4/4 products active
04 · File structure

What ships in the zip

Orravo Core is a small plugin (~280KB unzipped). One bootstrap file, twelve include classes, one admin class, and a handful of view templates.

orravo-core/ ├── orravo-core.php # Bootstrap, constants, hook wiring ├── uninstall.php # Drops Orravo Core tables on uninstall ├── languages/ # Translation .pot + .mo files ├── includes/ │ ├── class-oc-db.php # Schema install + migrations │ ├── class-oc-license.php # License activate/validate/deactivate │ ├── class-oc-api.php # HTTP client for orravo.com licensing API │ ├── class-oc-helper.php # Public helper functions (orravo_is_licensed, etc.) │ ├── class-oc-updater.php # Channel-aware plugin updater + rollback │ ├── class-oc-notifications.php │ ├── class-oc-export.php # Settings export/import + snapshots │ ├── class-oc-webhooks.php # Outbound HMAC-signed webhooks + retry │ ├── class-oc-shell.php # Suite shell + command palette registry │ ├── class-oc-rest.php # REST routes (orravo-core/v1/*) │ ├── class-oc-queue.php # Background job queue (cron-driven) │ └── class-oc-cli.php # WP-CLI commands (loaded only under WP_CLI) └── admin/ ├── class-oc-admin.php # Menu, AJAX, asset enqueue ├── views/ # Tab templates (overview, license, etc.) └── assets/ # oc-admin.css + oc-admin.js
05 · Database tables

Seven tables, all prefixed

Core installs seven tables, all named {prefix}orravo_*. None of them touch wp_users, wp_posts, or any other Orravo plugin’s data.

TablePurposeTypical row count
orravo_licensesActive license payload (one row per active install)1
orravo_notificationsPer-user inbox items pushed by any Orravo plugintens to hundreds
orravo_snapshotsSettings snapshots for one-click rollbackup to ~20
orravo_activity_logRecent activity events. Auto-trims to last 500up to 500
orravo_webhooksConfigured outbound webhook endpoints0 to ~10
orravo_webhook_logDelivery log (status, latency, retries)per dispatch
orravo_api_keysScoped API keys for the REST API0 to ~10

In addition to the tables above, Core uses a small set of wp_options keys: orravo_license_key, orravo_license_cache, orravo_license_verification_log, orravo_grace_expires, orravo_mini_license_key, orravo_mini_license_data, and oc_db_version. Mini-Core options are mirrored so the fallback shim sees the same payload as the full Core.

06 · Admin interface

Six tabs, one menu

Core registers a single top-level wp-admin menu (orravo-core) with six tabs. Submenu links deep-link straight to a tab.

TabURLWhat it does
Overview?page=orravo-coreLicense health, detected products, recent activity
License?page=orravo-core&tab=licenseActivate / deactivate / refresh the license key
Products?page=orravo-core&tab=productsDetected Orravo plugins, version, channel, status
Tools?page=orravo-core&tab=toolsSettings export / import, snapshots, debug log
Developer?page=orravo-core&tab=developerAPI keys, webhooks, REST docs
System Status?page=orravo-core&tab=statusPHP, WP, cron, table integrity, last revalidation
07 · License model

One key, every plugin

A single license key covers every product in your purchase tier. The license payload is cached in orravo_license_cache for six hours; helper functions return from cache for fast, repeated checks.

Tiers
TierSitesProducts covered
single1 productionThe product you bought
studioup to 10 productionBundle: every plugin in the studio pack
unlimitedunlimitedEvery Orravo plugin, including future releases
Use orravo_tier_at_least('studio') in your own code to gate features that should only run for the studio or unlimited tier.
08 · Activations

Per-site seats

Every site that activates the license consumes one seat. Dev-site mode marks staging or local installs so they don’t use a production seat.

Toggle dev-site mode from the License tab or programmatically:

php// Mark this install as a dev/staging site (no production seat consumed)
update_option('oc_is_dev_site', true);

// Transfer the active license off this site (frees the seat)
OC_License::deactivate();
09 · Products

Auto-detected plugins

Core scans every installed plugin for the Orravo namespace marker (a known slug from OC_KNOWN_PRODUCTS) and registers any matches.

Currently recognised slugs:

SlugDisplay name
omailerOmailer
oformsOForms
oadsOAds
ofeedbackOFeedback
oforumOForum
ointelOIntel
omobileOMobile
onavONav
oonboardOOnboard
opwaoPWA
oengageOEngage
ocodeinsertOCodeInsert
oamazonOamazon
10 · Mini-Core fallback

Plugins keep working

Every paid Orravo plugin ships a 40-line PHP shim called Mini-Core. It reads the cached license payload from orravo_mini_license_data and answers the four helper functions even when the full Orravo Core is not installed.

mini-core.php// Drop into includes/mini-core.php in your plugin and require it from your bootstrap.
if (! function_exists('orravo_is_licensed')) {
    function orravo_is_licensed(string $slug): bool {
        $data = get_option('orravo_mini_license_data', []);
        if (empty($data)) return false;
        if (($data['status'] ?? '') !== 'active') return false;
        return in_array($slug, $data['products'] ?? [], true);
    }
}

if (! function_exists('orravo_license_status')) {
    function orravo_license_status(): string {
        $data = get_option('orravo_mini_license_data', []);
        return $data['status'] ?? 'inactive';
    }
}
Once the full Orravo Core is installed, it mirrors the same payload into orravo_mini_license_data, so the shim stays in sync. If Core is later deactivated, the shim still reads the cached state and your plugin keeps working.
11 · Updates & channels

Stable, beta, nightly

Core ships a custom updater that hooks into WordPress’s native plugin updates UI. Pick a release channel per plugin from the Tools tab.

  • stable the default. Releases tagged vX.Y.Z with no suffix.
  • beta early access (typically a release candidate). Releases tagged vX.Y.Z-beta.N.
  • nightly latest commit on main. Useful for bug fixes you need to confirm before a stable cuts.

Roll back to any previous version from the Products tab. Core keeps the last three versions of each plugin in wp-content/orravo-rollbacks/ for offline rollback.

12 · Snapshots & rollback

Capture everything

A snapshot bundles every Orravo plugin’s settings into one JSON blob. Restore in one click. Useful before plugin upgrades, demos, or staging-to-production handoffs.

php// Create a snapshot programmatically
OC_Export::snapshot('Pre Q2 release');

// List all snapshots
$rows = OC_Export::snapshots();
// [ ['id' => 1, 'name' => 'Pre Q2 release', 'created_at' => ...], ... ]

// Restore by id
OC_Export::restore_snapshot(1);
13 · Suite shell

Shared admin chrome

Every Orravo plugin opts into the same topbar: a unified breadcrumb, a notifications bell, an activity drawer, and the command palette trigger. Plugins drop in, the chrome stays consistent.

Register your screen with one line:

phpif (class_exists('OC_Shell')) {
    OC_Shell::register_screen('omailer', 'Omailer');
}

From that point on, your plugin’s admin pages render inside the suite shell, with a breadcrumb that says Orravo › Omailer › (current page).

14 · Command palette

Press Cmd+K

The palette is a filter-as-you-type list of every command registered by every Orravo plugin on the site. Hidden until you press ⌘K (or Ctrl+K on Windows). Default Core commands include Activate license, Refresh license status, Open System Status, and Create snapshot.

Add commands from your own plugin:

phpOC_Shell::register_commands([
    [
        'id'       => 'omailer.compose',
        'label'    => 'Omailer · Compose campaign',
        'section'  => 'Omailer',
        'href'     => admin_url('admin.php?page=omailer&view=compose'),
        'shortcut' => 'g c',
    ],
]);

// Or use the filter:
add_filter('orravo_command_palette_items', function (array $items) {
    $items[] = [ 'id' => 'studio.deploy', 'label' => 'Studio · Deploy', 'section' => 'Studio' ];
    return $items;
});
15 · Notifications & activity

Inbox + log

Two surfaces: a per-user notifications inbox (the bell icon) and a site-wide activity log (the drawer). Push items from any plugin.

php// Push a notification visible to all admin users
orravo_notify([
    'plugin'   => 'omailer',
    'level'    => 'info', // info | warning | success | error
    'title'    => 'Campaign sent',
    'message'  => 'April newsletter delivered to 4,820 subscribers',
    'link_url' => admin_url('admin.php?page=omailer&view=campaigns'),
]);

// Append to the activity log (no inbox, just an audit trail)
orravo_activity('omailer', 'Imported 318 subscribers from CSV', '/wp-admin/admin.php?page=omailer');
16 · Helper functions

Six functions cover most of it

Defined in includes/class-oc-helper.php. All are namespace-free and idempotent (function_exists guarded), so they work alongside the Mini-Core shim.

FunctionReturnsNotes
orravo_is_licensed($slug)boolTrue if active license covers the given product slug
orravo_license_data()?arrayFull cached payload (key, status, tier, products, sites, expiry)
orravo_license_status()stringactive | expired | invalid | inactive
orravo_license_tier()stringsingle | studio | unlimited
orravo_tier_at_least($tier)boolTier comparison (single < studio < unlimited)
orravo_is_staging()boolTrue if dev-site mode is on for this install
orravo_notify($data)intPush a notification, returns the notification id
orravo_activity($plugin, $msg, $link)voidAppend to the activity log
orravo_log($level, $message)voidWrite to the Orravo debug log when enabled
orravo_fire_event($event, $data)voidDispatch to any subscribed webhook endpoints
17 · OC_Shell API

Suite-shell facade

Use OC_Shell instead of reimplementing your own topbar, command palette, or breadcrumb. Idempotent (last write wins).

MethodSignature
register_screenOC_Shell::register_screen(string $plugin_slug, string $label)
register_commandOC_Shell::register_command(array $command)
register_commandsOC_Shell::register_commands(array $commands)
commandsOC_Shell::commands(): array (returns all registered, post-filter)

Command shape:

php[
    'id'       => 'unique.id',           // required, dot-namespaced
    'label'    => 'Visible label',       // required
    'section'  => 'Plugin name',         // groups commands in the palette
    'href'     => '/wp-admin/...',       // optional, navigate on enter
    'callback' => fn() => do_action(...) // optional, run on enter
    'icon'     => 'rocket',              // optional, icon slug
    'shortcut' => 'g c',                 // optional, e.g. 'g c' or 'cmd k'
]
18 · REST API

Namespace orravo-core/v1

Every route lives under /wp-json/orravo-core/v1/. Logged-in admins skip token auth so the wp-admin UI can call these directly. External callers send X-OC-API-Key.

MethodRouteReturns
GET/licenseActive license payload
GET/productsDetected Orravo plugins on this install
GET/system/statusPHP, WP, cron, table integrity, last revalidation
GET, POST, DELETE/webhooksList, create, remove webhook endpoints
GET, POST, DELETE/api-keysList, create, revoke scoped API keys
curl$ curl -H "X-OC-API-Key: oc_live_..." https://yoursite.com/wp-json/orravo-core/v1/license
{
  "key": "ORV-9F3K-7T2X-...",
  "status": "active",
  "tier": "studio",
  "products": ["omailer","oforms","oads","ofeedback"],
  "sites_used": 2,
  "sites_max": 10,
  "expires_at": 1762358400
}
19 · API keys

Scoped access

Create per-integration API keys with one of three scopes: read (GET only), write (PUT, POST, DELETE on owned resources), admin (full surface). Hashes are stored, never the raw key.

Generate from the Developer tab or via WP-CLI:

wp-cli$ wp orravo api-key create "CRM integration" --scopes=read,write
oc_live_8K3F2X9TJ7RV4N8KQ2HF1...
20 · Webhooks

HMAC-signed events

Outbound webhooks fire on suite-wide events (license_renewed, product_updated, snapshot_created, plus anything plugins push via orravo_fire_event()). Each dispatch is HMAC-SHA256 signed with the endpoint secret, headered as X-OC-Signature.

Verify on your end:

php$payload   = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_OC_SIGNATURE'] ?? '';
$secret    = getenv('OC_WEBHOOK_SECRET');

if (! hash_equals(hash_hmac('sha256', $payload, $secret), $signature)) {
    http_response_code(401);
    exit;
}

$event = json_decode($payload, true);
// $event['type']  e.g. 'license_renewed'
// $event['site']  the originating site URL
// $event['data']  payload specific to the event

Failed dispatches are queued (table orravo_webhook_log) and retried via the orravo_webhook_retry cron with exponential backoff up to five attempts.

21 · Hooks & filters

Extension points

HookTypeNotes
orravo_command_palette_itemsfilterAdd custom palette commands suite-wide
orravo_command_itemsfilterLegacy alias kept for back-compat
orravo_license_activatedactionFires after a successful license activation
orravo_license_deactivatedactionFires after deactivation
orravo_license_revalidatedactionDaily cron, after the license payload refreshes
orravo_webhook_retryactionCron target for failed dispatch retries
orravo_core_revalidateactionDaily cron tick (revalidates the license)
orravo_core_update_checkactionTwice-daily cron (refreshes update channels)
22 · WP-CLI

Scriptable everything

Loaded only under WP-CLI. Useful from CI, deploy hooks, and one-shot maintenance.

wp-cli$ wp orravo license activate ORV-9F3K-7T2X-RV4N-8KQ2
license activated · studio tier · 4 products · expires 2027-04-18

$ wp orravo license status
active · studio · sites 2/10 · last validated 4h ago

$ wp orravo product list
omailer    3.3.2  stable  licensed
oforms     1.2.0  stable  licensed
ofeedback  1.4.0  stable  licensed

$ wp orravo snapshot create "Pre release"
snapshot #4 created

$ wp orravo doctor
tables ✓ · cron ✓ · license ✓ · 4/4 products active
23 · Comparison

vs. the alternatives

FreemiusEDD Software LicensingCustom-builtOrravo Core
License key validationpaid tier$199 yrmanual
Per-site activation tracking$199 yrmanual
Auto-detect installed productsnonono
Unified suite shell + Cmd+K palettenonono
REST API + WP-CLI + scoped API keyspaid tiermanual
Snapshots + rollbacknonono
Mini-Core fallback (works without Core)nonono
Pricing$99 + 20% rev share$199 yrtime + riskFree forever
24 · Pricing

Free. Forever.

Orravo Core is the licensing client itself. Charging for it would mean charging twice for the same plugin. Premium plugins fund the work.

25 · Changelog

Recent releases

v2.3.0
current · stable
  • Self-healing license table on version mismatch (Audit P0-002)
  • System Status surfaces stale-cron warnings via orravo_core_revalidate_last_run
  • Sibling plugins merge into the palette via orravo_command_palette_items (Audit P1-007 / F6)
  • De-duplicated submenu entries; one submenu per tab (Audit P0-004)
v2.2.0
previous
  • Added scoped API keys with per-key revocation
  • Outbound webhooks moved to a queued retry model (exponential backoff)
  • Snapshots now bundle every Orravo plugin’s settings, not just Core
v2.1.0
previous
  • Cmd+K command palette ships across the entire suite
  • OC_Shell facade introduced for screen and command registration
  • Mini-Core fallback shim documented and adopted by every paid plugin
// install once

Power the whole Orravo suite.

One install, one set of tables, one shared admin chrome. Every other Orravo plugin gets thinner because of it.