> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dokstamp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deletion Rules

> What can and cannot be deleted once certificates have been issued. Understanding soft deletes and referential integrity.

# Deletion Rules

DokStamp is designed to preserve the integrity of issued certificates. Once a certificate has been issued, the entities it references are protected from deletion. This page explains the rules and the recommended patterns for integrations.

***

## Soft deletes

All entities in DokStamp use **soft deletes**: when you call `DELETE /resource/{uuid}`, the record is not physically removed from the database. Instead, a `deleted_at` timestamp is set. Soft-deleted records:

* Are excluded from all `GET` list responses
* Cannot be referenced by new resources
* Retain all their data and relationships intact
* Can be restored by the platform administrator if needed

This means **no data is ever permanently lost** through the standard delete API.

***

## Deletion protection rules

Attempting to delete an entity that has dependent issued certificates will result in an error. The protection is enforced at the database level via foreign key constraints.

| Entity          | Cannot be deleted when...                                        |
| --------------- | ---------------------------------------------------------------- |
| **Institution** | Has any courses, modules, or certificates referencing it         |
| **Course**      | Has cohorts, enrollments, or certificates referencing it         |
| **Module**      | Is attached to any course (`course_modules` relationship exists) |
| **Cohort**      | Has enrollments or certificates referencing it                   |
| **Student**     | Has certificates, enrollments, or a credential subject snapshot  |

***

## Why this matters for integrations

When your third-party system deletes or deactivates an entity, you must **not mirror that deletion blindly** to DokStamp if certificates have already been issued. The recommended approach:

### 1. Check for certificates before deleting

```javascript theme={null}
async function canDelete(entityType, uuid) {
  const certs = await api.get('/certificates', {
    params: { [`where[${entityType}_uuid]`]: uuid, per_page: 1 }
  });
  return certs.data.meta.total === 0;
}

// Example for a course
if (await canDelete('course', courseUuid)) {
  await api.delete(`/courses/${courseUuid}`);
} else {
  // Archive instead of delete
  await api.patch(`/courses/${courseUuid}`, { status: 'archived' });
}
```

### 2. Archive instead of delete

For courses and institutions, prefer updating the `status` field to `archived` or `inactive` rather than deleting:

```javascript theme={null}
// Instead of DELETE /courses/{uuid}
await api.patch(`/courses/${courseUuid}`, { status: 'archived' });
```

This preserves all relationships while clearly marking the entity as no longer active.

### 3. Handle the error gracefully

If a deletion attempt fails due to an existing dependency, the API returns an error. Always handle this in your integration:

```javascript theme={null}
try {
  await api.delete(`/courses/${courseUuid}`);
} catch (err) {
  if (err.response?.status === 500) {
    // Likely a referential integrity error — log and archive instead
    logger.warn(`Cannot delete course ${courseUuid} — has dependent records. Archiving instead.`);
    await api.patch(`/courses/${courseUuid}`, { status: 'archived' });
  } else {
    throw err;
  }
}
```

***

## Certificate immutability

Once a certificate is issued, all the data associated with it is preserved:

* Student identity (name, email, document ID, date of birth, country) — captured in an immutable snapshot at issuance
* Course, institution, cohort, and enrollment data — all preserved through the referential integrity rules above

This guarantees that a certificate's public verification URL will always display accurate, complete information regardless of any future changes to the underlying entities.

***

## Module detachment vs deletion

Modules can be **detached** from a course without being deleted:

```http theme={null}
DELETE /courses/{course_uuid}/detach/modules
```

This removes the `course_modules` association but leaves both the course and the module intact. This is the preferred operation when reorganizing a curriculum, as it allows the module to be reattached to a different course.

Deleting a module entirely (via `DELETE /modules/{uuid}`) is only possible once it has been detached from all courses.

***

## Summary: prefer archiving over deleting

| Scenario                         | Recommended action                                        |
| -------------------------------- | --------------------------------------------------------- |
| Course discontinued              | `PATCH /courses/{uuid}` → `{ "status": "archived" }`      |
| Institution inactive             | `PATCH /institutions/{uuid}` → `{ "status": "inactive" }` |
| Student record to be deactivated | Do not delete; leave the record intact                    |
| Module no longer taught          | Detach from course; do not delete the module              |
| Cohort ended                     | No action needed; cohorts are historical records          |
