New to Kestra?
Use blueprints to kickstart your first workflows.
List Dropbox files past a retention threshold, alert Slack with the stale paths, and log the result for platform teams.
A shared Dropbox folder accumulates exports, old reports, and one-off uploads nobody ever circles back to clean up. Dropbox has no scheduled, folder-wide retention sweep of its own, only a per-file view if someone opens it. This blueprint reads what is actually under a path, flags what has outlived its retention window by its own clientModified date, and reports the real file paths, not a guess.
This blueprint was created by Mohit Jeswani.
list_files (io.kestra.plugin.dropbox.files.List) lists every entry under
dropbox_path, recursively when recursive_scan is true. Read-only; nothing in Dropbox
is changed. allowFailure: true covers an API or auth error without failing the flow
outright.evaluate (io.kestra.plugin.core.output.OutputValues) filters to entries where type
is file and clientModified is older than retention_days, with a jq filter, since
the Dropbox List API itself has no age-based filter.route (io.kestra.plugin.core.flow.If):summary logs the count and severity, closing the governance cycle.errors alerts Slack if the flow itself fails, for example an expired access token.clientModified is null for a
folder and this check only ever evaluates type == "file".files.List used for a
governance check, distinct from this repo's existing Dropbox blueprints, which handle
intake, backup, and report distribution rather than retention auditing.Dropbox shows a file's modified date one file at a time; it does not compare that date
across a whole folder against a retention policy you declare, or notify anyone. Kestra keeps
retention_days as a flow input, turns the scan into a Slack page naming the actual stale
file paths, and keeps a full execution history of every run.
dropbox_path.This flow calls the Dropbox API directly over HTTPS; there is no official local Dropbox
emulator, so list_files cannot be exercised against a local Docker container.
DROPBOX_ACCESS_TOKEN: the Dropbox access token used by list_files. In Kestra OSS,
provide it as the base64-encoded environment variable SECRET_DROPBOX_ACCESS_TOKEN.SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as
the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.| Input | Default | Purpose |
|---|---|---|
dropbox_path |
`` (root) | Dropbox path to scan |
recursive_scan |
true |
Whether to traverse sub-folders |
retention_days |
180 |
Age past which a file is reported stale |
max_stale_count |
1 |
Matched-file count that triggers the Slack alert |
{{ outputs.list_files.rows }}: every scanned entry (name, id, path, type, size,
clientModified).{{ outputs.evaluate.values.stale_count }} / .stale_paths: how many files are stale and
their display paths, semicolon-joined.{{ outputs.evaluate.values.severity }}: OK, STALE_FILES_FOUND, or CRITICAL.clientModified is the last time the file's content changed, set by the client that
uploaded or edited it, not when Dropbox itself last touched the file internally; a file
re-synced but not actually edited does not reset the staleness clock.limit on files.List defaults to 2000 entries per call with no pagination handled here;
a path with more entries than that is only partially scanned in one run.recursive_scan: false only lists the top level of dropbox_path; a stale file several
folders deep is invisible to this check unless recursion is enabled.DROPBOX_ACCESS_TOKEN and SLACK_WEBHOOK_URL secrets.dropbox_path to a real folder.summary logs a count.retention_days above every scanned file's age, then lower it below a known old
file's age, to confirm both compliant and alert fire correctly.weekly trigger once retention_days matches your actual retention policy.dropbox_path values with io.kestra.plugin.core.flow.Loop to cover
more than one shared folder in a single scheduled run.io.kestra.plugin.dropbox.files.Move on each stale file to a "pending deletion"
sub-folder instead of deleting outright, gated behind an explicit confirm_move input.size across stale entries in the evaluate step to report reclaimable bytes alongside
the file count.