---
title: "Creates a Purchase order"
method: POST
path: "/api/2026-10-01/resources/procurement/purchase_orders"
tags: ["Procurement > PurchaseOrder"]
---

# Creates a Purchase order

`POST /api/2026-10-01/resources/procurement/purchase_orders`

## Request

- Base URL: `https://api.factorialhr.com`
- URL: `https://api.factorialhr.com/api/2026-10-01/resources/procurement/purchase_orders`
- Auth: API key in header `x-api-key`

Create a standalone purchase order (e.g. pushed by an ERP integrator), not linked to any purchase request. The purchase order is pinned to the company's ACTIVE purchase order template version; template fields are addressed by their stable field_key and validated against that version: unknown field keys, missing required fields and reference values that do not resolve in the company are all rejected with a field-keyed 422. A vendor_id or legal_entity_id that does not exist or is not visible to the credential is rejected earlier by the platform resource check (400).

## Request body

- object
  - `company_id` string, required: Company identifier, refers to /api/me endpoint.
  - `legal_entity_id` string, required: Identifier of the legal entity that owns the purchase order. Must belong to the company.
  - `vendor_id` string: Identifier of the vendor (Finance contact) by internal Factorial id. Vendors synced from an external system must be resolved to their Factorial id first (e.g. via the vendors read endpoint).
  - `currency` string, required: Currency code in ISO 4217 format.
  - `date` string: Purchase order date. Defaults to today when omitted.
  - `deadline` string: Deadline date for the purchase order delivery or completion.
  - `status` 'draft' | 'pending' | 'ordered' | 'partial' | 'received' | 'closed': Status of the purchase order. Defaults to `draft`. `processing` is an internal transient status and is rejected.
  - `description` string: Description or notes about the purchase order.
  - `preferred_payment_method` 'banktransfer' | 'cash' | 'virtualcard': Preferred payment method for this purchase order.
  - `header_field_values` object[]: Header field values of the ACTIVE purchase order template version, as an array of `{field_key, value}` pairs. Only custom (non-predefined, non-computed) field keys are accepted; predefined fields (vendor, order_date, currency, due_date, payment_method, legal_entity) are populated from the corresponding top-level parameters. Reference fields (employee, cost_center, project, tax_rate, team) take the referenced internal id as the value. If a field_key appears more than once, the last occurrence wins.
    - `field_key` string, required: Stable field key of the template field.
    - `value` string: Value for the field.
  - `line_items` object[]: Line items of the purchase order, each carrying its values as an array of `{field_key, value}` pairs addressed by the line-item field keys of the ACTIVE template version (e.g. concept, quantity, unit_price, tax_rate). Computed keys (subtotal, tax_amount, total, discount_amount) are derived server-side and rejected as input.
    - `position` integer, required: Zero-based position of the line item.
    - `fields` object[], required: Line-item values as `{field_key, value}` pairs.
      - `field_key` string, required
      - `value` string

## Response `201`

CREATED

- ProcurementPurchaseOrder
  - `id` string, required: Unique identifier of the purchase order
  - `po_number` integer, required: Purchase order number assigned to this order
  - `description` string, required: Description or notes about the purchase order
  - `status` 'processing' | 'draft' | 'pending' | 'ordered' | 'partial' | 'received' | 'closed', required: Current status of the purchase order
  - `cost` object, required: Total cost of the purchase order
    - `cents` integer, required: Total cost in cents (smallest currency unit)
    - `currency` string, required: Currency code in ISO 4217 format
  - `date` string, required: Date when the purchase order was created
  - `deadline` string: Deadline date for the purchase order delivery or completion. Writable through the update endpoint (omitted or null keeps it); readable here so the GET -> modify -> PUT roundtrip is complete.
  - `vendor_id` string: Identifier of the vendor (contact) associated with this purchase order
  - `purchase_request_id` string: Identifier of the purchase request that generated this purchase order, if any. Externally-created purchase orders (e.g. synced from an ERP) have no purchase request.
  - `legal_entity_id` string, required: Identifier of the legal entity that owns this purchase order
  - `company_id` string, required: Identifier of the company that owns this purchase order
  - `formatted_po_number` string, required: Formatted purchase order number with prefix (e.g., PO-00001)
  - `preferred_payment_method` 'banktransfer' | 'cash' | 'virtualcard': Preferred payment method for this purchase order
  - `po_template_version_id` string: Identifier of the pinned PO template version this purchase order uses. Fetch that version (and its field definitions) to interpret the purchase order's header and line-item field keys. Null for legacy purchase orders created without a template.
  - `header_field_values_by_key` object[]: Custom header field values, addressed by the field_key of the purchase order's PINNED template version, as an array of `{field_key, value}` pairs — exactly the shape the update endpoint accepts, so a GET -> modify -> PUT roundtrip works verbatim. Predefined fields (vendor, order_date, currency, due_date, payment_method, legal_entity) surface as top-level parameters instead, and computed or hidden values never appear (they are preserved server-side on update). Null for purchase orders without a template version.
    - `field_key` string, required
    - `value` string
  - `line_items_by_key` object[]: Line items with their field values addressed by the field_key of the purchase order's PINNED template version — the same shape the update endpoint accepts: modify and send the whole set back. Rows are addressed by id (rows without an id are created, persisted rows missing from the set are deleted). Null for purchase orders without a template version.
    - `id` string, required: Identifier of the line item row.
    - `position` integer, required: Zero-based position of the line item.
    - `fields` object[], required: Line-item values as `{field_key, value}` pairs.
      - `field_key` string, required
      - `value` string

## Changes

- **2026-11-03** `83ac9aa1de50`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/factorialhr/apis/factorial-api/changes/api/2026-10-01/resources/procurement/purchase_orders/post.md)

---

[API](https://skmtc.dev/factorialhr/apis/factorial-api.md) - [All operations](https://skmtc.dev/factorialhr/apis/factorial-api/llms.txt) - [OpenAPI document](https://skmtc.dev/factorialhr/apis/factorial-api/revisions/83ac9aa1de50?raw)
