# `Codat.ModifiedDates`
[🔗](https://github.com/iamkanishka/codat.git/blob/v1.0.0/lib/codat/modified_dates.ex#L1)

Helpers for incremental data fetching using Codat's `modifiedAfter` parameter.

Codat tracks a `modifiedDate` on every record — the last time a record was
created, updated, or deleted in the integration. Use `modifiedAfter` to fetch
only records that changed since your last sync, dramatically reducing data
transfer for ongoing synchronisation.

## How It Works

Codat sets `modifiedDate` when:
- A record is first pulled from the integration
- Codat detects a change to the record in a subsequent sync
- A record is deleted (the record remains but `modifiedDate` updates)

> **Important:** `modifiedDate` reflects when Codat **detected** the change,
> not when the change occurred in the accounting platform. There may be a
> delay between the accounting system change and Codat's detection.

## Usage

    # Track your last sync time
    last_sync_at = DateTime.utc_now() |> DateTime.add(-86400, :second)  # 24h ago

    # Fetch only changed invoices
    {:ok, page} = Codat.Accounting.Invoices.list(client, company_id,
      modified_after: last_sync_at
    )

    # Or as an ISO8601 string
    {:ok, page} = Codat.Accounting.Invoices.list(client, company_id,
      modified_after: "2024-01-15T10:00:00Z"
    )

## Recommended Pattern

    defmodule MyApp.InvoiceSync do
      def sync(client, company_id) do
        last_synced_at = MyApp.SyncState.get_last_synced_at(:invoices, company_id)

        Codat.Accounting.Invoices.stream(client, company_id,
          modified_after: last_synced_at,
          page_size: 100
        )
        |> Stream.each(fn invoice ->
          MyApp.Invoices.upsert(invoice)
        end)
        |> Stream.run()

        MyApp.SyncState.update_last_synced_at(:invoices, company_id, DateTime.utc_now())
      end
    end

# `add_to_params`

```elixir
@spec add_to_params(
  keyword(),
  DateTime.t() | String.t() | nil
) :: keyword()
```

Builds a `modifiedAfter` query parameter from a datetime and merges it
into an existing params keyword list.

Called automatically by `Codat.Pagination.to_params/1` when `:modified_after`
is present in opts.

## Example

    params = Codat.ModifiedDates.add_to_params(
      [pageNumber: 1, pageSize: 100],
      ~U[2024-01-15 10:00:00Z]
    )
    # => [modifiedAfter: "2024-01-15T10:00:00Z", pageNumber: 1, pageSize: 100]

# `to_param`

```elixir
@spec to_param(DateTime.t() | String.t() | nil) :: String.t() | nil
```

Converts a `modified_after` option value to the Codat `modifiedAfter` query parameter.

Accepts:
- A `DateTime` struct
- An ISO8601 string (passed through as-is)
- `nil` (omitted from params)

## Example

    iex> Codat.ModifiedDates.to_param(~U[2024-01-15 10:00:00Z])
    "2024-01-15T10:00:00Z"

    iex> Codat.ModifiedDates.to_param("2024-01-15T10:00:00Z")
    "2024-01-15T10:00:00Z"

    iex> Codat.ModifiedDates.to_param(nil)
    nil

---

*Consult [api-reference.md](api-reference.md) for complete listing*
