---
title: "list purchase orders"
method: GET
path: "/api/v1/organizations/{organization_id}/purchase-orders"
tags: ["purchase_orders"]
---

# list purchase orders

`GET /api/v1/organizations/{organization_id}/purchase-orders`

## Request

- Base URL: `https://api.app.tightly.io`
- URL: `https://api.app.tightly.io/api/v1/organizations/{organization_id}/purchase-orders`
- Auth: HTTP bearer

A page of purchase orders for one organisation: number, order type, status, supplier, destination location, order and expected delivery dates, total cost and line count, with `filtered_max_size` for the size of the filtered set. Header figures only, so call get_purchase_order for one order's line quantities and its deliveries.

`organization_id` in the path must be the key's own organisation; a key naming another one is refused `organization_mismatch`. Page with `limit` and `offset`, narrow with `filter_args` on status, supplier_id, location_id, date_created, date_drafted, delivery_date, total_cost and has_supplier_updates, and order with `sort_args` over expected_delivery_date, name and quantity_to_manufacture.

Filter the expected delivery date under the key `delivery_date`. `expected_delivery_date` is not a filter key: sent as one it is ignored rather than refused, and every order comes back.

Statuses: Drafted, FullyConfirmed, InProduction, FullyShipped, FullyDelivered, Completed, Cancelled.

`on_hold` says whether a row is held and `hold_reason` why, in the holder's own words. A hold with no reason is refused, so `hold_reason` is set whenever `on_hold` is true and null otherwise. A held order refuses every status advance but cancellation. The full log of who acted and why is `status_audit` on get_purchase_order, not here.

Scope: `purchase_orders:read`.

## Path parameters

- `organization_id` string, required

## Query parameters

- `limit` integer
- `offset` integer
- `filter_args` object[]
- `sort_args` string
- `search` string

## Headers

- `Tightly-Version` string

## Response `200`

A page of purchase orders

- GetPurchaseOrdersResponse
  - `data` union
    - GetPurchaseOrdersPayload
      - `last_updated_po` object, nullable
      - `max_size` integer, required
      - `offset` integer, required
      - `purchase_orders` PurchaseOrderListItem[], required
        - `billed_at` string, nullable
        - `cancel_date` string, nullable: The last day of the ship window, inclusive. After it the buyer may walk away from whatever the vendor has not shipped. Null where the order was placed without a window.
        - `commitment_id` string, nullable
        - `commitment_name` string, nullable
        - `completed_status_updated_at` string, nullable
        - `confirmation_status_updated_at` string, nullable
        - `date_created` string, nullable
        - `date_drafted` string, nullable
        - `delivery_status_updated_at` string, nullable
        - `display_quantity` object, nullable
        - `drafted_status_updated_at` string, nullable
        - `expected_delivery_date` string, nullable
        - `external_id` string, required
        - `has_delivery_delay` boolean
        - `hold_reason` string, nullable: Why the current hold was taken, in the words whoever took it typed. Non-null whenever `on_hold` is true, because a hold with no reason is refused. Null when the order is not held.
        - `id` string, required
        - `integrations` object, nullable
        - `is_active` boolean, required
        - `is_billed` boolean, nullable
        - `is_completed` boolean, required
        - `is_proposal` boolean, required
        - `location_id` string, required
        - `location_name` string, required
        - `manufacturable_id` string, nullable
        - `manufacturable_product_id` string, nullable
        - `manufacturable_product_title` string, nullable
        - `manufacturable_sku` string, nullable
        - `manufacturable_variant_title` string, nullable
        - `name` string, required
        - `on_hold` boolean: True while this order is held. A held order refuses every status advance except cancellation until the hold is released. Never null: an order is held or it is not.
        - `order_type` unknown
        - `owner_name` string, nullable
        - `owner_user_id` string, nullable
        - `production_status_updated_at` string, nullable
        - `purchase_unit_summary` object, nullable
        - `quantity_to_manufacture` integer, nullable
        - `quantity_unit` string, nullable
        - `recommended_location_id` string, nullable
        - `recommended_location_name` string, nullable
        - `recommended_quantity` integer, nullable
        - `request_status_updated_at` string, nullable
        - `ship_window_start` string, nullable: The first day the vendor may ship this order. This is the window the vendor agreed to, not the day the goods are expected: that is `expected_delivery_date`. Null where the order was placed without a window.
        - `shipment_status_updated_at` string, nullable
        - `shortage` boolean, nullable
        - `source_location_id` string, nullable
        - `source_location_name` string, nullable
        - `split` string, nullable
        - `status` 'DRAFTED' | 'FULLY_CONFIRMED' | 'FULLY_SHIPPED' | 'FULLY_DELIVERED' | 'CANCELLED' | 'IN_PRODUCTION' | 'COMPLETED', required
        - `supplier_id` string, nullable
        - `supplier_min_order_value` integer, required: Legacy whole-currency minimum, rounded up conservatively. Use supplier_min_order_value_amount for the exact amount.
        - `supplier_min_order_value_amount` number, nullable: Exact canonical supplier minimum in supplier currency, including fractional units. Null means unstated.
        - `supplier_name` string, nullable
        - `supplier_signals` string[]
        - `total_cost` number, required
        - `total_delivered_quantity` integer, required
        - `total_quantity` integer, required
      - `size` integer, required
      - `status_numbers` object
    - object, nullable
  - `message` PurchaseOrderApiMessage
    - `desc` string
    - `service` string
    - `severity` 'SUCCESS' | 'INFO' | 'ERROR' | 'WARNING'

## Other responses

- `400`: Bad Request - Invalid request parameters or validation errors
- `401`: No usable key: malformed, unknown, revoked, expired or stopped. One refusal covers all five, telling a caller which is which maps the surface for them. A request with no Authorization header at all is refused 400 before any key is looked for.
- `403`: The key may not reach this operation. `scope_missing` when the key does not hold Purchase orders; `organization_mismatch` when the path names an organisation that is not the key's; `ip_not_allowed` when the caller's address is outside the key's allowlist.
- `429`: The key has spent its allowance for this minute. 600 reads and 120 writes a minute, counted per key, refused calls included. `Retry-After` says how long to wait.
- `500`: Internal Server Error - Database connection or processing errors
- `503`: The database is briefly out of reach, which is what a failover or a full connection pool looks like from outside. Wait the seconds `Retry-After` names and send the request again. A read is safe to repeat. A write is not, because the connection was lost in the middle of it, so read the object back before sending it a second time. Branch on the status rather than on `code`, which is `POSTGRES_UNAVAILABLE` from one of the two seams that raise this and `SERVICE_UNAVAILABLE` from the other.

---

[API](https://skmtc.dev/tightly/apis/tightly-api.md) · [All operations](https://skmtc.dev/tightly/apis/tightly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tightly/apis/tightly-api/revisions/199f7eb35afb?raw)
