Skip to main content

Work Order Integration

This guide walks you through the most common Pico API integration pattern: a bidirectional work order flow with your ERP system. Before the flow can run, your ERP's products and operations must be mapped to Pico operations — that mapping is a prerequisite covered first. You'll then learn how to create orders when you're ready to manufacture and receive real-time completion notifications to update your inventory and material consumption. By the end of this guide, you'll understand the complete lifecycle of an order from creation through completion, with practical examples for each step.

Prerequisite: Map ERP Operations to Pico Operations

Before you start: You'll need an API token before making any calls. See the Authentication Guide for details.

Every operation order names the Pico operation to build (operationId), so before your ERP can place orders it needs a mapping from its own products and operations to Pico's. There are two ways to establish it:

Map with the ERP Mapping UI

Push your ERP's products and operations — and the serialized materials each one consumes — into Pico with erpOperationsSave. A Pico manager then maps each ERP operation to the corresponding Pico operation in the ERP Mapping UI, including allocating consumed serials to Pico attributes marked as consumed serials. Read the result back with erpOperations: in the operation's mappings list, the entry whose operationId is the ERP operation's own id is its self mapping — the mapping of the operation itself, as opposed to entries mapping its sub-operations — and that entry's picoOperationId is the value to use as operationId when creating operation orders. The consumed-serial allocations let you process completion events without additional lookups.

This is the recommended path for new integrations — the mapping lives in Pico, a person who knows the shop floor confirms it, and your integration code never needs matching logic. It also lets you map against undeployed changes: operations can be mapped before their edits are deployed, making minor adjustments easier to manage. See ERP Example Calls sections 7-9 for the full ingest → read-back → order flow.

Match in your own code

You can instead manage the mapping yourself by fetching Pico's catalog and matching in your own code. This approach is fully supported — many existing integrations use it and can continue to, no Mapping UI required.

Operations represent the products, subassemblies, and manufacturing processes defined in Pico. Each operation gives you several handles to match on:

  • id - Pico's internal identifier
  • name - Human-readable name
  • externalId - Optional stored part number (e.g., "PROD-101")
  • externalRevision - Optional stored revision (e.g., "A", "B")
  • consumedSerials - List of required serialized materials/components, each with a quantity and attr describing the consumed part

Query the operations field to retrieve all products and processes and match them to your ERP's records however fits your data — by name, by the stored part number and revision when present, or both. Query subOperations for the product structure (which components are used in which products) when extra context helps disambiguate. This is typically a one-time sync, with periodic updates when products change. Map consumed serials back to serialized parts in your ERP during this step so completion events can be processed without additional lookups.

The Order Flow

With the mapping in place — from either path — the integration itself is two steps:

1. Create Operation Orders for Products

What is an operation order? When your ERP needs something built (a sales order is released, inventory hits a reorder point), it creates an operation order against the mapped Pico operation. Pico then orders the individual work orders from the operation's designed Pico workflow — a work order tells an operator to build or run one process at a station for that order. A single operation order for a product typically fans out into many work orders.

When to create operation orders: When your ERP determines a product needs to be built - for example, when a sales order is released or when inventory reaches a reorder point.

How it works: Use the operationOrderSave mutation with:

  • operationId - The product to build (the mapped Pico operation from the prerequisite above)
  • externalOrderId - Your ERP's order identifier (e.g., "SALES-123")

See the OperationOrderSaveInput type for all available options.

Limiting where an order can be built: Optionally pass stationIds and/or stationLineIds to restrict the order to specific stations or to any station assigned to the listed station lines — useful when ERP work centers map to Pico station lines. The two lists combine as an OR match, both empty means buildable anywhere, and IDs are validated at save. Station-line assignments are read live, so moving a station to a different line immediately changes which orders it can build.

Use the stationLines query to look up those IDs, with each station nested under the line it belongs to:

query {
stationLines {
lines {
id
name
stations {
id
name
}
}
unassignedStations {
id
name
}
}
}

Stations assigned to no line are returned in unassignedStations, so every station appears exactly once across the response. A line with no stations assigned yet returns null for stations.

Once created, the operation order's work orders appear on the shop floor and operators can begin building.

2. Subscribe to Operation Order Completions

What are completions? When the ordered product or process finishes on the shop floor (its work orders are done), Pico generates a completion event containing:

  • What was built (product and serial number)
  • When it was built (timestamps)
  • What materials were consumed (component serial numbers)

Why subscribe? Your ERP needs to know when products are completed so it can:

  • Update inventory (add the produced item)
  • Consume materials (deduct components used)
  • Update order status
  • Trigger billing or shipping processes

How it works: Establish a WebSocket subscription to operationOrderCompletesStream. Pico pushes a message to you immediately when any operation order completes, without you having to poll. See the OperationSummary type for details on the completion data structure.

Subscribe to changes to deployed operations and suboperations

Whichever mapping path you use, Pico's catalog changes over time — subscribe to keep your ERP's view current (especially important if you match in your own code):

subscription ops {
operationsStream {
partNo: externalId
name
consumedSerials {
id
quantity
attr {
name
partNo: externalId
}
}
updatedAt
}
}

subscription subOps {
subOperationsStream {
parentId
subId
updatedAt
}
}

Ingest ERP operations for mapping

This pushes an ERP operation (with a consumed serial) into Pico so a manager can map it in the ERP Mapping UI. Re-sending the same id updates it. See ERP Example Calls section 7 for the full version.

mutation ingestERPOperations($input: ERPOperationsSaveInput!) {
erpOperationsSave(input: $input) {
message
}
}
variables {
"input": {
"operations": [
{
"id": "ERP-OP-1001",
"name": "Frame Weld Assembly",
"externalId": "FRAME-WELD",
"hasPlannedOrder": true,
"consumedSerials": [
{ "id": "ERP-CS-1", "name": "Down Tube", "externalId": "TUBE-DOWN", "quantity": 1 }
]
}
]
}
}

Read back the operation mapping

Once mapped, the self mapping (the mappings entry whose operationId is the operation's own id) carries the picoOperationId to order with. See ERP Example Calls section 8 for the full version.

query erpMapping {
erpOperations(where: { id: { _eq: "ERP-OP-1001" } }) {
id
hasPlannedOrder
mappings {
operationId
picoOperationId
}
neverMappedReason
}
}

Omit where to fetch all of your ERP operations.

Save an operation order for a product

This is what the example graphql payload may look like when you want to build a PROD-101 for sales order SALES-123.

mutation saveOperation($opId: String!, $order: String!) {
operationOrderSave(input: {operationId: $opId, externalOrderId: $order}) {
message
}
}
variables {
"opId": "def123",
"order": "SALES-123"
}

Subscribe to operation order completions for all products

This is the payload used to subscribe to all future operation order completions.

Note: we use graphql aliases to rename fields so they may match any domain (e.g. externalOrderId -> order)

subscription NewOpCompletions {
operationOrderCompletesStream {
order: externalOrderId
at
operation {
id
partNo: externalId
name
}
operationSummary {
consumedSerials {
attrId # pre-mapped during operation sync
value
}
}
endState {
producedSerial
}
}
}

See Also