Extending the plugin

The plugin exposes several hooks that allow you to add/modify functionality through WordPress filters. This page lists the available filters and provides example code for some common use cases.

List of available filter hooks

Placeholders

Some hooks contain placeholder {{doctype}}, the value of which is either invoice or estimate, depending on the type of Moneybird document that is being generated. Document type estimate is only available in version 4.0 and newer.

  • woocommerce_moneybird_combined_invoice_order_heading

    Filter the order heading text on combined invoices (i.e. invoices with multiple orders).
    Default is "*Order {{order_id}}*". The heading is skipped if the filter returns an empty string.
    -
    Plugin versions:    5.6.0 and newer
    Filtered object:    String containing the heading text.
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_contact_details

    Filter array containing the contact details of a given order. 
    These contact details are used to search for a match in the Moneybird contacts, 
    or to create a new Moneybird contact.
    -
    Plugin versions:    3.5.0 and newer
    Filtered object:    Array containing the contact details
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_contact_updatable

    Filter a boolean indicating whether a given existing Moneybird contact may be updated.
    -
    Plugin versions:    3.51.0 and newer
    Filtered object:    Boolean indicating update permission
    Arguments:          (1) Moneybird contact object
    
  • woocommerce_moneybird_credit_invoice

    Filter the credit invoice object before it is pushed to Moneybird.
    -
    Plugin versions:    3.0.0 and newer
    Filtered object:    Array containing the complete credit invoice object
    Arguments:          (1) WC_Order: refund object, (2) WC_Order: original order
    
  • woocommerce_moneybird_custom_field_value

    Filter the value of a custom field.
    -
    Plugin versions:    3.20.0 and newer
    Filtered object:    Value of the custom field for the corresponding WC_Order.
    Arguments:          (1) string: custom field key, (2) int: order id
    
  • woocommerce_moneybird_custom_fields

    Filter the array of available custom field keys.
    -
    Plugin versions:    3.20.0 and newer
    Filtered object:    Array containing the available custom field keys.
    Arguments:          None
    
  • woocommerce_moneybird_{{doctype}}

    Filter the sales invoice or estimate object before it is submitted to Moneybird.
    -
    Plugin versions:    2.1.2 and newer
    Filtered object:    Array containing the complete invoice/estimate object
    Arguments:          (1) WC_Order, (2) Array of secondary WC_Orders (in case of combined invoice)
    
  • woocommerce_moneybird_invoice_coupons

    Filter invoice lines corresponding to coupon redemptions.
    -
    Plugin versions:    3.56 and newer
    Filtered object:    Array of invoice lines (see source for details)
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_invoice_item

    Filter item details that are put on the Moneybird invoice.
    Return an empty array to skip the item.
    -
    Plugin versions:    2.5 and newer
    Filtered object:    Array of invoice lines (see source for details)
    Arguments:          (1) WC_Order_Item, (2) WC_Order
    
  • woocommerce_moneybird_invoice_shipping

    Filter invoice lines corresponding to shipping costs.
    -
    Plugin versions:    2.5 and newer
    Filtered object:    Array of invoice lines (see source for details)
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_invoice_fees

    Filter invoice lines corresponding to ordering fees.
    -
    Plugin versions:    2.5 and newer
    Filtered object:    Array of invoice lines (see source for details)
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_invoice_gift_cards

    Filter invoice lines corresponding to gift card redemptions.
    -
    Plugin versions:    3.49 and newer
    Filtered object:    Array of invoice lines (see source for details)
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_invoice_payments

    Filter the array of invoice payments that are submitted to Moneybird for a given WC_Order.
    -
    Plugin versions:    5.8.0 and newer
    Filtered object:    Array of payment data arrays.
    Arguments:          (1) WC_Order, (2) Moneybird invoice object.
    
  • woocommerce_moneybird_{{doctype}}_send_parameters

    Filter the parameters of the Moneybird API request to send an invoice or estimate.
    -
    Plugin versions:    3.48.0 and newer
    Filtered object:    Array containing the API request parameters
    Arguments:          (1) WC_Order, (2) Moneybird invoice/estimate object
    
  • woocommerce_moneybird_{{doctype}}_sequence_id

    Filter the `{id}` part of the invoice/estimate number, usually in format `{year}-{id}`. 
    The default is empty, causing Moneybird to automatically generate the sequence id upon sending.
    -
    Plugin versions:    2.1.1 and newer
    Filtered object:    incremental part of the invoice/estimate id
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_is_order_paid

    Filter the payment status of an order.
    By default, an order is considered paid if the status is "processing" or "complete",
    and a payment method has been associated with the order.
    -
    Plugin versions:    2.5 and newer
    Filtered object:    Boolean indicating the payment status
    Arguments:          (1) WC_Order, (2) Array of secondary WC_Orders (in case of combined invoice)
    
  • woocommerce_moneybird_new_contact

    Filter array containing the fields for a new Moneybird contact.
    Use this filter to add any additional fields, such as `tax_number`.
    -
    Plugin versions:    2.1.1 and newer
    Filtered object:    Array containing the contact details
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_process_order

    Filter a boolean indicating whether the specified order should be
    processed. Returning false allows one to suppress Moneybird contact and
    invoice generation.
    -
    Plugin versions:    3.34.0 and newer
    Filtered object:    Boolean indicating whether order should be processed (default: true).
    Arguments:          (1) WC_Order, (2) string: either 'invoice' or 'estimate'
    
  • woocommerce_moneybird_reference

    Filter the value of the reference field on the invoice.
    -
    Plugin versions:    2.1.1 and newer
    Filtered object:    Value of the invoice reference string, for example "order #{{order_id}}"
    Arguments:          (1) WC_Order, (2) Array of secondary WC_Orders (in case of combined invoice)
    
  • woocommerce_moneybird_register_payment

    Filter a boolean indicating whether to register a payment in Moneybird.
    Use this filter to overwrite the payment registration setting for individual orders.
    -
    Plugin versions:    2.1.2 and newer
    Filtered object:    Boolean indicating if the order payment should be registered in Moneybird
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_revenue_ledger_accounts

    Filter the array of available Moneybird revenue ledger accounts.
    The keys of the associative array start with 's', followed by the id of the ledger account.
    The values contain the ledger names.
    -
    Plugin versions:    3.16.0 and newer
    Filtered object:    Associative array containing the available Moneybird ledger accounts.
    Arguments:          (1) Array: in format s{id} => {ledger_name}.
    
  • woocommerce_moneybird_payment_amount

    Filter the payment amount.
    The default payment amount is equal to the open balance of the invoice (to prevent rounding errors).
    -
    Plugin versions:    2.7 and newer
    Filtered object:    Float: payment amount in the store's default currency
    Arguments:          (1) WC_Order
    
  • woocommerce_moneybird_prices_include_tax

    Filter a boolean indicating whether the prices on the Moneybird document should be specified inclusive of tax.
    The default is to follow the WooCommerce setting for specifying prices inclusive/exclusive of tax. 
    Deviating from this can lead to rounding errors.
    -
    Plugin versions:    3.54.0 and newer
    Filtered object:    Boolean indicating whether prices should be specified inclusive of tax.
    Arguments:          (1) WC_Order, (2) Array of secondary WC_Orders (in case of combined invoice)
    
  • woocommerce_moneybird_sendmode

    Filter the invoice sending mode.
    -
    Plugin versions:    3.3.0 and newer
    Filtered object:    String with possible values: 'draft', 'default', 'Manual', 'Email' or 'Simplerinvoicing'.
    Arguments:          (1) WC_Order, (2) Moneybird document (invoice or estimate).
    

List of available action hooks

  • woocommerce_moneybird_after_{{doctype}}_generate

    This action is executed after a Moneybird invoice or estimate has been generated.
    -
    Plugin versions:    3.44.0 and newer
    Arguments:          (1) WC_Order instance, (2) Moneybird invoice or estimate object, (3) Array of secondary WC_Orders (in case of combined invoice)
    
  • woocommerce_moneybird_generate_{{doctype}}_error

    This action is executed if an error occurs during Moneybird document generation.
    It can be used for example to send a notification to the admin.
    -
    Plugin versions:    3.1.3 and newer
    Arguments:          (1) WC_Order instance, (2) string: description of the error
    
  • woocommerce_moneybird_webhook

    ```txt This action is executed if the webhook is called by Moneybird. A list of all possible events that can trigger a webhook is available here: https://developer.moneybird.com/webhooks/#events

The plugin registers a webhook for the following events: administration_removed, administration_suspended, document_style_destroyed, ledger_account_deactivated, ledger_account_destroyed, project_archived, project_destroyed, sales_invoice_destroyed, sales_invoice_merged, sales_invoice_state_changed_to_paid, tax_rate_deactivated,

tax_rate_destroyed, workflow_deactivated, workflow_destroyed.

Plugin versions: 5.5.0 and newer Arguments: (1) object: webhook payload, (2) WC_MoneyBird2 instance ```

  • woocommerce_moneybird_webhook_{{event}}

    Same as woocommerce_moneybird_webhook but with the event code included.
    -
    Plugin versions:    5.5.0 and newer
    Arguments:          (1) object: webhook payload, (2) WC_MoneyBird2 instance
    

Access invoice from front-end

If you want to provide customers with a link to their invoice(s) you can use the following code to access the invoice linked to a WooCommerce order:

$moneybird = WCMB(); // This loads the registered WC_MoneyBird2 instance
$invoice = $moneybird->get_invoice_from_order_id($order_id);
if ($invoice) {
    var_dump($invoice); // Replace this with code to output info about the invoice
}

Add VAT number to Moneybird contacts

Support for the EU VAT numbers plugin is built-in since v2.5.9. The plugin checks the following order meta fields for a VAT number: _vat_number, vat_number, _billing_vat_number. If one of these fields contains a VAT number, it is automatically passed to Moneybird. Almost all EU VAT plugins store the VAT number in one of the mentioned fields, so it should work out-of-the-box. However, some custom code might be required to pass VAT numbers to Moneybird if you use another plugin to collect the VAT number.

You can add a piece of code to functions.php such that the VAT numbers of customers get passed on to Moneybird. Modify the code below to read the VAT number from the correct location (depends on the plugin used for collecting the VAT number). It is also possible the pass the Chamber of Commerce registration (“KvK nummer” in Dutch) to Moneybird (see the commented line in the example code).

function filter_woocommerce_moneybird_new_contact($contact, $order) {
    // Add VAT number from "EU VAT Number" plugin to Moneybird contact
    $order_id = is_callable(array($order, 'get_id')) ? $order->get_id() : $order->id;
    $vat_number = get_post_meta($order_id, '_vat_number', true); // Modify to read the correct field
    if ($vat_number) {
        $contact['tax_number'] = $vat_number;
    }
    // $contact['chamber_of_commerce'] = 'FILL THIS FIELD IF NEEDED';

    return $contact;
}

add_filter('woocommerce_moneybird_new_contact', 'filter_woocommerce_moneybird_new_contact', 10, 2);

Example: order-dependent invoice workflow

Edit and paste the following code snippet in functions.php to make the workflow of the invoice dependent on the properties of the WooCommerce order. For example, we can use a different workflow for orders in the German language:

// The following filter modifies the invoice workflow based on the WooCommerce order.
// $order contains the WC_Order instance corresponding to the order for which the invoice is being generated.

function filter_woocommerce_moneybird_modify_workflow($invoice, $order) {
    // Use the $order object here to look up the required information
    $order_id = is_callable(array($order, 'get_id')) ? $order->get_id() : $order->id;
    $language = get_post_meta($order_id, 'wpml_language', true);

    if ($language == 'de') {
        // Note: the workflow id can be extracted from the url when editing it in Moneybird.
        $invoice['workflow_id'] = '136261670020318887';
    }

    return $invoice;
}

add_filter('woocommerce_moneybird_invoice', 'filter_woocommerce_moneybird_modify_workflow', 10, 2);

Example: ignore non-virtual products when generating invoices

The code snippet below provides an example of how to filter order items when generating an invoice.

function mb_invoice_item_filter($item, $wc_order_item, $wc_order) {
    // Ignore non-virtual products when generating invoices

    $product = apply_filters('woocommerce_order_item_product', $wc_order->get_product_from_item($wc_order_item), $wc_order_item);
    if (!$product->is_virtual()) {
        $item = array();
    }

    return $item;
}
add_filter('woocommerce_moneybird_invoice_item', 'mb_invoice_item_filter', 10, 3);

Example: add Subscription properties as custom fields

If you use WooCommerce Subscriptions, you might want to make certain properties of subscriptions available as custom fields, so they can be mapped to custom invoice/contact fields (“Extra Velden”) in Moneybird. The following example code illustrates how this can be achieved.

function insert_subscription_custom_fields($custom_fields) {
    // Add user-defined custom field keys to the list of available custom fields.
    $custom_fields[] = 'subscription_start_date';
    return $custom_fields;
}

add_filter('woocommerce_moneybird_custom_fields', 'insert_subscription_custom_fields', 10, 1);

function resolve_subscription_custom_field_values($val, $key, $order_id) {
    // Resolve the value of all user-defined custom fields (as specified in `insert_subscription_custom_fields`).
    if (!in_array($key, array('subscription_start_date'))) {
        // We don't have to resolve this custom field
        return $val;
    }

    // Get subscriptions associated with the order
    $subscriptions = wcs_get_subscriptions_for_order($order_id);
    if (!$subscriptions) {
        $subscriptions = wcs_get_subscriptions_for_renewal_order($order_id);
    }

    if ($subscriptions) {
        if ($key == 'subscription_start_date') {
            foreach ($subscriptions as $subscription) {
                $start_date = $subscription->get_time('date_created');
                if ($start_date) {
                    $val = date('d-m-Y', $start_date);
                    break;
                }
            }
        }
    }
    return $val;
}

add_filter('woocommerce_moneybird_custom_field_value', 'resolve_subscription_custom_field_values', 10, 3);

Example: change ledger account based on country

Use the following example code to change the Moneybird revenue ledger account (omzetcategorie) for all invoice lines if the country of the buyer is not NL.

function filter_woocommerce_moneybird_modify_ledger_account($invoice, $order) {
    // Use the $order object here to look up the required information
    if (strtolower($order->get_billing_country()) != 'nl') {
        // Note: the ledger account id can be extracted from the url when editing it in Moneybird.
        for ($i=0; $i<count($invoice['details_attributes']); $i++) {
            $invoice['details_attributes'][$i]['ledger_account_id'] = '123456789'; # TODO: use correct id here
        }
    }

    return $invoice;
}

add_filter('woocommerce_moneybird_invoice', 'filter_woocommerce_moneybird_modify_ledger_account', 10, 2);

Example: modify contact details

The following example code replaces the default values of contact fields with order meta field values. Additionally, you can fill contact fields that are not filled by default. In the example, the “T.a.v. facturen” field is filled, corresponding to the send_invoices_to_attention field in the Moneybird API. Refer to the Moneybird Contacts API documentation for a full overview of the available fields.

function wc_mb_modify_contact_details($contact_details, $order) {
    // Replace values in $contact_details array with values from custom meta fields
    // This overwrites the default field values. To clear a value, use:
    // $contact_details['firstname'] = ''; // Empty value
    $order_id = $order->get_id();
    $contact_details['company_name'] = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['firstname']    = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['lastname']     = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['address1']     = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['address2']     = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['zipcode']      = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['city']         = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['country']      = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['email']        = get_post_meta($order_id, '_custom_field_name', true);
    $contact_details['phone']        = get_post_meta($order_id, '_custom_field_name', true);

    // Fill the "T.a.v. facturen" field of Moneybird contact
    $contact_details['send_invoices_to_attention'] = get_post_meta($order_id, '_custom_field_name', true);

    return $contact_details;
}

add_filter('woocommerce_moneybird_contact_details', 'wc_mb_modify_contact_details', 10, 2);

Example: force prices on invoice to be inclusive/exclusive of tax

The plugin follows the WooCommerce setting for prices being inclusive of exclusive of tax. If product prices are inclusive of tax, the invoice will also have invoice lines inclusive of tax and vice versa.

Code to force the invoice prices to be exclusive of tax:

// The following filter forces the invoice to have prices EXCLUSIVE of tax.
function force_moneybird_prices_exclude_tax($include_tax, $order) {
    return false;
}

add_filter('woocommerce_moneybird_prices_include_tax', 'force_moneybird_prices_exclude_tax', 10, 2);

Code to force the invoice prices to be inclusive of tax:

// The following filter forces the invoice to have prices INCLUSIVE of tax.
function force_moneybird_prices_include_tax($include_tax, $order) {
    return true;
}

add_filter('woocommerce_moneybird_prices_include_tax', 'force_moneybird_prices_include_tax', 10, 2);

Example: include product properties on invoice line

A WooCommerce product can have custom properties, for example “Height” or “Course date”. Such product properties are not saved in the Order, and will not be included on invoices by default. You can use the following code to add all textual product properties that are visible on the product page to the corresponding invoice line.

function wcmb_insert_product_properties($invoice_item, $item, $order) {
    $product = apply_filters('woocommerce_order_item_product', $order->get_product_from_item($item), $item);
    if (!$product) {
        // Corresponding product is not available
        return $invoice_item;
    }

    foreach ($product->get_attributes() as $attr_code => $attr) {
        // Only include text properties that are marked as "visible on product page"
        if ($attr->get_visible() && !($attr->is_taxonomy())) {
            $values = array();
            foreach ($attr->get_options() as $val) {
                if (is_string($val) && !empty($val)) {
                    $values[] = $val;
                }
            }
            if ($values) {
                // Add the following to the invoice item description: white line, property name in bold, property value on separate line(s)
                $invoice_item['description'] .= "\n\n*" . $attr->get_name() . "*:\n" . strip_tags(implode("\n", $values));
            }
        }
    }

    return $invoice_item;
}

add_filter('woocommerce_moneybird_invoice_item', 'wcmb_insert_product_properties', 10, 3);