# Delete a sealed record

Soft-deletes a record. It becomes an envelope-only **tombstone**: it appears in the [change feed](/docs/api-reference/sealed-stores/list-changes) and the [deleted list](/docs/api-reference/sealed-stores/list-deleted), and it can be [undeleted](/docs/api-reference/sealed-stores/undelete-record) for 30 days, after which it is removed for good. Its content is kept until then, so an undelete restores it.

A store keeps its newest 500 tombstones. A delete past that removes the store's oldest tombstone at once, before its 30 days are up, and feed cursors from before that removal are then refused with `410 SEALED_CURSOR_EXPIRED`.

The delete names the revision it was read at in the `revision` query parameter. A stale one is `409 SEALED_RECORD_REVISION_CONFLICT`, and an already deleted record `409 SEALED_RECORD_DELETED`; both carry the record as it is now in `error.details.current`.

Requires an `Idempotency-Key` header: re-sending the same key answers the first call's exact response (header `Idempotent-Replayed: true`) and changes nothing; a refused call is not remembered, so it may be retried with the same key.

#### Path Parameters

**`store`** string required

The store: `aitronos-browser`. Up to 64 characters; an unknown store is `404 SEALED_STORE_NOT_FOUND`.

**`record_id`** string required

The record's id, as the client minted it: 16 to 128 characters of `A-Z a-z 0-9 _ -`.

#### Query Parameters

**`revision`** integer required

The revision this delete was based on. At least 1.

**`device_id`** string required

The deleting device's id: the device id it signed in with. 16 to 255 characters of `A-Z a-z 0-9 . _ : @ -`.

#### Headers

**`Authorization`** string required

`Bearer <access token>` from the person's own sign-in. API keys and service accounts are refused with `403 SEALED_STORE_PERSONAL_SESSION_REQUIRED`.

**`Idempotency-Key`** string required

A random id minted once for this change and sent again on every retry of it: 16 to 128 printable ASCII characters, no spaces (a UUID works). The first accepted answer is remembered for 30 days; see [Idempotency-Key](/docs/api-reference/sealed-stores/introduction#idempotency-key).

## Returns

`200 OK` with the tombstone's envelope: `deleted` is `true`, `deleted_at` is set, `payload_bytes` is `null`, and `device_id` is the deleting device.

- **`object`** string — `sealed_record_envelope`.
- **`id`** string — the client's record id.
- **`kind`** string — `session` or `favourites`.
- **`schema_version`** integer — as the last accepted write sent it.
- **`revision`** integer — server-assigned; rises by 1 on every accepted write.
- **`created_at`** string — when the record was created (ISO 8601 UTC).
- **`last_touched_at`** string — set by the server on every accepted write. Sort by it, ties by `id`.
- **`deleted`** boolean — whether the record is a tombstone.
- **`deleted_at`** string or null — when it was deleted.
- **`device_id`** string — the device of the last accepted write.
- **`payload_bytes`** integer or null — the decoded payload size; `null` for a tombstone.


There is no copy of the sealed content: [get the record](/docs/api-reference/sealed-stores/get-record) or read the [change feed](/docs/api-reference/sealed-stores/list-changes) for it.

Every answer carries the header **`Idempotent-Replayed`**: `false` on the first answer, `true` when this is the remembered answer to an `Idempotency-Key` sent before.

## Errors

| Status | Code | When |
|  --- | --- | --- |
| 401 | `AUTHENTICATION_REQUIRED` | No access token, or one that is not valid. |
| 403 | `SEALED_STORE_PERSONAL_SESSION_REQUIRED` | The call used an API key or a service account. Only a person's own sign-in session reaches a sealed store. |
| 404 | `SEALED_STORE_NOT_FOUND` | No store with that name (`details.store`). |
| 404 | `SEALED_RECORD_NOT_FOUND` | No record with that id in the caller's store, or its tombstone has passed the 30-day retention. |
| 409 | `SEALED_OPERATION_IN_PROGRESS` | An earlier call with this `Idempotency-Key` has not finished. Retry in a moment. |
| 409 | `SEALED_RECORD_DELETED` | The record is already deleted. This wins over a stale revision. `details.current` is the tombstone. |
| 409 | `SEALED_RECORD_REVISION_CONFLICT` | `revision` is not the record's current revision. `details.current` is the record as it is now. |
| 422 | `SEALED_IDEMPOTENCY_KEY_REQUIRED` | No `Idempotency-Key` header. |
| 422 | `SEALED_IDEMPOTENCY_KEY_INVALID` | The `Idempotency-Key` is not 16 to 128 printable ASCII characters without spaces. |
| 422 | `SEALED_IDEMPOTENCY_KEY_REUSED` | The `Idempotency-Key` was already used for a different call. Mint a new one for a new change. |
| 422 | `VALIDATION_ERROR` | `revision` or `device_id` is missing or invalid, or `record_id` does not match its pattern. |



```bash cURL
curl -X DELETE "https://api.aitronos.com/v1/sealed-stores/aitronos-browser/records/vSWmWbg9sDur336pnYgYzQ?revision=2&device_id=1f783def-2aa1-4b44-9c73-3c6b9102c06b" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: 604d9e35-d800-493f-bec6-37cceeeb0245"
```


```python Python
import os
import uuid

import requests

idempotency_key = str(uuid.uuid4())  # once per change; reuse it on every retry

response = requests.delete(
    "https://api.aitronos.com/v1/sealed-stores/aitronos-browser/records/vSWmWbg9sDur336pnYgYzQ",
    headers={
        "Authorization": f"Bearer {os.environ['AITRONOS_TOKEN']}",
        "Idempotency-Key": idempotency_key,
    },
    params={"revision": 2, "device_id": "1f783def-2aa1-4b44-9c73-3c6b9102c06b"},
    timeout=30,
)
body = response.json()
if response.status_code == 200:
    print("deleted at", body["deleted_at"], "- tombstone revision", body["revision"])
elif body["error"]["code"] in ("SEALED_RECORD_REVISION_CONFLICT", "SEALED_RECORD_DELETED"):
    current = body["error"]["details"]["current"]
    print("record is at revision", current["revision"], "deleted:", current["deleted"])
else:
    print(response.status_code, body["error"]["code"])
```


```javascript JavaScript
const idempotencyKey = crypto.randomUUID(); // once per change; reuse it on every retry
const params = new URLSearchParams({ revision: "2", device_id: "1f783def-2aa1-4b44-9c73-3c6b9102c06b" });
const response = await fetch(`https://api.aitronos.com/v1/sealed-stores/aitronos-browser/records/vSWmWbg9sDur336pnYgYzQ?${params}`, {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.AITRONOS_TOKEN}`,
    "Idempotency-Key": idempotencyKey,
  },
});
const body = await response.json();
if (response.ok) {
  console.log("deleted at", body.deleted_at, "- tombstone revision", body.revision);
} else {
  console.log(response.status, body.error.code, body.error.details.current?.revision);
}
```

**Response:**

200 OK

```json
{
  "object": "sealed_record_envelope",
  "id": "vSWmWbg9sDur336pnYgYzQ",
  "kind": "session",
  "schema_version": 1,
  "revision": 3,
  "created_at": "2026-10-10T08:41:17.204913Z",
  "last_touched_at": "2026-10-10T09:30:05.551390Z",
  "deleted": true,
  "deleted_at": "2026-10-10T09:30:05.551390Z",
  "device_id": "1f783def-2aa1-4b44-9c73-3c6b9102c06b",
  "payload_bytes": null
}
```

409 Already deleted

```json
{
  "success": false,
  "error": {
    "code": "SEALED_RECORD_DELETED",
    "message": "This item was deleted on another device.",
    "system_message": "the record is a tombstone; undelete it before writing",
    "type": "client_error",
    "status": 409,
    "details": {
      "current": {
        "object": "sealed_record",
        "id": "vSWmWbg9sDur336pnYgYzQ",
        "kind": "session",
        "schema_version": 1,
        "revision": 3,
        "created_at": "2026-10-10T08:41:17.204913Z",
        "last_touched_at": "2026-10-10T09:30:05.551390Z",
        "deleted": true,
        "deleted_at": "2026-10-10T09:30:05.551390Z",
        "device_id": "1f783def-2aa1-4b44-9c73-3c6b9102c06b",
        "wrapped_dek": null,
        "payload": null,
        "payload_bytes": null
      }
    },
    "trace_id": "aee5ef40-67ef-4a9a-aea6-43616371dcf4",
    "timestamp": "2026-10-10T09:30:41.906224Z"
  }
}
```

409 Stale revision

```json
{
  "success": false,
  "error": {
    "code": "SEALED_RECORD_REVISION_CONFLICT",
    "message": "This item changed on another device. Merge and save again.",
    "system_message": "revision 1 is stale; the record is at revision 2",
    "type": "client_error",
    "status": 409,
    "details": {
      "current": {
        "object": "sealed_record",
        "id": "vSWmWbg9sDur336pnYgYzQ",
        "kind": "session",
        "schema_version": 1,
        "revision": 2,
        "created_at": "2026-10-10T08:41:17.204913Z",
        "last_touched_at": "2026-10-10T09:02:44.918207Z",
        "deleted": false,
        "deleted_at": null,
        "device_id": "1aee2c02-ccac-4ede-b017-1334be895e2e",
        "wrapped_dek": {
          "v": 1,
          "aead": "aes-256-gcm",
          "nonce": "oxwDDz+SyxUEkitE",
          "ct": "UvORUdzuxuE3FMncUQgc4qOEz2QT8a5LarNYrATM0A4Zi1J0aJj9Yu+5ySIKPQHY",
          "epk": "fRXpvCBVDmU9kJ+PSkoqi7NU2Po3FQMK9SbJiz1gOGs="
        },
        "payload": "hWbThAu7J8u8jIcvARYROTja+vbbV4hlntXsIctvvcVdqWGMyTjVt2LgISSfrFORn+gjkJcDsT9l8dsHXoFFCaDLzP06FHLuixGaBMY3WOfWFex4l7SU0G5IKY7DABr74o0l20asWcd9gADrlQl4Zg==",
        "payload_bytes": 112
      }
    },
    "trace_id": "73433f8c-a40d-41a7-92d2-c0177676ddb9",
    "timestamp": "2026-10-10T09:29:58.163390Z"
  }
}
```

## Related Resources

- [Sealed stores](/docs/api-reference/sealed-stores/introduction)
- [Undelete a sealed record](/docs/api-reference/sealed-stores/undelete-record)
- [List deleted sealed records](/docs/api-reference/sealed-stores/list-deleted)
- [Get a sealed record](/docs/api-reference/sealed-stores/get-record)
- [List sealed store changes](/docs/api-reference/sealed-stores/list-changes)