Create Purchase Orders via API
Overview
Yanet Auto Purchase Orders provides a Public API that allows external systems to create Purchase Orders programmatically.
This is useful when you want to connect Yanet Auto Purchase Orders with another system and automatically create Purchase Orders based on data from that system.
Note: The Public API currently supports creating Purchase Orders. Other API operations are not covered by this documentation.
Endpoint: POST /api/public/purchase-orders
1. Overview
Property | Value |
|---|---|
Method |
|
Endpoint |
|
Authentication | Client credentials |
Content-Type |
|
Maximum POs / request |
|
Purchase Orders created through this endpoint are automatically recorded with: |
source = "public_api"2. Authentication
Before making API requests, generate your API credentials from:
Settings → Manage key
Each request must include the following headers:
Header | Required | Description |
|---|---|---|
| Yes | Shop client ID |
| Yes | Shop client secret |
| Yes | Shopify shop domain, e.g. your-store.myshopify.com |
Step 1 — Open Settings
Open Yanet Auto Purchase Orders and go to Settings.

Step 2 — Open API Access
Select API Access from the Settings menu.

Step 3 — Generate API Credentials
Click Generate new key to generate your Client ID and Client Secret.

Step 4 — Copy Your Credentials
Copy the Client ID and Client Secret and use them to authenticate API requests.
Keep your Client Secret secure and do not share it publicly.
Example
X-Client-ID: YOUR_CLIENT_ID
X-Client-Secret: YOUR_CLIENT_SECRET
X-Shop-Domain: your-store.myshopify.com
Authentication errors — 401 Unauthorized
Error | Description |
|---|---|
|
|
|
|
|
|
| The shop domain does not pass Shopify domain validation |
| No shop exists for the specified domain |
| The shop exists but is not active |
| API keys have not been generated for the shop |
| The client ID does not match the shop's stored credentials |
| The client ID is valid, but the client secret does not match |
| Unexpected shop configuration/data issue |
3. Request Body
The API supports three request formats.
3.1 Recommended: Wrapped array
Use this format when creating one or multiple Purchase Orders.
{
"purchase_orders": [
{
"...": "PO 1"
},
{
"...": "PO 2"
}
]
}
3.2 Raw array
[
{
"...": "PO 1"
},
{
"...": "PO 2"
}
]
3.3 Single Purchase Order — Legacy
A single PO can also be sent directly as the request body.
{
"...": "single PO fields"
}
Recommendation: Use the wrapped
purchase_ordersformat for new integrations. It provides a consistent structure for both single-PO and batch requests.
4. Purchase Order Fields
4.1 Required Fields
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Existing supplier name in the app. Matching is case-insensitive. |
|
| Yes | Shopify Location ID. Accepts the GID or numeric ID format used by the app. |
|
| Yes | Purchase order line items. Must contain at least one item. |
Supplier field compatibility
For backward compatibility, you may use supplier instead of supplier_name.
{
"supplier": "Acme Supplies"
}
In this API, supplier is interpreted as a supplier name, not a supplier ID.
Resolution priority:
supplier_name → supplierIf both are provided, supplier_name takes priority.
4.2 Line Items — items[]
Each Purchase Order must contain at least one line item.
Required fields
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Shopify Product ID |
|
| Yes | Shopify Variant ID |
|
| Yes | Product title |
|
| Yes | Variant title |
|
| Yes | Quantity to purchase. Must be |
|
| Yes | Unit cost. Must be |
Optional fields
Field | Type | Description |
|---|---|---|
|
| Product SKU |
|
| Supplier SKU |
|
| Price. Must be |
|
| Compare-at price. Must be |
|
| Tax percentage. Must be between |
|
| Product image URL |
|
| Accepted quantity. Must be |
|
| Rejected quantity. Must be |
4.3 Optional Purchase Order Fields
Field | Type | Description |
|---|---|---|
|
| External or display reference |
|
| PO sequence number. Must be |
|
|
|
|
| Estimated arrival date |
|
| Estimated shipping date |
|
| Invoice date |
|
| Shipping carrier |
|
| Tracking number |
|
| Additional notes |
|
| PO tags |
|
|
|
|
| Amount paid. Must be |
|
| Payment date |
|
| Payment due date |
|
| Payment note |
|
| Payment method |
|
| Payment terms |
|
| Additional costs associated with the PO |
4.4 Additional Costs — additional_costs[]
Each additional cost must contain:
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Cost name |
|
| Yes | Cost description/value |
|
| Yes | Cost amount. Must be |
Example: |
{
"additional_costs": [
{
"name": "Shipping",
"value": "Express",
"cost": 50
}
]
}
4.5 Server-managed Fields
The following fields should not be provided by the client:
Field | Behavior |
|---|---|
| Automatically resolved from |
| Automatically set to |
| Supplier is resolved from the supplier name |
5. Response
The endpoint uses partial success for batch requests.
A request can return 200 OK even when some Purchase Orders fail.
Always check:
success— number of successfully created POsfailed— number of failed POscreated— details of successfully created POserrors— errors for POs that could not be created
Example response
{
"success": 1,
"failed": 1,
"created": [
{
"id": "674a1b2c3d4e5f678901234",
"po_number": "PO-042",
"reference_number": "EXT-1001",
"sequence_number": 42,
"supplier": "6655aabbccddeeff00112233",
"supplier_name": "Acme Supplies",
"destination": "gid://shopify/Location/123456789",
"status": "ordered",
"payment_status": "pending",
"tracking_number": "",
"estimated_arrival": "2026-09-01T00:00:00.000Z",
"estimated_ship": null,
"invoice_date": null,
"subtotal": 1000,
"tax_total": 0,
"additional_costs_total": 50,
"total": 1050,
"item_count": 1,
"source": "public_api",
"created_at": "2026-08-21T07:00:00.000Z",
"updated_at": "2026-08-21T07:00:00.000Z",
"shipping_carrier": "",
"additional_note": "",
"tags": [],
"amount_paid": 0,
"paid_on": null,
"payment_due": null,
"payment_note": "",
"payment_method": "",
"payment_terms": "",
"items": [
{
"product_id": "gid://shopify/Product/111",
"variant_id": "gid://shopify/ProductVariant/222",
"product_title": "T-Shirt",
"variant_title": "M / Black",
"sku": "TS-M-BLK",
"supplier_sku": "ACME-TS-01",
"quantity": 10,
"accepted_quantity": 0,
"rejected_quantity": 0,
"cost": 100,
"price": 0,
"tax": 0,
"image_url": ""
}
],
"additional_costs": [
{
"name": "Shipping",
"value": "Express",
"cost": 50
}
]
}
],
"errors": [
"EXT-1002: Supplier not found for name \"Unknown Vendor\""
]
}
Response fields
Field | Type | Description |
|---|---|---|
|
| Number of POs created successfully |
|
| Number of POs that failed |
|
| Details of successfully created POs |
|
| Per-PO error messages. Uses |
6. Errors
6.1 Request-level errors — 400 Bad Request
Request-level errors prevent the request from being processed.
Error | Description |
|---|---|
| Request body is empty or no Purchase Orders could be parsed |
| The request contains more than 100 POs |
| The shop could not be resolved after authentication |
6.2 Per-PO errors
Per-PO errors are returned inside the errors[] array. Other valid POs in the same request are still processed.
Error | Description |
|---|---|
| Supplier name is missing |
| Destination is missing |
|
|
| No matching supplier exists in the shop |
Batch behavior
For example, if a request contains 3 POs and 1 fails:
{
"success": 2,
"failed": 1,
"created": ["PO 1", "PO 3"],
"errors": [
"EXT-1002: Supplier not found for name \"Unknown Vendor\""
]
}
The successful POs are still created.
7. cURL Examples
7.1 Create Multiple Purchase Orders
curl -X POST "https://your-app-host.com/api/public/purchase-orders" \
-H "Content-Type: application/json" \
-H "X-Client-ID: YOUR_CLIENT_ID" \
-H "X-Client-Secret: YOUR_CLIENT_SECRET" \
-H "X-Shop-Domain: your-store.myshopify.com" \
-d '{
"purchase_orders": [
{
"supplier_name": "Acme Supplies",
"destination": "gid://shopify/Location/123456789",
"reference_number": "EXT-1001",
"status": "ordered",
"estimated_arrival": "2026-09-01",
"additional_note": "Created via public API",
"tags": [
"api",
"wholesale"
],
"items": [
{
"product_id": "gid://shopify/Product/111",
"variant_id": "gid://shopify/ProductVariant/222",
"product_title": "T-Shirt",
"variant_title": "M / Black",
"sku": "TS-M-BLK",
"quantity": 10,
"cost": 100,
"tax": 0
}
],
"additional_costs": [
{
"name": "Shipping",
"value": "Express",
"cost": 50
}
]
}
]
}'
7.2 Create a Single Purchase Order
The recommended format can also be used for a single PO:
curl -X POST "https://your-app-host.com/api/public/purchase-orders" \
-H "Content-Type: application/json" \
-H "X-Client-ID: YOUR_CLIENT_ID" \
-H "X-Client-Secret: YOUR_CLIENT_SECRET" \
-H "X-Shop-Domain: your-store.myshopify.com" \
-d '{
"purchase_orders": [
{
"supplier_name": "Acme Supplies",
"destination": "gid://shopify/Location/123456789",
"status": "draft",
"items": [
{
"product_id": "gid://shopify/Product/111",
"variant_id": "gid://shopify/ProductVariant/222",
"product_title": "T-Shirt",
"variant_title": "M / Black",
"quantity": 5,
"cost": 100
}
]
}
]
}'
8. JavaScript Example
const BASE_URL = 'https://po.yanet.io';
const headers = {
'Content-Type': 'application/json',
'X-Client-ID': 'YOUR_CLIENT_ID',
'X-Client-Secret': 'YOUR_CLIENT_SECRET',
'X-Shop-Domain': 'your-store.myshopify.com',
};
const response = await fetch(
`${BASE_URL}/api/public/purchase-orders`,
{
method: 'POST',
headers,
body: JSON.stringify({
purchase_orders: [
{
supplier_name: 'Acme Supplies',
destination: 'gid://shopify/Location/123456789',
reference_number: 'EXT-1001',
status: 'ordered',
items: [
{
product_id: 'gid://shopify/Product/111',
variant_id: 'gid://shopify/ProductVariant/222',
product_title: 'T-Shirt',
variant_title: 'M / Black',
sku: 'TS-M-BLK',
quantity: 10,
cost: 100,
},
],
},
],
}),
}
);
const result = await response.json();
console.log('Created:', result.success);
console.log('Failed:', result.failed);
console.log('Errors:', result.errors);
console.log('Created POs:', result.created);
9. Integration Guidelines
Before integrating, make sure that:
- The supplier already exists in Yanet. Supplier matching is performed by name and is case-insensitive.
- The destination is valid for the Shopify shop and uses a Location ID recognized by the app.
- A maximum of 100 POs can be submitted in a single request.
- Batch requests support partial success. A failed PO does not prevent other POs from being created.
- After every request, check
success,failed, anderrors. - Each create operation can be recorded in API Call History when API logging is enabled.
10. Quick Reference
Endpoint
POST /api/public/purchase-ordersRequired headers
Content-Type: application/json
X-Client-ID: YOUR_CLIENT_ID
X-Client-Secret: YOUR_CLIENT_SECRET
X-Shop-Domain: your-store.myshopify.com
Minimal request
{
"purchase_orders": [
{
"supplier_name": "Acme Supplies",
"destination": "gid://shopify/Location/123456789",
"items": [
{
"product_id": "gid://shopify/Product/111",
"variant_id": "gid://shopify/ProductVariant/222",
"product_title": "T-Shirt",
"variant_title": "M / Black",
"quantity": 10,
"cost": 100
}
]
}
]
}
Success indicators
HTTP 200
success > 0
failed = 0
For batch requests, HTTP 200 does not necessarily mean every PO was created successfully. Always inspect success, failed, and errors.
Updated on: 25/08/2026
Thank you!
