Overview

SoftCo supports two invoicing models. For non-PO invoices — expenses, ad-hoc services, or spend that does not require a formal commitment — invoices are coded and approved directly within SoftCo without any upstream purchase order. For PO-based invoices — where your organisation's procurement policy requires a purchase order before a supplier can invoice — SoftCo needs visibility of those POs from your ERP in order to validate and match against them. This API serves that second scenario.

The Purchase Orders API lets your ERP push purchase order data directly into SoftCo's AP platform, making each PO available for automated invoice matching. Once a PO is received, SoftCo can compare incoming supplier invoices against the committed quantities, unit prices, and GL coding on the order — reducing manual coding effort and accelerating invoice processing. Organisations using three-way matching can additionally pair this with the Goods Received API, requiring a confirmed receipt before an invoice can be approved.

A single call to POST /purchase-orders/v1 submits one or more complete purchase orders. Each order includes a header with order details and supplier information, together with one or more line items carrying the pricing, quantities, and GL coding that SoftCo needs for matching. SoftCo uses the po_number as the primary reference when matching supplier invoices.

Where Purchase Orders fit in the AP workflow

SoftCo's AP platform is the system of record for invoice processing. When a supplier invoice arrives that references a purchase order, SoftCo looks up the PO your ERP has already sent via this API and compares the invoice against it — validating the supplier, quantities, and unit prices. Invoices that match within tolerance can be auto-approved; those outside tolerance are routed for review. For organisations that also use non-PO invoicing, both flows coexist: PO-referenced invoices are matched automatically, while non-PO invoices follow a direct coding and approval workflow. The richer the PO data you send, the more effectively SoftCo can automate the matching process.

Two-level data structure

The Purchase Orders API uses a two-level payload structure. Header fields carry PO-level information — the order number, dates, supplier, totals, and delivery addresses. Line item fields (nested in the rows array) carry line-level detail — quantities, pricing, GL codes, and accounting objects. Both levels are submitted together in a single request.

When to call this endpoint

When a PO is raised or approved in your ERP — send the PO to SoftCo immediately, or as part of a scheduled sync, so SoftCo is ready to match when the supplier invoice arrives.
When a PO is amended or revised — resend the full updated PO. SoftCo will refresh the record using the same po_number. Use revision_number to indicate the amendment version.
During initial data migration — you can batch multiple POs in a single request to catch SoftCo up on open commitments from your ERP.
Resending is safe

Resubmitting a PO that SoftCo has already received refreshes the record without creating a duplicate. This makes it straightforward to resend after a correction or to replay a batch.

Quick Start

The minimum viable PO request — a single order with two line items. Copy this, swap in your credentials and real PO data, and send. The required fields at header level are record_id, po_number, supplier_number, and po_date. Each line item in the rows array requires row_id, line_number, quantity, uom, unit_price, and receipting_required.

Quick Start — Single Purchase Order
POST /purchase-orders/v1
x-api-key:     your-api-key-here
Content-Type:  application/Json
Client_Id:     your-client-id
Client_Secret: your-client-secret

{
  "objects": {
    "object": {
      "record": [
        {
          "organization":    "main",
          "record_id":       "1",
          "po_number":       "PO-2024-00891",
          "po_date":         "2024-03-15",
          "supplier_number": "SUP-001234",
          "supplier_name":   "Acme Office Supplies Ltd",
          "currency":        "EUR",
          "po_net_total":    1250.00,
          "po_gross_total":  1537.50,
          "rows": [
            {
              "row_id":              "1",
              "line_number":         1,
              "line_description":    "A4 Copy Paper — 5 Ream Box",
              "quantity":            10,
              "uom":                 "BOX",
              "unit_price":          62.50,
              "row_net_total":       625.00,
              "receipting_required": "true"
              "gl_code":             "6100"
            },
            {
              "row_id":              "2",
              "line_number":         2,
              "line_description":    "Printer Ink Cartridge — Black",
              "quantity":            5,
              "uom":                 "EA",
              "unit_price":          125.00,
              "row_net_total":       625.00,
              "receipting_required": "true"
              "gl_code":             "6100"
            }
          ]
        }
      ]
    }
  }
}

A successful response looks like this:

202 Accepted — you're done
{
  "status":      "SUCCESS",
  "total":       1,
  "succeeded":   1,
  "failed":      0,
  "errors":      [],
  "message":     "All records processed successfully."
}
What happens next

A 202 Accepted means your purchase order has been validated and queued. The integration layer picks it up, transforms it into SoftCo's internal format, and delivers it for AP processing. The PO will be available for invoice matching once delivered. If it does not appear within a few minutes, see the Troubleshooting section.

How It Works

Every request follows the same pipeline. Your system sends once — validation, transformation, and delivery to SoftCo are handled automatically.

Your ERP
HTTP POST
JSON
API Gateway
Auth & Routing
Validated
Integration
Layer
Validate & Transform
XML
Integration
Queue
Async Buffer
Delivered
SoftCo
AP
PO Available
1
Your ERP sends the POST request
After raising or approving a purchase order, your ERP sends a JSON payload to POST /purchase-orders/v1 with your credentials and one or more complete PO records — each containing a header and at least one line item in the rows array.
2
Gateway checks your credentials
Your API key is validated immediately by the API Gateway. An invalid or missing key returns 401 Unauthorized before your payload is processed.
3
Your payload is validated against the PO schema
The integration layer checks your JSON against the purchase order schema — the envelope structure, required header fields, and the presence and structure of the rows array. If anything fails, you get a 400 Bad Request with a field-level error message. Nothing is queued until validation passes.
4
Data is transformed and queued — you get 202
On success, the PO data is transformed into SoftCo's internal format and placed on the integration queue. You receive 202 Accepted immediately — no further action is needed from your side.
5
SoftCo receives the PO and makes it available for matching
The queue listener delivers the purchase order to SoftCo AP, where it is indexed by po_number and made available for invoice matching. If SoftCo is temporarily unavailable, the queue holds the record and retries delivery automatically.
About the 202 Response

202 Accepted does not mean the PO is available in SoftCo yet — it means your request has been received, validated, and queued successfully. Delivery to SoftCo AP is asynchronous and typically completes within minutes. Resending a PO is always safe; SoftCo will refresh the record using the po_number as the key. If a PO does not appear after a reasonable period, contact your SoftCo Customer Success representative.

Rate Limits

Rate limits are configured per customer during onboarding. If you receive a 429 Too Many Requests response, reduce your request rate and retry after a short delay. For your specific rate limit thresholds, contact your SoftCo Customer Success representative.

Authentication

All requests require an API key and OAuth 2.0 credentials. Your credentials are provided during onboarding — keep them secure and never expose them in client-side code or version control.

Requests with a missing or invalid API key are rejected by the gateway immediately and never reach the integration layer.

Required Headers

HeaderValueNotes
x-api-keyYour assigned API keyProvided at onboarding. Required on every request.
Client_IdOAuth 2.0 Client IDProvided at onboarding.
Client_SecretOAuth 2.0 Client SecretTreat as a password — do not share or log.
Access_Token_URLOAuth 2.0 token endpointProvided at onboarding.
Content-Typeapplication/JsonMust be present on every POST request.
Lost or compromised credentials?

Contact your SoftCo Customer Success representative immediately to rotate your API key. Do not attempt to use the same credentials across multiple customer environments.

Response Codes

CodeStatusMeaningWhat to do
202AcceptedPayload validated and queued. Delivery to SoftCo is in progress.Nothing — your purchase order is on its way.
207Multi-StatusBatch partially accepted. Valid records were queued; one or more failed validation. Check the errors array for details on failing records.Inspect the errors array by record index, correct the failing records, and resubmit only those that failed.
400Bad RequestPayload failed schema validation. A field-level error is in the response body.Read the message and errors fields, fix the payload, retry. See Troubleshooting.
401UnauthorizedAPI key missing or invalid.Check your x-api-key header value.
403ForbiddenValid API key but no permission for this endpoint.Contact your SoftCo Customer Success representative.
404Not FoundEndpoint path is incorrect.Verify the URL — check for typos or trailing slashes.
408Request TimeoutRequest took too long to process.Retry once after a short delay.
429Too Many RequestsRate limit exceeded.Slow your request rate and retry after the delay indicated.
500Internal Server ErrorUnexpected error on our side.Retry once. If it persists, raise a ticket with the requestId.
503Service UnavailableService temporarily unavailable.Retry after a short delay.

POST /purchase-orders/v1

Submit one or more purchase orders to SoftCo. Each record contains a PO header with supplier and address information, and a rows array with one or more line items. The payload is validated and queued for delivery to SoftCo AP, where the PO becomes available for invoice matching by po_number.

POST /purchase-orders/v1

Request Headers

HeaderValue
x-api-keyYour assigned API key.
Content-Typeapplication/Json
Client_IdYour OAuth 2.0 Client ID.
Client_SecretYour OAuth 2.0 Client Secret.
Access_Token_URLYour OAuth 2.0 token endpoint URL.

Request Body

The Purchase Orders API uses the standard SoftCo iPaaS envelope: objects → object → record. For all PO requests, record is a JSON array. Each record carries PO header fields and a nested rows array of line item objects.

Single purchase order

"objects" // root — plain JSON object
"object" // container — plain JSON object
"record" // JSON array of PO records
[ { // a single PO record
"po_number": "string" // required — primary matching key
"po_date": "string" // required — YYYY-MM-DD
"supplier_number": "string" // required
... other header fields ...
"rows": [ // array of line items — at least one required
{ "row_id": "string", "line_number": "string", "quantity": "string", "uom": "string", "unit_price": "string", ... }
]
} ]

Batch (multiple purchase orders)

"objects" // root — plain JSON object
"object" // container — plain JSON object
"record" // array — each element is one complete PO
[ { "po_number": "PO-001", ..., "rows": [ {...} ] },
{ "po_number": "PO-002", ..., "rows": [ {...}, {...} ] } ]

Field Reference

The Purchase Orders API carries 61 fields across two levels: PO header fields that apply to the entire order, and line item fields nested within the rows array. The tables below cover each group in turn.

PO Header Fields

These fields sit directly within each record object and describe the purchase order as a whole — the order reference, dates, totals, and parties involved.

Field Type Required Description
organization string Recommended The SoftCo organisation entity this PO belongs to. If omitted, the integration defaults this value to "main".
Defaults to "main" if omitted.
system string Optional Identifier for the source system submitting the PO — for example the name or instance of your ERP. Used for traceability and audit purposes.
record_id string Required Your system's internal reference for this record submission. Useful for correlating API submissions back to records in your ERP for troubleshooting.
po_number string Required The purchase order number from your ERP. This is the primary key SoftCo uses to match incoming supplier invoices to a purchase commitment. Must be unique per order.
e.g. "PO-2024-00891"
po_type string Optional Indicates whether the purchase order is being created, updated, or closed. Accepted values are:
NEWUPDATECLOSE
Caution : Once a purchase order is marked as closed, it cannot be reopened for invoicing.
revision_number string Optional The amendment version of this PO. Increment each time the PO is revised and resent to SoftCo. Helps SoftCo track which version of a PO is current.
e.g. "0""1""2"
creation_date string Optional The date the PO was originally created in your ERP. Format: YYYY-MM-DD.
e.g. "2024-03-10"
po_date string Required The effective date of the purchase order. This is the date the order was raised or approved and is used by SoftCo for period-based matching and reporting. Format: YYYY-MM-DD.
e.g. "2024-03-15"
currency string Recommended The currency of the purchase order using ISO 4217 three-letter currency codes. Required for accurate invoice matching when your organisation operates across multiple currencies.
"EUR""USD""GBP"
buyer string Optional The name or identifier of the employee or user who raised the purchase order. Used for ownership and approval tracking in SoftCo.
e.g. "Jane Murphy"
approver string Optional The name or identifier of the person who approved the purchase order in your ERP. Carried through to SoftCo for audit trail and invoice routing purposes.
e.g. "Tom Walsh"
alternative_recipient string Optional An alternative contact or recipient for the order — for example, a project manager or department head who should be notified about delivery or invoice queries.
po_net_total number (decimal) Recommended The total net value of the purchase order before tax. Must be provided as a numeric value with up to 2 decimal places, without any thousand separators such as commas. Should equal the sum of all row_net_total line values.
e.g. 1250.00
po_tax_total number (decimal) Optional The total tax amount on the purchase order. Must be provided as a numeric value with up to 2 decimal places, without any thousand separators such as commas. Derived from line-level tax codes but can be supplied at header level for reconciliation.
e.g. 287.50
po_gross_total number (decimal) Recommended The total gross value of the purchase order including tax. Must be provided as a numeric value with up to 2 decimal places, without any thousand separators such as commas. Should equal po_net_total plus po_tax_total.
e.g. 1537.50

Supplier Fields

Supplier fields identify the vendor associated with this purchase order. supplier_number is the key reference SoftCo uses to link the PO to a vendor record. The remaining supplier fields carry address and identification detail for the supplier as recorded in your ERP at time of order.

Field Type Required Description
supplier_number string Required The vendor ID from your ERP — the primary identifier SoftCo uses to link this PO to a supplier record. Should match the supplier_number sent via the Vendor Data API.
e.g. "SUP-001234"
supplier_site_code string Optional The site or location code for this supplier in your ERP, where a supplier has multiple sites. Used to disambiguate supplier addresses and payment terms.
e.g. "DUBLIN-01"
supplier_name string Optional The supplier's trading name as recorded in your ERP at the time the PO was raised. Carried through for display and reference in SoftCo.
e.g. "Acme Office Supplies Ltd"
supplier_address1 string Optional First line of the supplier's address.
supplier_address2 string Optional Second line of the supplier's address.
supplier_city string Optional The city of the supplier's address.
supplier_postcode string Optional The postcode or ZIP code of the supplier's address.
supplier_state string Optional The state, province, or county of the supplier's address.
supplier_country string Optional The country of the supplier's address. Recommended if your organisation works with international suppliers.
e.g. "Ireland""United Kingdom"

Address Fields

Two address groups are supported: the invoice-to address is where the supplier should direct their invoice; the deliver-to address is where the ordered goods or services are to be received. Both groups are optional but recommended where your organisation uses centralised invoicing or multiple delivery locations.

Field Type Required Description
Invoice-To Address
invoice_to_name string Optional The name of the entity or department to whom the supplier should address their invoice.
invoice_to_address1 string Optional First line of the invoice-to address.
invoice_to_address2 string Optional Second line of the invoice-to address.
invoice_to_city string Optional City of the invoice-to address.
invoice_to_postcode string Optional Postcode or ZIP of the invoice-to address.
invoice_to_state string Optional State, province, or county of the invoice-to address.
invoice_to_country string Optional Country of the invoice-to address.
Deliver-To Address
deliver_to_name string Optional The name of the person, department, or site receiving the goods or services.
deliver_to_address1 string Optional First line of the delivery address.
deliver_to_address2 string Optional Second line of the delivery address.
deliver_to_city string Optional City of the delivery address.
deliver_to_postcode string Optional Postcode or ZIP of the delivery address.
deliver_to_state string Optional State, province, or county of the delivery address.
deliver_to_country string Optional Country of the delivery address.

Line Item Fields (rows array)

Line item fields are nested within the rows array inside each PO record. Each element of the rows array represents one purchase order line — with its own quantity, unit price, GL coding, and optional accounting object splits. Every PO record must contain at least one row.

Field Type Required Description
Line Identification
row_id string Required A unique identifier for this line within the PO, typically the line's sequence number or internal row key from your ERP. Used to distinguish lines when multiple rows are present.
e.g. "1""2"
line_number number (integer) Required The line number as it appears on the purchase order — the reference a supplier would see on the printed or emailed PO. Used by SoftCo for invoice line matching.
e.g. 1210
item_number string Optional Your ERP's internal item or product code for the goods or service on this line. Where the item is managed as a catalogue item in your ERP, provide this code for richer matching.
e.g. "ITEM-00452"
line_description string Recommended A human-readable description of the goods or service being ordered on this line. This is the description that appears on the PO and is used by SoftCo for display and matching context.
e.g. "A4 Copy Paper — 5 Ream Box"
supplier_item_number string Optional The supplier's own product reference or catalogue number for the item on this line. Useful for cross-referencing supplier invoices that cite the supplier's part number rather than yours.
Quantity & Pricing
quantity number (decimal) Required The quantity ordered on this line. SoftCo uses this for quantity-based invoice matching — checking that the invoiced quantity does not exceed the ordered quantity. Must be provided as a numeric value with up to 6 decimal places, without any thousand separators such as commas.
e.g. 102.550.750
uom string Required The unit of measure for the quantity on this line. Should match the unit of measure used on the supplier's invoice to enable accurate matching.
"EA""BOX""KG""HR""DAY"
unit_price number (decimal) Required The agreed unit price for one unit of the item on this line. SoftCo compares this against the invoiced unit price during matching. Whether this is a net or gross price is indicated by unit_price_is_net. Must be provided as a numeric value with up to 2 decimal places, without any thousand separators such as commas.
e.g. 62.50125.00
unit_price_is_net string Optional Indicates whether the unit_price is a net (pre-tax) price. Send "true" if the unit price excludes tax, "false" if it is a gross price inclusive of tax.
"true""false"
row_net_total number (decimal) Recommended The total net value for this line (quantity × unit price before tax). Must be provided as a numeric value with up to 2 decimal places, without any thousand separators such as commas. Should equal quantity × unit_price when unit_price_is_net is true.
e.g. 625.00
row_gross_total number (decimal) Optional The total gross value for this line including tax. Must be provided as a numeric value with up to 2 decimal places, without any thousand separators such as commas.
e.g. 768.75
Receipting & Matching Controls
receipting_required string Required Controls whether a goods receipt or service confirmation is required before SoftCo will approve an invoice for this line. Send "true" to enable three-way matching (PO + GRN + invoice). Send "false" for two-way matching (PO + invoice only).
"true""false"
exact_GRN_level_match string Optional When receipting is required, this flag controls whether SoftCo requires an exact match between the goods receipt quantity and the invoiced quantity. Send "true" to enforce exact matching; "false" to allow tolerance-based matching.
"true""false"
by_pass_confirmation string Optional When set to "true", instructs SoftCo to bypass the normal confirmation or approval step for this line. Use only where the line has already been approved upstream and confirmation in SoftCo is not required.
"true""false"
GL & Tax Coding
gl_code string Recommended The general ledger account code for this line. Should match a GL code that has been synchronised to SoftCo via the GL Account Codes API. Providing this at PO level pre-populates the coding on matched invoices, reducing manual coding effort.
e.g. "6100""7200"
tax_code string Recommended The tax code applicable to this line — for example the VAT rate or tax treatment. Should correspond to a tax code configured in SoftCo.
e.g. "T1""T0""T9"
Accounting Objects (accounting_object_1 – accounting_object_9)
accounting_object_1
through
accounting_object_9
string Optional Up to nine accounting dimension values — cost centres, departments, projects, or any other segmentation dimensions configured in SoftCo. These correspond directly to the accounting object dimensions in the Accounting Objects API. Only populate the dimensions your organisation uses; unused fields can be omitted or left empty.
e.g. accounting_object_1: "CC-MKTG"accounting_object_2: "PRJ-0042"
Pre-populating invoice coding

Providing gl_code, tax_code, and accounting object values at line level means SoftCo can automatically pre-populate the coding on matched invoices — eliminating manual coding and accelerating the approval workflow for your AP team.

Example Requests

Single purchase order with two lines

Single PO — Two Line Items
POST /purchase-orders/v1
x-api-key:     your-api-key-here
Content-Type:  application/Json
Client_Id:     your-client-id
Client_Secret: your-client-secret

{
  "objects": {
    "object": {
      "record": [
        {
          "organization":        "main",
          "system":              "NetSuite",
          "record_id":           "5",
          "po_number":           "PO-2024-00891",
          "po_type":             "NEW",
          "po_date":             "2024-03-15",
          "currency":            "EUR",
          "buyer":               "Jane Murphy",
          "approver":            "Tom Walsh",
          "supplier_number":     "SUP-001234",
          "supplier_name":       "Acme Office Supplies Ltd",
          "supplier_address1":   "14 Parkway Business Centre",
          "supplier_city":       "Dublin",
          "supplier_postcode":   "D12 XF70",
          "supplier_country":    "Ireland",
          "deliver_to_name":     "Goods Inward — Building A",
          "deliver_to_address1": "1 Corporate Park",
          "deliver_to_city":     "Dublin",
          "deliver_to_country":  "Ireland",
          "po_net_total":        1250.00,
          "po_tax_total":        287.50,
          "po_gross_total":      1537.50,
          "rows": [
            {
              "row_id":              "1",
              "line_number":         1,
              "line_description":    "A4 Copy Paper — 5 Ream Box",
              "quantity":            10,
              "uom":                 "BOX",
              "unit_price":          62.50,
              "unit_price_is_net":   "true",
              "row_net_total":       625.00,
              "receipting_required": "true",
              "gl_code":             "6100",
              "tax_code":            "T1",
              "accounting_object_1": "CC-ADMIN"
            },
            {
              "row_id":              "2",
              "line_number":         2,
              "line_description":    "Printer Ink Cartridge — Black",
              "quantity":            5,
              "uom":                 "EA",
              "unit_price":          125.00,
              "unit_price_is_net":   "true",
              "row_net_total":       625.00,
              "receipting_required": "true",
              "gl_code":             "6100",
              "tax_code":            "T1",
              "accounting_object_1": "CC-ADMIN"
            }
          ]
        }
      ]
    }
  }
}

Batch — two purchase orders in one request

Batch — Two Purchase Orders
POST /purchase-orders/v1
x-api-key:     your-api-key-here
Content-Type:  application/Json
Client_Id:     your-client-id
Client_Secret: your-client-secret

{
  "objects": {
    "object": {
      "record": [
        {
          "record_id":       "5",
          "po_number":       "PO-2024-00891",
          "po_date":         "2024-03-15",
          "supplier_number": "SUP-001234",
          "currency":        "EUR",
          "po_net_total":    1250.00,
          "po_gross_total":  1537.50,
          "rows": [
            { "row_id": "1", "line_number": 1, "quantity": 10, "uom": "BOX", "unit_price": 62.50, "receipting_required": "true", "gl_code": "6100" }
          ]
        },
        {
          "record_id":       "6",
          "po_number":       "PO-2024-00892",
          "po_date":         "2024-03-15",
          "supplier_number": "SUP-000876",
          "currency":        "EUR",
          "po_net_total":    3400.00,
          "po_gross_total":  4182.00,
          "rows": [
            { "row_id": "1", "line_number": 1, "line_description": "IT Consulting Services", "quantity": 8, "uom": "DAY", "unit_price": 425.00, "receipting_required": "true", "gl_code": "7200", "accounting_object_1": "PRJ-0042" }
          ]
        }
      ]
    }
  }
}

Validation

Every request is validated against the purchase order schema before any processing takes place. If validation fails, the entire request is rejected immediately — nothing is queued or forwarded to SoftCo. You receive a clear error identifying the field or structural issue.

What is checked

CheckDetail
Envelope structureThe payload must use the PO envelope: objects as a JSON object, each containing a record array. Using the master data envelope (objects as an object with a record key) will fail validation.
Required header fieldsrecord_id, po_number, po_date, and supplier_number must be present in every record.
rows array presenceEvery PO record must contain a rows array with at least one line item object.
Required line fieldsEvery row must contain row_id, line_number, quantity, uom, unit_priceand receipting_required.
Field typesAll fields must be in line with the field type. Sending an incorrect data type for any field will fail validation.
Non-empty required valuesRequired fields must not be empty strings.

Validation error response

When validation fails, the API returns a 400 Bad Request with a JSON body identifying the failing field or structure:

400 Bad Request — validation failure
{
  "status":      "FAILED",
  "total":       1,
  "succeeded":   0,
  "failed":      1,
  "errors":      [{ "index": 0, "error": "required key [po_number] not found" }],
  "message":     "1 of 1 records failed validation."
}

The errors array identifies the exact field or path that failed, and the message field provides a summary. Fix the identified issue and resubmit.

Troubleshooting

The most common error scenarios and how to resolve them.

400
Missing required header field
One or more required PO header fields is absent from the record. The errors array will identify the missing field — for example required key [po_number] not found.
{ "status": "FAILED", "total": 1, "succeeded": 0, "failed": 1, "errors": [{"index": 0, "error": "required key [po_number] not found"}], "message": "1 of 1 records failed validation." }
Fix: Ensure po_number, po_date, and supplier_number are present in every record object. None can be omitted or null.
400
Missing or empty rows array
Every PO record must contain a rows array with at least one line item object. Sending a record without rows, or with an empty rows: [], will fail validation.
// Wrong — no rows { "po_number": "PO-2024-00891", "po_date": "2024-03-15", "supplier_number": "SUP-001234" } // Correct — rows with at least one line { "po_number": "PO-2024-00891", "po_date": "2024-03-15", "supplier_number": "SUP-001234", "rows": [ { "row_id": "1", "line_number": 1, "quantity": 5, "uom": "EA", "unit_price": 100.00 } ] }
Fix: Always include a rows array with at least one complete line item in every PO record.
400
Missing required line item field
A required field is absent from one or more row objects. The errors array will reference the failing field — for example a missing quantity, uom, or unit_price.
{ "status": "FAILED", "total": 1, "succeeded": 0, "failed": 1, "errors": [{"index": 0, "error": "required key [unit_price] not found"}], "message": "1 of 1 records failed validation." }
Fix: Ensure every row object includes row_id, line_number, quantity, uom, and unit_price. None can be omitted or null.
Resending a PO that already exists?

Resubmitting a PO with the same po_number is safe — SoftCo will update the existing record with the values in the new request. This makes it straightforward to resend after a correction or amendment without needing to delete the original first.

Example Responses

Success — 202 Accepted

202 Accepted
{
  "status":      "SUCCESS",
  "total":       1,
  "succeeded":   1,
  "failed":      0,
  "errors":      [],
  "message":     "All records processed successfully."
}

Partial success — 207 Multi-Status

207 Multi-Status — Partial
{
  "status":      "PARTIAL",
  "total":       3,
  "succeeded":   2,
  "failed":      1,
  "errors":      [{ "index": 1, "error": "required key [supplier_number] not found" }],
  "message":     "2 of 3 records processed successfully. 1 record failed validation."
}

Validation failure — 400 Bad Request

400 Bad Request
{
  "status":      "FAILED",
  "total":       1,
  "succeeded":   0,
  "failed":      1,
  "errors":      [{ "index": 0, "error": "required key [supplier_number] not found" }],
  "message":     "1 of 1 records failed validation."
}

Authentication failure — 401 Unauthorized

401 Unauthorized
{
  "status":   "FAILED",
  "message":  "Unauthorized"
}