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

# POST /replicate: Push Write-Behind Replication Chunks

> Upload one or more encrypted differential block chunks to the replication log, with Merkle root verification, billing debit, and split-brain conflict detection.

<style>
  {`
      main, article, .prose {
        margin-left: 2.5cm !important;
        margin-right: 2.5cm !important;
      }
      `}
</style>

The `POST /replicate` endpoint implements write-behind differential state replication. Instead of uploading a full snapshot on every change, you push compact encrypted block diffs — called chunks — along with a Merkle root that covers the full set. The server validates each chunk size, executes credit debits atomically, checks for split-brain conflicts, and confirms persistence. You can push multiple chunks in a single request to amortize round-trip latency.

## Request

```http theme={null}
POST /replicate
Authorization: Bearer <TOKEN>
Content-Type: application/json
```

## Request Body

<ParamField body="chunks" type="array" required>
  Array of one or more replication chunk objects to append to the log. Each element must conform to the chunk schema below.
</ParamField>

<ParamField body="merkle_root" type="string" required>
  64-character SHA-256 hex hash representing the Merkle tree root computed over all chunks in this request.
</ParamField>

### Chunk Object Schema

Each object in the `chunks` array must include:

<ParamField body="chunks[].sequence_number" type="integer" required>
  Monotonic sequence number for this chunk. Must not create gaps relative to the current replication head.
</ParamField>

<ParamField body="chunks[].block_hash" type="string" required>
  64-character SHA-256 hex hash of the packed block in `IV || ciphertext` form. Used for idempotency and split-brain detection.
</ParamField>

<ParamField body="chunks[].ciphertext_b64" type="string" required>
  Base64-encoded packed chunk block. The decoded size must not exceed 256 KB (`chunk_too_large` is returned if it does).
</ParamField>

### Example Request Body

```json theme={null}
{
  "chunks": [
    {
      "sequence_number": 10,
      "block_hash": "f5a2b3c4d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3",
      "ciphertext_b64": "SGVsbG8gV29ybGQ="
    }
  ],
  "merkle_root": "84c8a8d11d95e0cce8da70c1a96c14b7454f738f65429384f9b4f3b7d1597f8c"
}
```

## Billing Costs

| Token Type              | Cost                                                 |
| ----------------------- | ---------------------------------------------------- |
| `sov_proj_` (free tier) | \$0 — no charge                                      |
| `sov_live_` (paid)      | 0.045 milli-cents (0.00045 credits) per decoded byte |

Billing is executed atomically using the `atomic_debit_credits_milli_v2` function. If any part of the transaction fails, the full debit is refunded automatically.

## Idempotency and Split-Brain Conflict Detection

To guarantee absolute recall integrity, the database enforces a unique constraint on the `(agent_id, sequence_number)` pair for every chunk:

**Idempotent retries:** If a chunk's sequence number is already registered and its `block_hash` matches exactly, the server recognises the request as a safe retry and returns `200 OK` with `{ "idempotent": true }` — no credits are charged and no duplicate record is written.

**Split-brain conflict:** If a chunk's sequence number is already registered but the `block_hash` differs, the server detects a split-brain condition (two offline devices diverging on the same sequence slot) and rejects the write with `409 Conflict`:

```json theme={null}
{
  "error": "split_brain_detected",
  "conflicts": [
    {
      "sequence_number": 10,
      "existing_block_hash": "f5a2b3c4...",
      "attempted_block_hash": "e3b0c442..."
    }
  ]
}
```

<Warning>
  A split-brain conflict means two clients wrote different data at the same sequence number. You must resolve this client-side before continuing replication — the server will not auto-merge diverged state.
</Warning>

## Response

### 200 OK — Standard

<ResponseField name="accepted" type="integer">
  Number of chunks successfully written to the replication log.
</ResponseField>

<ResponseField name="sequence_number" type="integer">
  Sequence number of the last accepted chunk.
</ResponseField>

<ResponseField name="merkle_root" type="string">
  Echo of the `merkle_root` submitted in the request, confirming what the server recorded.
</ResponseField>

```json theme={null}
{
  "accepted": 1,
  "sequence_number": 10,
  "merkle_root": "84c8a8d11d95e0cce8da70c1a96c14b7454f738f65429384f9b4f3b7d1597f8c"
}
```

### 200 OK — Idempotent Replay

<ResponseField name="idempotent" type="boolean">
  `true` when the submitted chunk was already registered with a matching `block_hash`. No new record was created and no credits were debited.
</ResponseField>

```json theme={null}
{
  "idempotent": true
}
```

## curl Example

```bash theme={null}
curl -X POST https://ksrlmubaxzwufziwarps.supabase.co/functions/v1/v2-agent-state/replicate \
  -H "Authorization: Bearer sov_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chunks": [
      {
        "sequence_number": 10,
        "block_hash": "f5a2b3c4d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3",
        "ciphertext_b64": "SGVsbG8gV29ybGQ="
      }
    ],
    "merkle_root": "84c8a8d11d95e0cce8da70c1a96c14b7454f738f65429384f9b4f3b7d1597f8c"
  }'
```
