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

# Store an encrypted message

> Ask a Cache node to temporarily retain one eligible DDN envelope

This endpoint stores an encrypted [DDN envelope](/guides/ddn-envelope) without decrypting its payload. The Cache validates the recipient, expiration, size limits, and public delivery state before accepting it.

For a direct compatible-client request, send only the original envelope fields. Direct storage can use ordinary DID-service fall-through when no policy applies. When a policy rule applies, submit the original envelope to a Relay so the network can execute the winning `Store` action.

## Request

<Warning>
  Do not send `policy_context`, `policy_id`, `policy_revision`, `policy_rule_id`, `policy_block_hash`, or `policy_block_number`. Policy provenance is network-managed and client-supplied values do not authorize storage.
</Warning>

<RequestExample>
  ```bash Request theme={null}
  curl --request POST \
    --url "https://cache.example.com/cache/store" \
    --header "Content-Type: application/json" \
    --data '{
      "message_id": "9f8d6f08-bce5-4df5-b22b-bf8c6bd4e143",
      "to": "did:openpayload:1111111111111111111111",
      "timestamp": "<current-RFC3339-timestamp>",
      "ttl": "24h",
      "payload": {"ciphertext_b64":"<encrypted-message>"},
      "encrypted_header": "<base64-encrypted-header>",
      "header_nonce": "<base64-nonce>",
      "header_key_id": "recipient-key-1",
      "schema_version": "1"
    }'
  ```
</RequestExample>

The Cache treats a failed Directory or chain lookup as an error, not as proof that no policy applies. Network-managed policy delivery remains pinned to the finalized policy decision selected for that delivery attempt.

Chunk metadata uses the same assured-set contract as Relay submission. A Cache stores each opaque envelope but withholds an incomplete set from retrieval. It exposes the set after every declared sequence is present, or purges the incomplete set after its retry window.

## Response

<ResponseField name="accepted" type="boolean" required>
  `true` when the envelope is accepted.
</ResponseField>

<ResponseField name="deduped" type="boolean" required>
  `true` when this Cache already held the same message ID.
</ResponseField>

<ResponseField name="message_id" type="string" required>
  UUID of the accepted envelope.
</ResponseField>

<ResponseField name="recipient" type="string" required>
  Canonical recipient DID used for storage.
</ResponseField>

<ResponseField name="expires_at" type="string" required>
  Absolute ISO-8601 expiration applied to this stored copy.
</ResponseField>

<ResponseField name="max_ttl" type="string" required>
  Maximum clock-time duration allowed by the effective constraints.
</ResponseField>

<ResponseField name="applied_ttl" type="string" required>
  Duration applied to this entry.
</ResponseField>

<ResponseField name="chunked" type="boolean" required>
  Whether this entry is one chunk of a message group.
</ResponseField>

<ResponseField name="code" type="string">
  For a chunk, `chunk_staged` while the declared set is incomplete or `chunk_set_complete` when every sequence is present.
</ResponseField>

<ResponseField name="complete" type="boolean">
  For a chunk, whether the complete assured set is available for retrieval.
</ResponseField>

<ResponseField name="received_chunks" type="integer">
  Number of distinct sequences the Cache currently holds for this set.
</ResponseField>

<ResponseField name="expected_chunks" type="integer">
  Declared `total_chunks` for this set.
</ResponseField>

<ResponseField name="retry_until" type="string">
  For an incomplete set, the ISO-8601 deadline before the Cache may purge it.
</ResponseField>

<ResponseField name="proof" type="object" required>
  Public Cache delivery-event metadata for this entry. Optional `reason` and `signature` keys are absent when not populated.
</ResponseField>

<ResponseField name="policy_id" type="string">
  Network-verified policy ID when a Relay executed an applied policy.
</ResponseField>

<ResponseField name="policy_revision" type="integer">
  Network-verified policy revision when a rule applied.
</ResponseField>

<ResponseField name="rule_id" type="string">
  Network-verified winning rule ID when a rule applied.
</ResponseField>

<ResponseField name="policy_block_hash" type="string">
  Finalized block hash associated with the applied policy decision.
</ResponseField>

The optional policy fields appear at the top level. There is no `policy_resolution` or `cache_placement` response wrapper.

<ResponseExample>
  ```json 202 Response theme={null}
  {
    "accepted": true,
    "deduped": false,
    "message_id": "9f8d6f08-bce5-4df5-b22b-bf8c6bd4e143",
    "recipient": "did:openpayload:1111111111111111111111",
    "expires_at": "2026-07-25T16:30:00Z",
    "max_ttl": "PT48H",
    "applied_ttl": "PT24H",
    "chunked": false,
    "proof": {
      "event_type": "delivery",
      "message_id": "9f8d6f08-bce5-4df5-b22b-bf8c6bd4e143",
      "recipient_did": "did:openpayload:1111111111111111111111",
      "timestamp": "2026-07-24T16:30:01Z"
    }
  }
  ```
</ResponseExample>

## Straight to the point

```http theme={null}
POST /cache/store
Content-Type: application/json

<original encrypted DDN envelope>
```

* Accepted: `202`
* Client policy provenance: prohibited
* Same `message_id`: accepted with `deduped: true`
* Incomplete assured set: stored but hidden from retrieval until complete
* Maximum raw envelope: 25 MiB; maximum non-payload metadata: 64 KiB
* Expired, oversized, or policy-ineligible: rejected


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.