# Update a sealed record

Replaces the record's sealed content: `schema_version`, `device_id`, `wrapped_dek` and `payload` are all taken from the body. The body names the `revision` it was read at; the server sets the next revision and `last_touched_at`.

**Conflicts carry the current record.** When another device wrote first, the `revision` sent is stale and the answer is `409 SEALED_RECORD_REVISION_CONFLICT`. When the record was deleted, it is `409 SEALED_RECORD_DELETED`, even if the revision is also stale. Either way `error.details.current` holds the record as the server has it now (envelope and payload, or the tombstone), so the client can merge and write again without another read.

An accepted update answers the record's envelope, without a copy of the sealed content. Requires an `Idempotency-Key` header: re-sending the same key answers the first call's exact response (header `Idempotent-Replayed: true`) and changes nothing; only accepted changes are remembered, so a refused call may be retried with the same key once the client has merged.

#### 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 _ -`.

#### 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).

#### Body Parameters

`last_touched_at` and the other fields the server owns are ignored if sent.

**`revision`** integer required

The revision this write was based on: the `revision` of the record as this device last read it. At least 1.

**`schema_version`** integer required

The client's schema and sealing version for this value, 1 to 2,147,483,647. Stored and returned as sent; the server never interprets it.

**`device_id`** string required

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

**`wrapped_dek`** object required

The record's data key, wrapped to the account's identity public key with an ephemeral X25519 key agreement and an AEAD. Unknown fields inside it are refused; a wrapped key of the wrong shape is `422 SEALED_WRAPPED_KEY_INVALID`.

- **`v`** integer — the wrap format version, `1` (the string `"1"` is accepted too).
- **`aead`** string — `aes-256-gcm` or `chacha20-poly1305`.
- **`nonce`** string — the 12-byte nonce, base64.
- **`ct`** string — the 48-byte wrapped key (key plus tag), base64.
- **`epk`** string — the 32-byte ephemeral X25519 public key, base64.


**`payload`** string required

The sealed bytes, standard padded base64. At least 28 bytes decoded (a 12-byte nonce plus a 16-byte tag) and at most 512 KiB (524,288 bytes) decoded; the ceiling counts `payload` alone, not `wrapped_dek`.

## Returns

`200 OK` with the record's envelope at its new revision:

- **`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 a tombstone; undelete it before writing. 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. |
| 413 | `SEALED_PAYLOAD_TOO_LARGE` | `payload` is over 512 KiB decoded (`details.field`, `details.max_bytes`, `details.payload_bytes`). |
| 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 | `SEALED_PAYLOAD_INVALID` | `payload` is not standard padded base64, or decodes to fewer than 28 bytes (`details.field`). |
| 422 | `SEALED_WRAPPED_KEY_INVALID` | `wrapped_dek` is not a wrapped key of the documented shape (`details.field`). |
| 422 | `VALIDATION_ERROR` | A body field is missing, of the wrong type or out of range, or `record_id` does not match its pattern. |



```bash cURL
curl -X PUT "https://api.aitronos.com/v1/sealed-stores/aitronos-browser/records/vSWmWbg9sDur336pnYgYzQ" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: cf50c0a1-75a1-4540-ba88-fa54362972fc" \
  -H "Content-Type: application/json" \
  -d '{
  "revision": 1,
  "schema_version": 1,
  "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=="
}'
```


```python Python
import os
import uuid

import requests

idempotency_key = str(uuid.uuid4())  # once per change; reuse it on every retry
change = {
    "revision": 1,
    "schema_version": 1,
    "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=="
}

response = requests.put(
    "https://api.aitronos.com/v1/sealed-stores/aitronos-browser/records/vSWmWbg9sDur336pnYgYzQ",
    headers={
        "Authorization": f"Bearer {os.environ['AITRONOS_TOKEN']}",
        "Idempotency-Key": idempotency_key,
    },
    json=change,
    timeout=30,
)
body = response.json()
if response.status_code == 200:
    print("now at revision", body["revision"])
elif body["error"]["code"] == "SEALED_RECORD_REVISION_CONFLICT":
    current = body["error"]["details"]["current"]
    # Open current["payload"], merge it with this device's change, seal the result
    # and write it again with revision=current["revision"].
    print("another device wrote revision", current["revision"])
elif body["error"]["code"] == "SEALED_RECORD_DELETED":
    print("deleted on another device at", body["error"]["details"]["current"]["deleted_at"])
else:
    print(response.status_code, body["error"]["code"])
```


```javascript JavaScript
const idempotencyKey = crypto.randomUUID(); // once per change; reuse it on every retry
const change = {
  "revision": 1,
  "schema_version": 1,
  "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=="
};

const response = await fetch("https://api.aitronos.com/v1/sealed-stores/aitronos-browser/records/vSWmWbg9sDur336pnYgYzQ", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.AITRONOS_TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": idempotencyKey,
  },
  body: JSON.stringify(change),
});
const body = await response.json();
if (response.ok) {
  console.log("now at revision", body.revision);
} else if (body.error.code === "SEALED_RECORD_REVISION_CONFLICT") {
  const current = body.error.details.current;
  // Open current.payload, merge, seal the result and write it with revision current.revision.
  console.log("another device wrote revision", current.revision);
} else {
  console.log(response.status, body.error.code);
}
```

**Response:**

200 OK

```json
{
  "object": "sealed_record_envelope",
  "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",
  "payload_bytes": 112
}
```

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": "23d6b3ec-5672-4575-b78f-d40697476d02",
    "timestamp": "2026-10-10T09:03:20.551027Z"
  }
}
```

409 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": "36464e30-b4fb-446b-b370-0b009bfcb780",
    "timestamp": "2026-10-10T09:31:12.084466Z"
  }
}
```

## Related Resources

- [Sealed stores](/docs/api-reference/sealed-stores/introduction)
- [Get a sealed record](/docs/api-reference/sealed-stores/get-record)
- [Create a sealed record](/docs/api-reference/sealed-stores/create-record)
- [Delete a sealed record](/docs/api-reference/sealed-stores/delete-record)
- [Append a superseded value](/docs/api-reference/sealed-stores/append-superseded)