API v1 preview

# List orders

`GET /api/v1/orders`

## Overview

List orders owned by the authenticated account, ordered by updated_at then ID. Returns data, has_more and next_cursor. Keep filters unchanged while paging; payment changes also update updated_at.

Requires `orders:read`.

[Order and payment guide](https://ottomfg.com/docs/orders.md)

[Errors and retries](https://ottomfg.com/docs/errors.md)

Request

```
#!/usr/bin/env bash
# Bash + curl + jq. Requires orders:read.
set -euo pipefail
: "${API_BASE_URL:?Set API_BASE_URL}"
: "${OTTOMFG_API_KEY:?Set OTTOMFG_API_KEY}"
result=$(curl --fail-with-body --silent --show-error --max-time 60 -X GET "${API_BASE_URL%/}/api/v1/orders?limit=20" \
  -H "Authorization: Bearer $OTTOMFG_API_KEY") || { printf '%s\n' "$result"; exit 1; }
printf '%s\n' "$result" | jq .
```

Set API_BASE_URL and OTTOMFG_API_KEY. Save request keys before creating an order or starting payment; reuse the same key and body on retry. See the guide for permissions and recovery.

[Order setup and recovery](https://ottomfg.com/docs/orders.md)

## Parameters

`status` query · optional

Comma-separated statuses, e.g. awaiting_payment,confirmed. OR across values; AND with time filters. Omit for full reconciliation.

array

`updated_since` query · optional

Inclusive lower bound on domain updated_at; repeat on subsequent pages.

string (date-time)

`limit` query · optional

Page size, default 20, maximum 100; repeat on subsequent pages.

integer

`cursor` query · optional

Stateless keyset token containing the last updated_at and id. Never expires; repeat original filters and limit. No frozen snapshot.

string

`external_id` query · optional

Exact optional customer reference. Not unique.

string

`model_id` query · optional

Only orders containing this model, including its historical revisions.

Immutable model ID: MD- followed by eight uppercase Crockford Base32 characters. Use this same ID in the website, URLs and API; pass it unchanged.

string

`search` query · optional

Case-insensitive substring search across order number, recipient name, external reference and purchase order number.

string

`sort` query · optional

Ascending update time for synchronization (default), or newest orders first. Keep all filters and sort unchanged when using a cursor.

string

Allowed values: updated_at, -created_at

## Responses

Live order page.

200 response

JSON

```
{
  "data": [
    {
      "id": "OM-XMF1NT2E",
      "created_at": "2026-09-18T18:00:00.000000Z",
      "quote_id": "quote_6c82bd3e319b4bb099310d54a761879e",
      "currency": "usd",
      "items": [
        {
          "model_id": "MD-739YQ549",
          "quantity": 2,
          "unit_price": 3000,
          "subtotal": 6000,
          "repair": {
            "required": false,
            "applied": false,
            "reason": null,
            "status": "not_applied",
            "fee": 0,
            "covered_by_order_id": null
          },
          "longest_dimension_mm": 100,
          "dimensions_mm": {
            "x": 50,
            "y": 100,
            "z": 40
          }
        }
      ],
      "shipping_address": {
        "name": "Alex Example",
        "company": "Example Retail",
        "line1": "123 Example Street",
        "city": "Seattle",
        "state": "WA",
        "postal_code": "98101",
        "country": "US"
      },
      "buyer": {
        "company": "Example Store",
        "email": "orders@example.com"
      },
      "shipping_option": {
        "id": "shipopt_6c82bd3e319b4bb099310d54a761879e",
        "name": "Standard",
        "totals": {
          "subtotal": 6000,
          "shipping": 1000,
          "total": 7000
        },
        "estimated_transit_business_days": {
          "min": 3,
          "max": 5
        },
        "estimated_delivery": null
      },
      "external_id": "checkout-123",
      "purchase_order_number": "PO-2026-0042",
      "metadata": {
        "project": "launch"
      },
      "updated_at": "2026-09-18T18:00:00.000000Z",
      "status": "awaiting_payment",
      "events": [
        {
          "id": "evt_00000000000000000000000000000001",
          "sequence": 1,
          "type": "order.created",
          "at": "2026-09-18T18:00:00.000000Z",
          "reason": null,
          "data": {
            "status": "awaiting_payment"
          }
        }
      ],
      "estimated_ship_date": null,
      "estimated_delivery": null,
      "hold": null,
      "payment": {
        "status": "unpaid",
        "amount": 7000,
        "currency": "usd",
        "method": null,
        "paid_at": null,
        "receipt_url": null
      },
      "shipment": null,
      "pricing_version": "pv_2026_09_a",
      "preparation": {
        "status": "completed",
        "items": [
          {
            "model_id": "MD-739YQ549",
            "status": "completed",
            "longest_dimension_mm": 100
          }
        ]
      },
      "expires_at": "2026-09-19T18:00:00.000000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

`data` array · required

[Order object](https://ottomfg.com/docs/order-object.md)

`next_cursor` string | null · required

Pass as cursor on the next request. Null when has_more is false.

`has_more` boolean · required

**Response headers**

`X-Request-ID`

Request identifier for support. Send X-Request-ID with 8–64 ASCII letters, digits or hyphens to reuse that value; otherwise the server generates a UUID4 hex value. Include the returned X-Request-ID in support requests. Do not put secrets or account IDs in this value.

## Errors

| HTTP | Code | What to do |
| --- | --- | --- |
| 400 Bad Request | `invalid_argument` | A field, query parameter or header is invalid. Fix the field named in details, then send the request again. |
| 401 Unauthorized | `unauthenticated` | The API key is missing, invalid or revoked. Send a valid business API key in Authorization: Bearer. |
| 403 Forbidden | `permission_denied` | The key lacks the endpoint's scope, or payments lack spending consent. Check the scope listed on the endpoint. |
| 429 Too Many Requests | `resource_exhausted` | A rate or account limit was reached. Wait at least Retry-After seconds, then retry. |
| 500 Internal Server Error | `internal` | The server failed unexpectedly. Retry with backoff; contact support with X-Request-ID if it persists. |
| 503 Service Unavailable | `unavailable` | A required service is briefly unavailable. Retry with backoff, reusing the same Idempotency-Key. |

[Idempotent requests](https://ottomfg.com/docs/idempotency.md)

API v1 preview

Source: https://ottomfg.com/docs/list-orders
