Webhook Listeners

Nextcloud supports listening to internal events via webhooks.

Installation

  • Enable the webhook_listeners app that comes bundled with Nextcloud

occ app:enable webhook_listeners

Listening to events

You can use the OCS API to add webhooks for specific events: https://docs.nextcloud.com/server/latest/developer_manual/_static/openapi.html#/operations/webhook_listeners-webhooks-index

Note: When authenticating with the OCS API to register webhooks the account you authenticate as must have administrator rights or delegated administrator rights.

Filters

When registering a webhook listener, you can specify a filter parameter. The value of this parameter must be a JSON object whose properties represent filter conditions. The {} is an empty query, meaning no specific criteria, so all events are matched.

If you would like to match events fired by a specific user, you can pass { "user.uid": "bob" } to match all events fired in the context of user "bob".

If you would like to enforce multiple criteria, you can simply pass multiple properties { "event.tableId": 42, "event.rowId": 3 }

You can also use additional comparison operators ($eq, $ne, $gt, $gte, $lt, $lte, $in, $nin) as well as logical operators ($and, $or, $not, $nor). For example use { "time" : { "$lt": 1711971024 } } to accept only events prior to April 1st 2024 and { "time" : { "$not": { "$lt": 1711971024 } } } to accept events after April 1st 2024.

Speeding up webhook dispatch

This app uses background jobs to trigger the registered webhooks. Thus, by default, webhooks will be triggered only every 5 minutes, as the default cron interval is 5 minutes. To trigger webhooks earlier, you can set up a background job worker. The following command will launch a worker for the webhook call background job:

occ background-job:worker "OCA\\WebhookListeners\\BackgroundJobs\\WebhookCall"

It is recommended to restart this worker once a day to make sure code changes are effective and avoid memory leaks, for example by registering it as a systemd service with a daily timer.

Nextcloud Webhook Events

This is an exhaustive list of available events. It features the event ID and the available variables for filtering.

  • OCA\Forms\Events\FormSubmittedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "form": array{
     "id": int,
     "hash": string,
     "title": string,
     "description": string,
     "ownerId": string,
     "fileId": string|null,
     "fileFormat": string|null,
     "created": int,
     "access": int,
     "expires": int,
     "isAnonymous": bool,
     "submitMultiple": bool,
     "showExpiration": bool,
     "lastUpdated": int,
     "submissionMessage": string|null,
     "state": int,
    },
    "submission": array{
      "id": int,
      "formId": int,
      "userId": string,
      "timestamp": int,
    },
  }
}
  • OCA\Tables\Event\RowAddedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "tableId": int,
    "rowId": int,
    "previousValues": null|array<int, mixed>,
    "values": null|array<int, mixed>
  }
}
  • OCA\Tables\Event\RowDeletedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "tableId": int,
    "rowId": int,
    "previousValues": null|array<int, mixed>,
    "values": null|array<int, mixed>
  }
}
  • OCA\Tables\Event\RowUpdatedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "tableId": int,
    "rowId": int,
    "previousValues": null|array<int, mixed>,
    "values": null|array<int, mixed>
  }
}
  • OCP\Files\Events\Node\BeforeNodeCreatedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\BeforeNodeTouchedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\BeforeNodeWrittenEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\BeforeNodeReadEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\BeforeNodeDeletedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\NodeCreatedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\NodeTouchedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\NodeWrittenEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\NodeReadEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\NodeDeletedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "node": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\NodeCopiedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "source": array{"id": string, "path": string}
    "target": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\NodeRestoredEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "source": array{"id": string, "path": string}
    "target": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\NodeRenamedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "source": array{"id": string, "path": string}
    "target": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\BeforeNodeCopiedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "source": array{"id": string, "path": string}
    "target": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\BeforeNodeRestoredEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "source": array{"id": string, "path": string}
    "target": array{"id": string, "path": string}
  }
}
  • OCP\Files\Events\Node\BeforeNodeRenamedEvent

array{
  "user": array {"uid": string, "displayName": string},
  "time": int,
  "event": array{
    "class": string,
    "source": array{"id": string, "path": string}
    "target": array{"id": string, "path": string}
  }
}