# `Tipalti.Procurement.PurchaseOrders`
[🔗](https://github.com/iamkanishka/tipalti/blob/main/lib/tipalti/procurement/purchase_orders.ex#L1)

Procurement REST API — purchase order sync.

Backed by `GET /api/v1/resources/pos` and `POST /api/v1/resources/pos`
against `triggers.(sandbox.)approve.com`, authenticated with a static
`x-api-key` header (`config.procurement.api_key`).

Tipalti enforces API-side rate limits on this resource: reads should not
be made more often than every 10 minutes, and updates are limited to
roughly 5 requests/minute. `Tipalti.RateLimiter` is available if you want
to enforce this client-side as well; `Tipalti.Client`/`Tipalti.HTTP`
already retries a 429 with backoff, surfacing `Tipalti.RateLimitError`
(with `:retry_after` populated from the response's `Retry-After` header)
if retries are exhausted.

# `list`

```elixir
@spec list(
  Tipalti.Config.t(),
  keyword()
) :: {:ok, map()} | {:error, Exception.t()}
```

Retrieves purchase orders.

## Options

  * `:force_read_all` — boolean; if `true`, returns all POs regardless of
    change state instead of only those changed since the last read.
  * `:from_date`, `:to_date` — ISO8601 date strings to bound the query.

# `list!`

```elixir
@spec list!(
  Tipalti.Config.t(),
  keyword()
) :: map()
```

# `update`

```elixir
@spec update(Tipalti.Config.t(), map()) :: {:ok, map()} | {:error, Exception.t()}
```

Updates a purchase order's status in Tipalti to reflect its state in your
ERP/system of record — external ID, ERP status, internal document number,
error message, and/or receival info.

    Tipalti.Procurement.PurchaseOrders.update(config, %{
      po_ref_code: "PO-1001",
      external_id: "ERP-98765",
      erp_status: "synced"
    })

# `update!`

```elixir
@spec update!(Tipalti.Config.t(), map()) :: map()
```

---

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