Recycle bin
Most Workspace resources use a 30-day soft-delete recycle bin instead of hard-deleting rows. DELETE sets a deleted_at timestamp; the row stays queryable (via explicit filters) for 30 days, then a cron hard-deletes it. Restore anytime within that window.
How it works
- Default list queries exclude soft-deleted rows. A tenant that reads
/contactsnever sees the trash by accident. - ?deleted=true — list only rows in the recycle bin. Useful for recovery UIs.
- ?deleted=any — list both live and deleted rows together. Useful for full exports / backups.
- POST /:resource/:id/restore — undelete a row. Requires the same
.deletescope that performed the delete. - 30-day hard-purge. A daily cron picks up rows where
deleted_at < NOW() - INTERVAL 30 DAYand permanently removes them. After this point, restore is impossible.
Example flow
# 1. Soft-delete a contact curl -X DELETE "https://app.staffifyai.com/api/workspace/v1/contacts/1893" \ -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" # 2. See it in the recycle bin curl "https://app.staffifyai.com/api/workspace/v1/contacts?deleted=true" \ -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" # 3. Restore within 30 days curl -X POST "https://app.staffifyai.com/api/workspace/v1/contacts/1893/restore" \ -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"
Resources that support soft-delete
| Resource | Path | Delete scope |
|---|---|---|
| Contacts | /contacts | crm.contacts.delete |
| Companies | /companies | crm.companies.delete |
| Deals | /deals | crm.deals.delete |
| Tasks | /tasks | crm.tasks.delete |
| Notes | /notes | crm.notes.delete |
| Segments | /segments | crm.segments.delete |
| Quotes | /quotes | sales.quotes.delete |
| Invoices | /invoices | sales.invoices.delete (drafts only) |
| Products | /products | sales.products.delete |
| Bookings | /bookings | bookings.entries.delete |
| Booking customers | /bookings/customers | bookings.customers.delete |
| Booking links | /bookings/links | bookings.links.delete |
| Work orders | /workorders | operations.workorders.delete |
| Maintenance contracts | /maintenance-contracts | operations.maintenance.delete |
| Certifications | /certifications | operations.certifications.delete |
Resources without a recycle bin
A few resources use alternative semantics by design — DELETE on these is immediate or has a different meaning.
| Resource | Delete behavior |
|---|---|
| Stock items | Stock is a sidecar on CRM products — turn tracking off with PATCH is_stock_tracked=false instead of deleting. |
| Time logs | Ledger rows (append-only semantics). DELETE performs a hard-delete; movement history for the parent work order is preserved by other logs. |
| Maintenance installations | Child entities of a maintenance contract. DELETE performs a hard-delete; soft-delete the parent contract if you need the whole set back. |
| Appointments | Calendar entries use status=cancelled + cancelled_at (soft-cancel) instead of a recycle bin. The row stays in the table for history and reporting. |
| Webhook endpoints | Reversible via re-create. DELETE is immediate — the signing_secret is gone with the row. |