Skip to main content
POST
/
v1
/
purchases
/
bulk-delete-by-filters
Bulk Delete by Filters
const options = {
  method: 'POST',
  headers: {
    'x-api-key': '<x-api-key>',
    'x-organization-id': '<x-organization-id>',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({filter_hash: '<string>'})
};

fetch('https://api.dcycle.io/v1/purchases/bulk-delete-by-filters', options)
  .then(res => res.json())
  .then(res => console.log(res))
  .catch(err => console.error(err));
{
  "deleted": [
    "<string>"
  ],
  "failed": [
    {}
  ]
}

Bulk Delete by Filters

Delete all purchases that match the given filter criteria. Uses the same filter parameters as the list endpoint, plus a filter_hash for optimistic concurrency — ensuring you delete exactly what the user saw.

How filter_hash works

  1. Call the list endpoint with your filters — the response includes a filter_hash
  2. Pass that filter_hash in the body of this request along with the same filters
  3. If the filters changed between the two calls, the server returns 409 Conflict
This prevents accidental mass deletions when filters have been modified.

Request

Headers

x-api-key
string
required
Your API key for authenticationExample: sk_live_1234567890abcdef
x-organization-id
string
required
Your organization UUIDExample: a8315ef3-dd50-43f8-b7ce-d839e68d51fa

Query Parameters

At least one filter parameter is required. Supports all the same filters as the list endpoint:
purchase_date_from
string
Filter purchases on or after this date (YYYY-MM-DD)
purchase_date_to
string
Filter purchases on or before this date (YYYY-MM-DD)
Search by description or supplier name
status[]
string[]
Filter by status. Values: active, error, in_progress, in_review, inactive, pending
purchase_type[]
string[]
Filter by calculation methodology. Values: spend_based, supplier_specific
expense_type[]
string[]
Filter by expense classification. Values: capex, opex
file_id[]
string[]
Filter by file UUID
supplier_id[]
string[]
Filter by supplier UUID
unit_id[]
string[]
Filter by currency unit UUID
created_at_from
string
Filter records created on or after this date
created_at_to
string
Filter records created on or before this date
co2e_status
string
Filter by CO2e calculation status

Body Parameters

filter_hash
string
required
Hash from the list endpoint response. Must match the current filter set.

Response

deleted
string[]
UUIDs of successfully deleted purchases
failed
object[]
Failed deletions with reason

Example

# Step 1: Get filter_hash from list
RESPONSE=$(curl -s "https://api.dcycle.io/v1/purchases?expense_type[]=opex&purchase_date_to=2024-12-31" \
  -H "x-api-key: ${DCYCLE_API_KEY}" \
  -H "x-organization-id: ${DCYCLE_ORG_ID}")

FILTER_HASH=$(echo $RESPONSE | jq -r '.filter_hash')

# Step 2: Bulk delete with the same filters
curl -X POST "https://api.dcycle.io/v1/purchases/bulk-delete-by-filters?expense_type[]=opex&purchase_date_to=2024-12-31" \
  -H "x-api-key: ${DCYCLE_API_KEY}" \
  -H "x-organization-id: ${DCYCLE_ORG_ID}" \
  -H "Content-Type: application/json" \
  -d "{\"filter_hash\": \"${FILTER_HASH}\"}"

Successful Response

{
  "deleted": [
    "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "b2c3d4e5-f6a7-8901-bcde-f12345678901"
  ],
  "failed": []
}

Common Errors

401 Unauthorized

Cause: Missing or invalid API key
{"detail": "Invalid API key for organization", "code": "INVALID_API_KEY"}

403 Forbidden

Cause: The authenticated user is not a member of the organization
{"detail": "Logged User is not Member of Organization", "code": "LOGGED_USER_NOT_MEMBER"}

409 Conflict

Cause: The filter_hash doesn’t match the current filters — they changed since the list was loaded
{
  "detail": "Filter hash mismatch. The filters have changed since the list was loaded. Please refresh and try again."
}

422 Unprocessable Entity

Cause: No filter parameters provided (at least one is required to prevent accidental mass deletion)
{
  "detail": "At least one filter parameter is required for bulk delete by filters."
}

Bulk Delete

Delete specific purchases by ID

List Purchases

Browse purchases and get filter_hash