A purchase order (PO) is a document issued by a buyer to a vendor that specifies the items, quantities, and agreed-upon prices for goods or services. POs serve as the authoritative record of what was ordered and at what cost.
Source of truth: Purchase orders originate in your source system (ERP). Ottimate syncs POs from your ERP and stores them for document matching — your ERP remains the authoritative source for purchase order data.
When a PO is created in your source system, you sync it to Ottimate using the Purchase Orders API. Once in Ottimate, POs are used to match against invoices to validate that billed amounts align with what was ordered.
Each PO can be configured for one of two matching workflows:
is_2_way: true when creating the PO. This is common for services or other scenarios where delivery verification is not required.Ottimate tracks the lifecycle of each PO with the following statuses:
It is common for PO line items to carry dimension mappings (e.g., GL account, department, project) from the source ERP. When an invoice is matched to a PO, Ottimate can inherit these dimensions onto the invoice line items — so coding happens automatically based on what was already set on the purchase order.
Dimensions are passed as key-value pairs on each item, keyed by dimension type (e.g., DEPARTMENT, CLASS). Each value must be a plain string — the ERP dimension code or ID (e.g., "erp_dim_dept123"):
The dimensions format in POST/PATCH requests differs from GET responses. GET responses return dimensions as rich objects (with id, erp_dimension_id, name, and code fields). Copying dimensions from a GET response and passing them directly to a POST or PATCH request will return a PO4000 validation error: “Dimension value for ‘X’ must be a string.” Always use the plain string value (the ERP code or ID) when writing dimensions.
Dimensions must exist in Ottimate before they can be referenced on a PO. Dimensions are typically synced from your ERP via an Ottimate-hosted integration, or created directly using the Dimensions API. If a PO request references a dimension that does not exist in Ottimate, the request will return a 400 error.
When creating or updating a PO, providing dimensions on a line item replaces all existing dimensions on that item — include every dimension you want to keep. Omit the field or pass null to leave dimensions unchanged.
The bulk upsert endpoint allows you to create or update multiple POs in a single request. This operation is processed asynchronously.
Rate limits:
The response returns a batch_id that you can use with the Batch progress and Batch results endpoints to track the status of your bulk operation.
When updating a PO via PATCH, note the following restrictions:
status, po_number, external_id, erp_vendor_id, or ottimate_location_idid in the items arrayid field — Ottimate will create them automatically