Purchase Orders API
π Why Use the Purchase Orders API?β
Purchase orders are critical components of inventory management and logistics in DataDocks. They represent agreements for products to be delivered to your warehouses (inbound) or shipped from them (outbound). The Purchase Orders API enables you to programmatically create, track, and manage these essential documents, linking your supply chain systems directly to your warehouse operations.
Real Problems This API Solvesβ
- Streamline Order Processing: Automatically create and update purchase orders from your ERP or order management system
- Enhance Inventory Visibility: Track expected arrivals and departures with detailed product information
- Simplify Carrier Management: Associate carriers with purchase orders to streamline logistics
- Improve Planning: Set expected timelines to better manage warehouse resources
- Enable Advanced Analytics: Access structured purchase order data for reporting and analysis
5-Minute Quickstartβ
Ready to create your first purchase order via API? Follow these simple steps:
- Get your API token from support
- Identify your location subdomain (e.g.,
your-warehouse.datadocks.com
) - Create a basic purchase order with this command:
See cURL example
curl -X POST \
https://your-warehouse.datadocks.com/api/v1/purchase_orders \
-H 'Authorization: Token YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"purchase_order": {
"po_number": "PO-2023-001",
"carrier_name": "Express Logistics",
"outbound": false,
"expected_starts_at": "2023-06-01T08:00:00-04:00",
"expected_ends_at": "2023-06-01T16:00:00-04:00",
"purchase_order_items": [
{
"product_name": "Widgets",
"unit_name": "Pallet",
"quantity": 10,
"weight": 500
}
]
}
}'
- Done! Your purchase order is now in DataDocks. Check your dashboard to see it.
API Architecture Overviewβ
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Your System ββββββββΆβ DataDocks API ββββββββΆβ Warehouse Ops β
β (ERP/OMS/TMS) βββββββββ€ (REST/JSON) βββββββββ€ (POs/Items) β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β²
β β
βΌ β
βββββββββββββββββββ
β Appointments β
β & Scheduling β
β β
βββββββββββββββββββ
Authenticationβ
All API requests must include your API token in the Authorization
header:
Authorization: Token YOUR_API_TOKEN
Listing Purchase Ordersβ
Purposeβ
Retrieve a paginated list of purchase orders with optional filtering by PO number. Use this endpoint to sync purchase orders with your systems, check status of expected deliveries, or prepare reports on warehouse activity.
Business Use Casesβ
- Sync purchase orders with your ERP or order management system
- Generate reports on expected inventory movements
- Monitor upcoming deliveries or shipments
- Track carrier performance across purchase orders
HTTP Requestβ
GET https://[location_subdomain].datadocks.com/api/v1/purchase_orders
Query Parametersβ
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
page | Integer | No | Page number for pagination (defaults to 1) | page=2 |
po_number | String | No | Filter by exact PO number (case-insensitive) | po_number=A-1000 |
Response Formatβ
The response contains an array of purchase order objects, each with the following fields:
Field | Type | Description |
---|---|---|
id | Integer | Unique identifier for the purchase order |
po_number | String | Purchase order number |
name | String | Auto-generated name based on PO details |
carrier_name | String | Name of the carrier assigned to the purchase order |
location_name | String | Name of the warehouse location |
outbound | Boolean | Whether this is an outbound (true) or inbound (false) order |
expected_starts_at | String | ISO8601 timestamp when the PO is expected to start |
expected_ends_at | String | ISO8601 timestamp when the PO is expected to end |
custom_values | Object | Key-value pairs of custom fields |
purchase_order_items | Array | List of items associated with this purchase order |
Each item in purchase_order_items
contains:
Field | Type | Description |
---|---|---|
id | Integer | Unique identifier for the item |
customer_name | String | Name of the customer associated with the item |
product_name | String | Name of the product |
unit_name | String | Unit of measure (e.g., "Pallet", "Box") |
quantity | Number | Quantity of the product |
weight | Number | Weight of the item |
custom_values | Object | Key-value pairs of custom fields for this item |
Code Examplesβ
cURLβ
See cURL example
# Basic listing
curl -H "Authorization: Token YOUR_API_TOKEN" \
https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders
# Filtered by PO number
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders?po_number=A-1000"
JavaScriptβ
See JavaScript example
// Using fetch API with PO number filter
const getPurchaseOrders = async (poNumber) => {
const params = new URLSearchParams();
if (poNumber) params.append("po_number", poNumber);
const response = await fetch(
`https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders?${params.toString()}`,
{
method: "GET",
headers: {
Authorization: "Token YOUR_API_TOKEN",
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(
`Failed to fetch purchase orders: ${JSON.stringify(errorData)}`
);
}
return response.json();
};
Sample Responseβ
See sample response
[
{
"id": 1,
"po_number": "A-1000",
"name": "A-1000-FastCo-Cereal",
"carrier_name": "FastCo",
"location_name": "Toronto",
"outbound": false,
"expected_starts_at": "2020-10-09T13:35:00-04:00",
"expected_ends_at": "2020-10-15T13:35:00-04:00",
"custom_values": {
"expected_at": "2020-10-09",
"travel_type": "Plane",
"forklift_operator": "Joe"
},
"purchase_order_items": [
{
"id": 2,
"customer_name": "FishCo",
"product_name": "Trout",
"unit_name": "Skid",
"quantity": 16,
"weight": 102,
"custom_values": {}
},
{
"id": 1,
"customer_name": "FishCo",
"product_name": "Cereal",
"unit_name": "Skid",
"quantity": 33,
"weight": 581,
"custom_values": {}
}
]
}
]
Retrieving a Single Purchase Orderβ
Purposeβ
Get detailed information about a specific purchase order by ID. Use this endpoint when you need comprehensive data about a particular order, including all its line items and custom fields.
Business Use Casesβ
- Display detailed purchase order information in your application
- Verify purchase order details before processing
- Access the complete list of items in a specific order
- Check custom field values for integration with other systems
HTTP Requestβ
GET https://[location_subdomain].datadocks.com/api/v1/purchase_orders/:id
Path Parametersβ
Parameter | Type | Required | Description |
---|---|---|---|
id | Integer | Yes | Unique ID of the purchase order |
Responseβ
A successful request returns a 200 OK
response with the full purchase order object in the same format as the list response.
Code Examplesβ
cURLβ
See cURL example
curl -H "Authorization: Token YOUR_API_TOKEN" \
https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders/1
JavaScriptβ
See JavaScript example
const getPurchaseOrder = async (purchaseOrderId) => {
try {
const response = await fetch(
`https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders/${purchaseOrderId}`,
{
method: "GET",
headers: {
Authorization: "Token YOUR_API_TOKEN",
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
if (response.status === 404) {
throw new Error(`Purchase order #${purchaseOrderId} not found`);
}
const errorData = await response.json();
throw new Error(
`Failed to retrieve purchase order: ${JSON.stringify(errorData)}`
);
}
return await response.json();
} catch (error) {
console.error("Error fetching purchase order:", error);
throw error;
}
};
Creating a Purchase Orderβ
Purposeβ
Create a new purchase order record in DataDocks. This endpoint allows you to add new purchase orders and their line items programmatically, integrating your order management system directly with your warehouse operations.
Decision Tree: When to Create a PO via APIβ
βββββββββββββββββββ
β Need to add a β
β purchase order? β
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ Yes βββββββββββββββββββ
β Integration ββββββββββββββΆβ Perfect for β
β with your ERP/ β β the API! β
β Order system? β β β
ββββββββββ¬βββββββββ βββββββββββββββββββ
β No
βΌ
βββββββββββββββββββ Yes βββββββββββββββββββ
β Creating many ββββββββββββββΆβ Use bulk β
β orders at once? β β import β
ββββββββββ¬βββββββββ βββββββββββββββββββ
β No
βΌ
βββββββββββββββββββ
β Use the web β
β interface β
βββββββββββββββββββ
Business Use Casesβ
- System Integration: Create purchase orders directly from your ERP or order management system
- Automated Order Processing: Programmatically convert sales orders to purchase orders
- EDI Integration: Transform EDI 850 Purchase Order documents into DataDocks POs
- Vendor Integration: Allow vendors to submit purchase orders through your systems
HTTP Requestβ
POST https://[location_subdomain].datadocks.com/api/v1/purchase_orders
Request Bodyβ
Parameter | Type | Required | Description | Constraints | Default | Example |
---|---|---|---|---|---|---|
po_number | String | Yes | Purchase order number | Must be unique | None | "PO-2023-001" |
carrier_name | String | No * | Name of the carrier | None | None | "Express Logistics" |
carrier_number | String | No | Carrier's company number | Must match existing carrier | None | "EXP-001" |
location_name | String | No | Name of the location | Must match existing location | Current location | "Toronto Warehouse" |
outbound | Boolean | No | Whether this is an outbound order | None | false | true |
expected_starts_at | String | No | ISO8601 timestamp for expected start | Valid ISO8601 format | None | "2023-06-01T08:00:00-04:00" |
expected_ends_at | String | No | ISO8601 timestamp for expected end | Valid ISO8601 format | None | "2023-06-01T16:00:00-04:00" |
alternate_reference_number | String | No | Alternative reference number | None | None | "REF-123" |
closed | Boolean | No | Whether the PO is closed | None | false | true |
custom_values | Object | No * | Custom field values | Based on location settings | {} | {"department": "Produce"} |
purchase_order_items | Array | No | Line items for the PO | At least one item recommended | [] | See below |
Each item in purchase_order_items
can include:
Parameter | Type | Required | Description | Constraints | Example |
---|---|---|---|---|---|
customer_name | String | No * | Name of the customer | None | "Acme Corp" |
customer_number | String | No * | Customer's company number | Must match existing customer | "ACME-001" |
product_name | String | No * | Name of the product | None | "Widgets" |
unit_name | String | No * | Unit of measure | None | "Pallet" |
quantity | Number | No * | Quantity of the product | Must be positive | 10 |
weight | Number | No * | Weight of the item | Must be positive | 500 |
custom_values | Object | No * | Custom field values for this item | Based on location settings | {"color": "Blue"} |
* Fields might be required depending on location preferences
Responseβ
A successful request returns a 200 OK
response with the full purchase order object, including the generated id
and other system-assigned values.
Code Examplesβ
cURLβ
See cURL example
curl -H "Authorization: Token YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"purchase_order": {
"po_number": "PO-2023-001",
"carrier_name": "Express Logistics",
"outbound": false,
"expected_starts_at": "2023-06-01T08:00:00-04:00",
"expected_ends_at": "2023-06-01T16:00:00-04:00",
"custom_values": {
"department": "Electronics",
"priority": "High"
},
"purchase_order_items": [
{
"product_name": "Laptops",
"unit_name": "Box",
"quantity": 50,
"weight": 250,
"custom_values": {
"model": "XPS 13"
}
},
{
"product_name": "Monitors",
"unit_name": "Pallet",
"quantity": 10,
"weight": 500,
"custom_values": {
"size": "27-inch"
}
}
]
}
}' \
https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders
JavaScriptβ
See JavaScript example
const createPurchaseOrder = async (purchaseOrderData) => {
try {
const response = await fetch(
`https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders`,
{
method: "POST",
headers: {
Authorization: "Token YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ purchase_order: purchaseOrderData }),
}
);
if (!response.ok) {
const errorData = await response.json();
const errorMessages = Object.entries(errorData.errors || {})
.map(([field, messages]) => `${field}: ${messages.join(", ")}`)
.join("\n");
throw new Error(`Failed to create purchase order:\n${errorMessages}`);
}
return await response.json();
} catch (error) {
console.error("API Error:", error);
throw error;
}
};
Updating a Purchase Orderβ
Purposeβ
Update an existing purchase order's details. This endpoint allows you to modify any aspect of a purchase order, including its line items, dates, carrier information, and custom fields.
Business Use Casesβ
- Keep Data Current: Update delivery dates or carrier information as they change
- Modify Order Contents: Add, remove, or change line items as needed
- Change Order Status: Mark purchase orders as closed when fulfilled
- Add Reference Information: Update custom fields with tracking or delivery data
HTTP Requestβ
PUT https://[location_subdomain].datadocks.com/api/v1/purchase_orders/:id
Path Parametersβ
Parameter | Type | Required | Description |
---|---|---|---|
id | Integer | Yes | Unique ID of the purchase order |
Request Bodyβ
The request body accepts the same parameters as the create endpoint. Only the fields you want to change need to be included.
Common Update Scenariosβ
Updating Datesβ
{
"purchase_order": {
"expected_starts_at": "2023-06-05T08:00:00-04:00",
"expected_ends_at": "2023-06-05T16:00:00-04:00"
}
}
Changing Carrierβ
{
"purchase_order": {
"carrier_name": "Fast Transit Inc",
"carrier_number": "FTI-001"
}
}
Closing a Purchase Orderβ
{
"purchase_order": {
"closed": true
}
}
Updating Line Itemsβ
{
"purchase_order": {
"purchase_order_items": [
{
"id": 123,
"quantity": 15
},
{
"product_name": "New Product",
"unit_name": "Box",
"quantity": 5,
"weight": 25
}
]
}
}
Code Examplesβ
cURLβ
See cURL example
curl -H "Authorization: Token YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-X PUT \
-d '{
"purchase_order": {
"carrier_name": "Updated Logistics Co",
"expected_starts_at": "2023-06-02T08:00:00-04:00",
"custom_values": {
"tracking_number": "TRK12345"
}
}
}' \
https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders/1
JavaScriptβ
See JavaScript example
const updatePurchaseOrder = async (purchaseOrderId, updateData) => {
try {
const response = await fetch(
`https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders/${purchaseOrderId}`,
{
method: "PUT",
headers: {
Authorization: "Token YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ purchase_order: updateData }),
}
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(
`Failed to update purchase order: ${JSON.stringify(errorData)}`
);
}
return await response.json();
} catch (error) {
console.error("Error updating purchase order:", error);
throw error;
}
};
Removing All Purchase Order Itemsβ
If you need to clear all line items from a purchase order, include the clear_po_items
parameter with a value of true
:
{
"purchase_order": {
"clear_po_items": "true",
"purchase_order_items": [
{
"product_name": "New Product",
"unit_name": "Box",
"quantity": 10
}
]
}
}
This will remove all existing items and replace them with the new items provided (if any).
Deleting a Purchase Orderβ
Purposeβ
Remove a purchase order from the system. This endpoint allows you to delete purchase orders that are no longer needed.
Important Considerationsβ
Before deleting a purchase order, consider the following:
- The purchase order must not be associated with any active appointments
- Deletion is permanent and cannot be undone
- In many cases, it's better to mark a purchase order as closed rather than delete it
Business Use Casesβ
- Clean Up Test Data: Remove test or dummy purchase orders
- Remove Duplicate Records: Clean up after data de-duplication
- System Maintenance: Remove old, unused purchase order records
HTTP Requestβ
DELETE https://[location_subdomain].datadocks.com/api/v1/purchase_orders/:id
Path Parametersβ
Parameter | Type | Required | Description |
---|---|---|---|
id | Integer | Yes | Unique ID of the purchase order |
Responseβ
A successful request returns a 204 No Content
response, indicating that the purchase order was deleted successfully.
Code Examplesβ
cURLβ
See cURL example
curl -H "Authorization: Token YOUR_API_TOKEN" \
-X DELETE \
https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders/1
JavaScriptβ
See JavaScript example
const deletePurchaseOrder = async (purchaseOrderId) => {
try {
const response = await fetch(
`https://YOUR_LOCATION.datadocks.com/api/v1/purchase_orders/${purchaseOrderId}`,
{
method: "DELETE",
headers: {
Authorization: "Token YOUR_API_TOKEN",
},
}
);
if (!response.ok) {
if (response.status === 404) {
throw new Error(`Purchase order #${purchaseOrderId} not found`);
}
const errorData = await response.json();
throw new Error(
`Failed to delete purchase order: ${JSON.stringify(errorData)}`
);
}
return true; // Successfully deleted
} catch (error) {
console.error("Error deleting purchase order:", error);
throw error;
}
};
Automatic Entity Resolutionβ
Carrier Resolutionβ
When creating or updating a purchase order, you can provide either carrier_name
or carrier_number
(or both):
- If you provide
carrier_number
, the system will attempt to find a matching carrier by company number - If a match is found, the carrier's name and ID will be automatically associated with the purchase order
- If no match is found, the system will use the provided
carrier_number
as thecarrier_name
Product Resolutionβ
When creating or updating purchase order items:
- If the product name matches an existing product (case-insensitive), that product will be used
- If the product didn't match any existing product, the item will be created but may not be linked to a proper product record
- contact support if you need to create a product if it doesn't exist yet
Unit Resolutionβ
Similar to products:
- If the unit name matches an existing unit (case-insensitive), that unit will be used
- If the unit didn't match any existing unit, the item will not have a proper unit association
- contact support if you need to create a unit if it doesn't exist yet
Best Practicesβ
Data Managementβ
- Use Unique PO Numbers: Ensure each purchase order has a unique identifier
- Provide Carrier Numbers: When possible, use carrier company numbers for reliable carrier association
- Validate Data Client-Side: Ensure data meets basic validation before sending
- Consider Using Closed Flag: Rather than deleting purchase orders, mark them as closed
- Manage Custom Fields Properly: Only use custom fields that are configured for your location
Performance Optimizationβ
- Include Complete Data Sets: When possible, include all relevant data in a single API call
- Use Batch Operations: Group related purchase order updates together
- Be Specific with Queries: Use available filters to minimize data transfer
Common Gotchas and Troubleshootingβ
- PO Number Uniqueness: Purchase order numbers should be unique within a location
- Date Formatting: Dates must be in valid ISO8601 format (e.g., "2023-06-01T08:00:00-04:00")
- Carrier Association: If carriers aren't being properly associated, ensure you're using the correct company number
- Custom Field Types: JSON fields in custom values will be preserved as JSON; other fields will be converted to strings
- Clearing Line Items: Remember to use the
clear_po_items
parameter if you want to completely replace all line items
Error Handlingβ
Error Code | Description | Possible Cause |
---|---|---|
400 | Bad Request | Invalid values or format |
404 | Not Found | Purchase order ID doesn't exist |
422 | Unprocessable Entity | Validation failed (e.g., missing required field) |
401 | Unauthorized | Invalid or missing API token |
403 | Forbidden | Insufficient permissions |
Sample Error Responseβ
{
"errors": {
"po_number": ["can't be blank"],
"purchase_order_items": ["must have at least one item"]
}
}
Help and Supportβ
If you're experiencing issues not covered in this documentation:
- Check the error response: Most API errors include specific information about what went wrong
- Verify permissions: Ensure your API token has sufficient permissions
- Test in smaller steps: Break down complex operations to identify the specific issue