datocms-plugin-record-bin
v3.0.3
Published
A plugin to manage and create a backup of deleted records in DatoCMS
Readme
🗑 Record Bin
Record Bin stores deleted records so they can be restored later.
The plugin now supports two runtimes:
Lambdaruntime (webhook/API capable)Lambda-lessruntime (dashboard delete capture only)
The plugin requires the currentUserAccessToken permission.
Runtime modes
Runtime is selected with a single toggle in the plugin config screen:
- Toggle off (
Also save records deleted from the APIdisabled):Lambda-lessmode. - Toggle on (
Also save records deleted from the APIenabled):Lambda-fullmode.
If you are not sure what Lambda is, keep the toggle off.
If no explicit runtime has ever been saved yet, the plugin falls back to legacy auto-detection:
- Lambda URL present ->
Lambda-full - No Lambda URL ->
Lambda-less
Capability matrix
| Capability | Lambda runtime | Lambda-less runtime | |---|---|---| | Capture dashboard deletions | ✅ | ✅ | | Capture API deletions | ✅ | ❌ | | Restore from Record Bin | ✅ | ✅ | | Daily cleanup check of old bin entries (on plugin boot, no cron jobs) | ✅ | ✅ |
Cleanup trigger model (no CronJobs)
Cleanup is request-driven in both runtimes, not background-scheduled:
- The plugin runs a daily cleanup check on
onBoot. - The check is throttled to once per day using
automaticBinCleanup.timeStamp. - In
Lambda-fullmode, the plugin sendsPOST /to your lambda URL withevent_type: "cleanup". - In
Lambda-lessmode, the plugin performs cleanup directly through the CMA API usingcurrentUserAccessToken. - If the plugin is not booted for some time, cleanup runs the next time it boots.
Why we do not ship cron jobs
We intentionally opted out of built-in cron jobs. On serverless platforms, scheduled invocations add recurring compute cost, while storage reduction versus boot-triggered cleanup is usually small. For this plugin, that tradeoff was not worth the extra cost and operational complexity.
Setup
Option 1: Lambda-less (default)
- Open the plugin config screen.
- Keep
Also save records deleted from the APIdisabled. - Save plugin settings.
In this mode, deleted records are captured through onBeforeItemsDestroy.
Option 2: Lambda-full (API deletion capture)
- Open the plugin config screen.
- Enable
Also save records deleted from the API. - Lambda setup fields appear. Click
Deploy lambdaand choose one option:- Vercel
- Netlify
- Cloudflare
- Paste your deployed URL into
Lambda URL.- You can paste either
https://your-app.netlify.appor justyour-app.netlify.app; the plugin will prependhttps://when needed.
- You can paste either
- Click
Connect. - Confirm status shows
Connected (ping successful).
When connected, the plugin creates or updates a project webhook named 🗑️ Record Bin pointing to your lambda root URL.
The current user role must be allowed to manage webhooks for connect/disconnect operations.
Important limitations and behavior
- In Lambda-less mode, API-triggered deletions are not captured. Only dashboard-triggered deletions go to the bin.
- Lambda-less capture is fail-open: if backup capture fails, deletion still proceeds.
- Existing webhook-origin
record_bodypayloads are still restorable. - New Lambda-less payloads are stored in a webhook-compatible envelope (
event_type: to_be_restored) so records stay restorable after runtime switches.
Lambda health handshake contract (Lambda runtime)
The plugin sends this request payload to POST /api/datocms/plugin-health:
{
"event_type": "plugin_health_ping",
"mpi": {
"message": "DATOCMS_RECORD_BIN_PLUGIN_PING",
"version": "2026-02-25",
"phase": "config_connect"
},
"plugin": {
"name": "datocms-plugin-record-bin",
"environment": "main"
}
}phase values:
config_connectwhen the user clicksConnecton the config screen.config_mountevery time the config screen is opened.finish_installationis legacy and kept for backward compatibility with older saved states.
Expected successful response (HTTP 200):
{
"ok": true,
"mpi": {
"message": "DATOCMS_RECORD_BIN_LAMBDA_PONG",
"version": "2026-02-25"
},
"service": "record-bin-lambda-function",
"status": "ready"
}Any non-200 status, invalid JSON, timeout, network failure, or contract mismatch is treated as a connectivity error.
Record Bin webhook contract (Lambda runtime)
On connect, the plugin reconciles a managed project-level webhook (creates if missing, updates if existing):
name:🗑️ Record Bin(legacy🗑 Record Binis migrated)url: connected lambda base URLevents:item.deletecustom_payload:nullheaders:{}http_basic_user:nullhttp_basic_password:nullenabled:truepayload_api_version:3nested_items_in_payload:true
