> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omnicommerce.sg/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Order

> Create a native `agentic` order with line items. Supports `status`, `currency`, `country`, `totalAmount`, and per-line `price` / `unitPrice` / `paidPrice` / `costPrice`. When `productId` is provided, missing price/currency may resolve from the product catalog; explicit `costPrice` upserts `product_data.costPrice` and is snapshotted on the line. Omitted `costPrice` never clears existing product cost. When `country` is empty, Omni may derive marketplace country from order currency (e.g. PHP→philippines; USD is not guessed). Reuses the same upsert path as agentic checkout completion. Requires `orders:write`. Re-posting the same `externalOrderId` updates the existing order instead of creating a duplicate — partners who store one row per SKU should reuse the marketplace order id as `externalOrderId` and put their unique row id on `items[].externalOrderItemId`. When `totalAmount` is omitted, the order total is recomputed from all lines after upsert.



## OpenAPI

````yaml /openapi.json post /api/v1/orders
openapi: 3.1.0
info:
  title: OmniCommerce API
  version: 1.0.0
  license:
    name: Proprietary
    url: https://omnicommerce.sg/terms
  description: >-
    OmniCommerce API surface for agents and developer integrations. Includes
    public endpoints (merchant discovery, product search, compare, catalog, ACO
    retrieval) and authenticated endpoints (product management via API key
    Bearer tokens).
servers:
  - url: https://omnicommerce.sg
    description: Production
  - url: http://localhost:3000
    description: Local development
security: []
tags:
  - name: agentic-checkout
    description: Merchant-fulfilled agentic checkout
    x-group: Agentic Checkout
  - name: commerce
    description: Root commerce discovery
    x-group: Commerce
  - name: developer-platform
    description: Authenticated developer platform APIs
    x-group: Developer Platform
  - name: looks
    description: AI-styled product looks
    x-group: Looks
  - name: oauth
    description: OAuth token endpoints
    x-group: OAuth
  - name: orders
    description: Workspace and agentic orders
    x-group: Orders
  - name: organizations
    description: Organization management
    x-group: Organizations
  - name: price-books
    description: Marketplace list-price markup rules
    x-group: Price Books
  - name: products
    description: Product CRUD, bulk import, and publish
    x-group: Products
  - name: promotions
    description: Central promotions and marketplace sync
    x-group: Promotions
  - name: public-agent
    description: Public agent discovery and catalog APIs
    x-group: Public Agent
  - name: settlements
    description: settlements
    x-group: Settlements
  - name: ucp
    description: Universal Commerce Protocol
    x-group: UCP
paths:
  /api/v1/orders:
    post:
      tags:
        - orders
      summary: Create Order
      description: >-
        Create a native `agentic` order with line items. Supports `status`,
        `currency`, `country`, `totalAmount`, and per-line `price` / `unitPrice`
        / `paidPrice` / `costPrice`. When `productId` is provided, missing
        price/currency may resolve from the product catalog; explicit
        `costPrice` upserts `product_data.costPrice` and is snapshotted on the
        line. Omitted `costPrice` never clears existing product cost. When
        `country` is empty, Omni may derive marketplace country from order
        currency (e.g. PHP→philippines; USD is not guessed). Reuses the same
        upsert path as agentic checkout completion. Requires `orders:write`.
        Re-posting the same `externalOrderId` updates the existing order instead
        of creating a duplicate — partners who store one row per SKU should
        reuse the marketplace order id as `externalOrderId` and put their unique
        row id on `items[].externalOrderItemId`. When `totalAmount` is omitted,
        the order total is recomputed from all lines after upsert.
      operationId: post_v1_orders
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
                - items
              properties:
                organizationId:
                  type: string
                  maxLength: 120
                  description: >-
                    Optional for OAuth clients bound to one organization;
                    required when the caller can access multiple organizations.
                externalOrderId:
                  type: string
                  maxLength: 160
                  description: >-
                    Stable external order identifier and upsert key (unique per
                    org + agentic platform). For marketplace recon (e.g.
                    Zalora), use the marketplace order number — not a partner
                    per-SKU row id. When omitted, OmniCommerce generates a
                    developer order ID. Re-posting the same value upserts the
                    same order and appends/updates lines by externalOrderItemId.
                externalOrderNumber:
                  type: string
                  maxLength: 160
                  description: >-
                    Customer-facing order number. Defaults to externalOrderId
                    when omitted.
                platform:
                  type: string
                  enum:
                    - agentic
                  default: agentic
                status:
                  type: string
                  enum:
                    - pending
                    - to_ship
                    - shipped
                    - completed
                    - return
                    - canceled
                  default: pending
                  description: >-
                    Canonical order status. Same enum as PATCH
                    /api/v1/orders/{orderId}.
                currency:
                  type: string
                  minLength: 3
                  maxLength: 3
                  description: >-
                    ISO-4217 order currency. Prefer marketplace market currency
                    for recon (e.g. PHP for Zalora PH). When country is empty,
                    unambiguous market currencies also derive country
                    (SGD→singapore, MYR→malaysia, PHP→philippines, HKD→hong
                    kong, etc.). USD is not used to derive country.
                totalAmount:
                  type: number
                  minimum: 0
                  description: >-
                    Order total. When omitted, Omni recomputes from all line
                    paid/unit prices × quantity after item upsert (safe for
                    sequential one-line-at-a-time multi-SKU pushes). When
                    provided, the explicit value is stored as-is.
                shippingFee:
                  type: number
                  minimum: 0
                discountAmount:
                  type: number
                  minimum: 0
                country:
                  type: string
                  maxLength: 80
                  description: >-
                    Marketplace country (code or name, e.g. SG, singapore, PH,
                    philippines). Optional. When omitted or empty, Omni derives
                    from order currency when unambiguous (SGD→singapore,
                    MYR→malaysia, PHP→philippines, HKD→hong kong, THB→thailand,
                    VND→vietnam, IDR→indonesia, TWD→taiwan, BRL→brazil).
                    Explicit country always wins. Shipping address country is
                    used when top-level country is omitted. Stored as a
                    canonical full name when possible.
                accountId:
                  type: string
                  maxLength: 160
                buyer:
                  type: object
                  additionalProperties: true
                  properties:
                    name:
                      type: string
                      maxLength: 200
                    email:
                      type: string
                      maxLength: 320
                    phone:
                      type: string
                      maxLength: 80
                shippingAddress:
                  type: object
                  additionalProperties: true
                  properties:
                    name:
                      type: string
                      maxLength: 200
                    line1:
                      type: string
                      maxLength: 300
                    line2:
                      type: string
                      maxLength: 300
                    city:
                      type: string
                      maxLength: 160
                    region:
                      type: string
                      maxLength: 160
                    postalCode:
                      type: string
                      maxLength: 80
                    country:
                      type: string
                      maxLength: 80
                billingAddress:
                  type: object
                  additionalProperties: true
                  properties:
                    name:
                      type: string
                      maxLength: 200
                    line1:
                      type: string
                      maxLength: 300
                    line2:
                      type: string
                      maxLength: 300
                    city:
                      type: string
                      maxLength: 160
                    region:
                      type: string
                      maxLength: 160
                    postalCode:
                      type: string
                      maxLength: 80
                    country:
                      type: string
                      maxLength: 80
                orderCreatedAt:
                  type: string
                  format: date-time
                  description: >-
                    Order created timestamp (ISO 8601 with timezone). Defaults
                    to now. Re-posting the same externalOrderId does not
                    overwrite an existing created date; use PATCH
                    /api/v1/orders/{orderId} to correct it.
                orderUpdatedAt:
                  type: string
                  format: date-time
                items:
                  type: array
                  minItems: 1
                  maxItems: 100
                  description: >-
                    Order lines. Partners with one row per SKU can send one item
                    per request or all items in one request; reuse the same
                    externalOrderId and distinct externalOrderItemId values.
                  items:
                    type: object
                    additionalProperties: false
                    required:
                      - productName
                      - quantity
                    properties:
                      externalOrderItemId:
                        type: string
                        maxLength: 160
                        description: >-
                          Stable line identifier used for upserts and
                          marketplace recon (e.g. Zalora order item id, or a
                          partner per-SKU row id). When omitted, Omni generates
                          `{externalOrderId}-{index}`. Prefer setting this when
                          partners store one row per SKU.
                      productId:
                        type: string
                        format: uuid
                      productName:
                        type: string
                        minLength: 1
                        maxLength: 500
                      sku:
                        type: string
                        maxLength: 160
                      sellerSku:
                        type: string
                        maxLength: 160
                        description: >-
                          Seller SKU. Used as a secondary match key for
                          marketplace recon (e.g. Zalora) when unique on the
                          order.
                      shopSku:
                        type: string
                        maxLength: 160
                      quantity:
                        type: integer
                        minimum: 1
                        maximum: 9999
                      price:
                        type: number
                        minimum: 0
                        description: >-
                          Alias for `unitPrice` (list / original unit price).
                          Prefer `unitPrice` on new integrations. When list and
                          paid amounts are the same, you may send only `price`
                          or only `paidPrice`. When omitted together with
                          unitPrice/paidPrice, may resolve from the product
                          catalog if productId is provided.
                      unitPrice:
                        type: number
                        minimum: 0
                        description: >-
                          Per-unit list / original (sticker) price before line
                          discounts. Same meaning as `price`. Not the order
                          total. Use with `paidPrice` when you need list vs
                          discounted; otherwise one of unitPrice/price/paidPrice
                          is enough.
                      paidPrice:
                        type: number
                        minimum: 0
                        description: >-
                          Per-unit amount actually charged after discounts (what
                          the buyer paid for one unit). Preferred for order
                          totals, GMV, and return refund estimates: total line
                          money uses paidPrice×quantity when set, else
                          unitPrice/price×quantity. Not COGS (see costPrice).
                          Not marketplace fees.
                      costPrice:
                        type: number
                        minimum: 0
                        description: >-
                          Unit cost (COGS). When provided with productId,
                          updates the reusable product_data.costPrice catalog
                          default. The metadata.costPrice order-line snapshot is
                          canonical for historical P&L. Omitted costPrice never
                          clears existing product or line cost. When omitted
                          with productId on create, the line snapshot may
                          resolve from the product catalog. Distinct from
                          price/unitPrice/paidPrice (selling prices). Stored in
                          the local/target currency after FX when
                          costPriceCurrency is set.
                      costPriceCurrency:
                        type: string
                        minLength: 3
                        maxLength: 3
                        description: >-
                          ISO currency of the raw costPrice (e.g. USD) before
                          conversion. Required when cost is not already in the
                          order/line currency. Alias: costCurrency.
                      costCurrency:
                        type: string
                        minLength: 3
                        maxLength: 3
                        description: Alias for costPriceCurrency.
                      costPriceFxRate:
                        type: number
                        exclusiveMinimum: 0
                        description: >-
                          Manual FX rate: units of costPriceFxTo per 1 unit of
                          costPriceCurrency (USD→MYR at 4.45 means 1 USD = 4.45
                          MYR). Omit to auto-fetch the rate from Frankfurter
                          (ECB daily rates).
                      costPriceFxTo:
                        type: string
                        minLength: 3
                        maxLength: 3
                        description: >-
                          Target currency for the conversion. Defaults to the
                          line currency, then the order currency, and must match
                          that accounting currency when one is present.
                      costPriceFxAsOf:
                        type: string
                        pattern: ^\d{4}-\d{2}(-\d{2})?$
                        description: >-
                          Pins the auto-fetched rate to a date: YYYY-MM-DD, or
                          YYYY-MM for the last calendar day of that month. Omit
                          to use the latest rate.
                      currency:
                        type: string
                        minLength: 3
                        maxLength: 3
                      status:
                        type: string
                        enum:
                          - pending
                          - to_ship
                          - shipped
                          - completed
                          - return
                          - canceled
                        description: Canonical order status for the line item.
                      imageUrl:
                        type: string
                        format: uri
                        maxLength: 2048
                      variation:
                        type: string
                        maxLength: 500
                      metadata:
                        type: object
                        additionalProperties: true
                metadata:
                  type: object
                  additionalProperties: true
            examples:
              singleLine:
                summary: Single-line agentic order
                value:
                  organizationId: org_123
                  externalOrderId: partner-order-1001
                  externalOrderNumber: PO-1001
                  status: pending
                  currency: USD
                  totalAmount: 49.99
                  buyer:
                    name: Alex Buyer
                    email: alex@example.com
                  shippingAddress:
                    line1: 123 Market Street
                    city: Singapore
                    country: SG
                  items:
                    - productId: 11111111-1111-4111-8111-111111111111
                      productName: Linen Wrap Dress
                      sku: DRESS-001
                      quantity: 1
                      price: 49.99
                      unitPrice: 49.99
                      paidPrice: 49.99
                      costPrice: 20
                      currency: USD
              multiSkuMarketplaceCart:
                summary: >-
                  Multi-SKU marketplace cart (one Omni order; partner row ids as
                  line ids)
                description: >-
                  Use the marketplace order id as externalOrderId. Put each
                  partner per-SKU row id on externalOrderItemId. Omit
                  totalAmount so Omni recomputes from all lines when appending.
                value:
                  organizationId: org_123
                  externalOrderId: '3012345678'
                  externalOrderNumber: '3012345678'
                  status: to_ship
                  currency: SGD
                  items:
                    - externalOrderItemId: ORD-9001
                      sku: SKU-A
                      sellerSku: SKU-A
                      productName: Item A
                      quantity: 1
                      paidPrice: 50
                      currency: SGD
                    - externalOrderItemId: ORD-9002
                      sku: SKU-B
                      sellerSku: SKU-B
                      productName: Item B
                      quantity: 1
                      paidPrice: 40
                      currency: SGD
      responses:
        '200':
          description: Existing order updated for the same platform/externalOrderId pair.
          content:
            application/json:
              schema:
                type: object
        '201':
          description: Order created.
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
        '403':
          description: Forbidden or missing `orders:write` scope
        '429':
          description: Rate limit exceeded
        '500':
          description: Internal Server Error
      security:
        - bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        Bearer API key for server-to-server access. Session auth is also
        supported in first-party UI flows.

````