A REST API and hooks built to be extended, not forked.
A versioned REST API with a real permission model, signed webhooks on a retrying queue, 40 hooks at the moments that matter, WP-CLI, server-rendered blocks and the same Addon SDK all 35 Pro add-ons are written on.
Two namespaces, one permission model.
Every route declares a permission callback. Store data uses two capabilities — ambikly_manage_store and ambikly_view_store — carried by the Store Manager and Support Agent roles; only settings, gateway credentials, webhooks, import/export and system status need manage_options. Responses use a { success, data } envelope with page / per_page / total pagination; errors are standard WP_Error objects with an HTTP status.
- Products, attributes, variations, categories, tags, brands
- Orders, statuses, notes, refunds, invoices, packing slips
- Customers, addresses, B2B companies with credit limits and buyers
- Cart, checkout, shipping, tax, coupons, reviews, reports, downloads
- Pro: add-ons, license, plus every add-on’s own routes
# list the 25 most recent orders
curl -u editor:xxxx-xxxx-xxxx-xxxx \
"https://store.example.com/wp-json/ambikly/v1/orders?per_page=25"
# transition an order; fires ambikly_order_status_changed
curl -u editor:xxxx-xxxx-xxxx-xxxx -X POST \
-d status=completed \
"https://store.example.com/wp-json/ambikly/v1/orders/10944/status"Signed, retried, logged.
Nine events fire signed POSTs to any http(s) endpoint. Delivery runs through the durable job queue: eight attempts with exponential backoff (1m, 5m, 30m, 2h, 6h, then daily), the last 200 attempts kept per webhook with status, duration and error, and a synchronous test-fire from the admin. Outbound requests go through wp_safe_remote_post.
- order.created · order.paid · order.status_changed · order.refunded
- checkout.completed · review.submitted
- subscription.renewed · subscription.cancelled · subscription.renewal_failed
- X-Ambikly-Signature: sha256= · X-Ambikly-Event:
- Secret shown once at creation; masked on every later read
$body = file_get_contents( 'php://input' );
$sig = $_SERVER['HTTP_X_AMBIKLY_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac( 'sha256', $body, WEBHOOK_SECRET );
if ( ! hash_equals( $expected, $sig ) ) {
http_response_code( 401 );
exit;
}
$event = $_SERVER['HTTP_X_AMBIKLY_EVENT']; // e.g. order.paid
$data = json_decode( $body, true );The class all 35 add-ons extend is the one you get.
Subclass Addon, set five properties, implement boot(). Settings are declared as a schema array and stored as JSON; fields typed secret or password are masked before they ever leave the server. activate() and uninstall() give you a place for tables and migrations, and a lapsed license simply skips boot() — settings and data are never touched.
- Auto-discovered from addons//Addon.php, or registered via the ambikly_pro_addons filter
- Settings schema with automatic secret masking
- Shared durable job queue: enqueue a job, handle ambikly_job_{type}, throw to retry
- Templates overridable at {theme}/ambikly/…; account tabs via ambikly_account_tabs
namespace AmbiklyPro\Addons\MyFeature;
use AmbiklyPro\Addon\Addon as BaseAddon;
class Addon extends BaseAddon
{
public function __construct()
{
$this->slug = 'my-feature';
$this->name = 'My Feature';
$this->description = 'Does one thing well.';
$this->category = 'marketing';
$this->version = '1.0.0';
}
public function boot(): void
{
add_action( 'ambikly_order_paid', [ $this, 'onPaid' ] );
}
}The hooks you will actually use.
A selection of the 40 actions and filters. Dynamic names take the event, audience or job type in braces.
| Hook | Type | Fires / filters |
|---|---|---|
| ambikly_order_created | action | After an order and its items are persisted — Order $order |
| ambikly_order_paid | action | When an order is settled as paid; triggers fulfillment, stock and emails |
| ambikly_order_status_changed | action | Every status transition — Order, $old, $new |
| ambikly_order_refunded | action | After a full or partial refund — Order, Refund |
| ambikly_checkout_completed | action | End of a successful checkout — Order, PaymentResult|null |
| ambikly_download_served | action | After a download token is redeemed |
| ambikly_account_tab_{tab} | action | Render the body of an account tab you added |
| ambikly_job_{type} | action | Handle a claimed job; throw to trigger backoff retry |
| ambikly_payment_gateways | filter | Register a custom gateway |
| ambikly_cart_totals | filter | Adjust totals — where gift cards, credit, points and pricing hook in |
| ambikly_shipping_rates | filter | Add or change shipping rates for a context |
| ambikly_stock_shortfalls | filter | Extend checkout stock validation |
| ambikly_product_on_sale | filter | Decide whether a product is on sale |
| ambikly_product_card_actions | filter | Add buttons to product cards (wishlist, quick view…) |
| ambikly_account_tabs | filter | Add a tab to the customer account |
| ambikly_locate_template | filter | Final override point for any template path |
| ambikly_{event}_subject_to_{audience} | filter | Email subject per event and audience |
| ambikly_invoice_pdf_renderer | filter | Plug in Dompdf / mPDF for real PDF invoices |
| ambikly_pro_addons | filter | Register a third-party add-on class |
| ambikly_review_auto_approve | filter | Skip moderation for a review |
Seven gateways, one abstract class.
PaymentGateway::process() is required; refund(), chargeRenewal() and chargeAdditional() are optional and drive refunds, subscription renewals and post-purchase upsells. When a cart holds a subscription, gateways without chargeRenewal() are filtered out of checkout.
| Gateway | Refunds | Renewals | Extra charges | Notes |
|---|---|---|---|---|
| Stripe | ✓ | ✓ | ✓ | Signature-verified webhook; Idempotency-Key on every off-session charge |
| PayPal | ✓ | — | — | Orders v2; return + webhook endpoints verified server-side |
| Net Terms | ✓ | — | — | Atomic credit reservation for B2B companies; settle via record-payment |
| Manual | ✓ | — | — | Staff-only at checkout |
| Cash on Delivery | — | — | — | Offline settlement |
| Bank Transfer | — | — | — | Order held pending |
| Check | — | — | — | Offline settlement |
Exports and maintenance from the terminal.
| Command | What it does |
|---|---|
| wp ambikly export products [--status=] [--type=] [--file=path.csv] | Stream the 32-column products CSV |
| wp ambikly export orders [--status=] [--from=YYYY-MM-DD] [--to=YYYY-MM-DD] [--file=path.csv] | Stream the 31-column orders CSV |
| wp ambikly recompute customer-totals [--id=123] | Rebuild cached customer totals |
| wp ambikly upgrade-db | Run pending schema migrations |
Blocks, shortcodes and theme overrides.
Eight API-v2 Gutenberg blocks are rendered in PHP for SEO and theme compatibility, with progressive enhancement on top. Every block has a shortcode twin. Templates resolve from {theme}/ambikly/ before the plugin’s own, wrapped in before/after actions, and the customer account is a single page with tabs you can extend.
- ambikly/product-grid · featured-product · add-to-cart · mini-cart
- ambikly/cart · checkout · customer-account · reviews
- [ambikly_shop] [ambikly_product] [ambikly_cart] [ambikly_checkout] [ambikly_account] [ambikly_thank_you] [ambikly_search] [ambikly_archive]
- Account tabs: dashboard, orders, downloads, addresses, profile — plus any you add
add_filter( 'ambikly_account_tabs', function ( $tabs ) {
$tabs['rewards'] = __( 'Rewards', 'my-theme' );
return $tabs;
} );
add_action( 'ambikly_account_tab_rewards', function ( $customer ) {
echo '<h2>Your rewards</h2>';
// render anything
} );What it needs, what it creates, what it removes.
| Topic | Detail |
|---|---|
| Requirements | WordPress 5.4+, PHP 7.4+. Pro requires the free core. No build step; vendor/ is production-only. |
| Database | 38 core tables under {prefix}ambikly_*, versioned by ambikly_db_version and migrated automatically on admin load or via wp ambikly upgrade-db. Add-ons create their own tables in activate(). |
| Privacy | Registers WordPress personal-data exporters and erasers for customer records and orders, so Tools → Export / Erase Personal Data covers store data. |
| Uninstall | Nothing is deleted unless the shared opt-in option ambikly_remove_data_on_uninstall is true; then tables, options, roles and transients are removed. Pro drops any ambikly_* table the core does not claim. |
| Logging | Failures go to PHP error_log with an Ambikly prefix; operator surfaces are REST resources — /jobs/status, /jobs/failed, /webhooks/{id}/deliveries, /system/status. |
| i18n | Text domains ambikly and ambikly-pro, loaded on init. |
Developer questions.
How do I authenticate against the REST API from outside WordPress?
Use any standard WordPress REST authentication — Application Passwords work out of the box, because every route’s permission callback is a plain current_user_can() check. Browser clients use cookie auth with the wp_rest nonce in X-WP-Nonce. There is no separate API-key scheme to manage.
Can a non-admin use the API?
Yes. Ambikly defines two capabilities — ambikly_manage_store and ambikly_view_store — and two roles, Store Manager and Support Agent. Only settings, gateway credentials, webhooks, import/export, email templates and system status require manage_options.
How do I verify a webhook?
Compute HMAC-SHA256 of the raw request body with the webhook secret and compare it, constant-time, to the X-Ambikly-Signature header (format sha256=). The event name is in X-Ambikly-Event. The secret is shown once when the webhook is created.
Can I write my own add-on?
Yes. Subclass AmbiklyPro\Addon\Addon, set its properties, implement boot(), and register it through the ambikly_pro_addons filter (or drop it into addons/ for auto-discovery). Settings are a schema array; secret-typed fields are masked automatically.
Can I add a payment gateway?
Implement Ambikly\Payments\PaymentGateway — process() is required; refund(), chargeRenewal() and chargeAdditional() are optional — and register it with the ambikly_payment_gateways filter. It appears at checkout once isAvailable() returns true.
What are the requirements?
WordPress 5.4+ and PHP 7.4+. No build step: the shipped vendor/ is production-only and there is nothing to compile. Ambikly Pro requires the free core.
Read the source. It is the documentation of record.
Both plugins are GPLv3 with readable, unobfuscated code and a DEVELOPER.md in each repository.