# Data Consistency

The ODUS API is designed for high throughput and low latency. As a result, some read endpoints can reflect a write with a slight delay. This page explains how consistency works across different endpoint types.

## Strongly consistent endpoints

All **write operations** (create, update, authorize, capture, reverse, etc.) return the latest state of the resource in the response body. The returned object always reflects the most recent changes.

**Retrieve-by-ID** endpoints (e.g. `GET /v2/payments/{id}`) are also strongly consistent and always return the latest state.

```
POST /v2/payments/{id}/authorize  →  Returns the up-to-date Payment object

GET  /v2/payments/{id}            →  Always returns the latest state
```

## Eventually consistent endpoints

**List endpoints** (e.g. `GET /v2/payments`, `GET /v2/customers`, `GET /v2/subscriptions`) are optimized for high-volume read traffic. Under normal operating conditions, data is available on list endpoints within a few hundred milliseconds of a write. In rare cases during high load, propagation may take up to one second.

```
GET /v2/payments       →  May have a brief delay after a write

GET /v2/transactions   →  May have a brief delay after a write

GET /v2/subscriptions  →  May have a brief delay after a write
```

note

This applies to all paginated list endpoints across all resources.

## Response caching

Every response carrying merchant data is scoped to the key that requested it, so none of it may be cached. Those responses are returned with:

```
Cache-Control: no-store
```

They carry no `ETag`, and conditional requests (`If-None-Match`, `If-Modified-Since`) are ignored — every request is answered in full, and the API never replies `304 Not Modified`. Configure your HTTP client, proxy, and CDN accordingly: store nothing, and re-request whenever you need current data.

The OpenAPI documents, including the v2 document at `/openapi.v2.json`, are the one exception. They are identical for every caller and change only when the API does, so they are returned with `Cache-Control: no-cache` and an `ETag`: cache them, and send `If-None-Match` to revalidate — you'll get a `304 Not Modified` while your copy is current.

## Best practices

1. **Use the write response as the source of truth.** After creating or updating a resource, use the response body — don't immediately poll the list endpoint.

2. **Don't rely on list endpoints for read-after-write flows.** If you need to confirm a payment was authorized, use the response from `POST /v2/payments/{id}/authorize` or retrieve it by ID with `GET /v2/payments/{id}`.

3. **Webhooks deliver the latest state.** If you receive a webhook event and need the full resource, use the retrieve-by-ID endpoint (`GET /v2/payments/{id}`) which is always strongly consistent.

## Summary

| Endpoint type    | Consistency     | Example                                                 |
| ---------------- | --------------- | ------------------------------------------------------- |
| Write operations | Strong          | `POST /v2/payments`, `POST /v2/payments/{id}/authorize` |
| Retrieve by ID   | Strong          | `GET /v2/payments/{id}`                                 |
| List (paginated) | Eventual (< 1s) | `GET /v2/payments`                                      |
