I want to define some scheduled jobs so that old data is deleted from time to time. For example contacts in trash, mailings older than X year, drafted mailings never sent... For scheduled jobs I need to use api v3 - is this right? I read it somewhere...

I found a module with some basic functionality like we need (https://github.com/fuzionnz/nz.co.fuzion.deleteoldbulkmailings) and tried to adjust to our needs. I would like to understand how CiviCRM finds new API 3 actions and entities so I got rid of all the civix code. I reduced the code so that there is only folowing left:

In folder api/v3/Bulkmailing there is is a file Deleteoldrecords.php:

 * Bulkmailing.Deleteoldrecords API
 * @param array $params
 * @return array API result descriptor
 * @see civicrm_api3_create_success
 * @see civicrm_api3_create_error
 * @throws API_Exception
function civicrm_api3_bulkmailing_Deleteoldrecords($params) {
  $isEnabled = Civi::settings()->get('logging');
  $logging = new CRM_Logging_Schema();
  if ($isEnabled) {
  if ($isEnabled) {

  return civicrm_api3_create_success(array(), $params, 'BulkMailing', 'DeleteOldRecords');

In folder CRM/BulkMailing/BAO there is a file named Delete.php with the class CRM_BulkMailing_BAO_Delete:

class CRM_BulkMailing_BAO_Delete extends CRM_Contact_BAO_DeleteBase {

   * Delete older bulk mailing records
   * @param array $parameters
   *  The parameters as defined in scheduled job.
   *  See self::getMailingIdsFromParams() for details
   *  Additionally skip_activity_delete can be set to TRUE so that Activities
   *  related to the deleted mailing should not be deleted.
   * @throws \API_Exception
   * @throws \CiviCRM_API3_Exception
  public static function delete(array $parameters): void {
    $parameters['delete_drafts'] = FALSE;
    $mailingIds = self::getMailingIdsFromParams($parameters);
    if (!empty($mailingIds)) {

For what ever reason before my changes I was able to create a scheduled job for entity BulkMailing and with action Deleteoldrecords. Now I can not.

I find no documentation about how to create custom entities and actions for api v3 - at least none which exactly explains how CiviCRM finds my new entities / actions. All I find is how to use civix to create mass of code which is not actually needed (I am not a fan of these tools creating code for me...). I am sure there are naming conventions which are not documented?! Maybe I have somewhere a typo or a uppercase/lowercase problem which simply leads to this issue?!

Could somebody explain to me a) if there is a way to use api V4 for scheduled jobs (which I would prefer) and b) if not how CiviCRM actually finds out which apiv3 entities and actions are defined by my extension?

  • Since your question is about doing this without civix, I'll just put this as a comment. Civix is intended to make it easier to do things like this and hide some of the underlying complexity. See docs.civicrm.org/dev/en/latest/extensions/civix/#generate-api civix generate:api NewEntity newaction --schedule Hourly creates all the files you need for your API function and a scheduled job to call it. Civix doesn't create stuff just for the fun of filling up your filesystem!
    – Aidan
    May 5, 2022 at 8:31
  • The whole MODULE.civix.php file is full of functions which are not needed. They are all "just in case" functions. So I'd like to understand what actually is needed to achieve just what I want to achieve without a bunch of useless code. May 5, 2022 at 9:56
  • totten has just released an updated civix reducing the boilerplate: civicrm.org/blog/totten/…
    – Aidan
    May 5, 2022 at 10:53

1 Answer 1


Not exactly a scheduled job or an answer to the questions in regard to civix and the api but you may want to have a look at the SQL-Task Extension.

It allows you to configure any number of scheduled tasks via the UI. It is essentially a SQL driven, configurable execution of any of the following generic CiviCRM actions:

  • Create activities
  • Call any CiviCRM API3 action
  • Export to CSV,including zipping, uploading, emailing the results
  • Synchronize a SQL result such as a contact ID list with a given tag or group

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.