Create a delivery
Endpoint Overview
This API endpoint provides a detailed overview of the endpoint responsible for creating a delivery (an outgoing stock picking to a customer/partner) within the Inventory module of the Juleb ERP. A single call can create one or many deliveries at once.
Endpoint Details
- Method: POST
- URL:
/api/v1/inventory/picking/delivery
Parameters
- Path Parameters: None
- Query Parameters: None
Request Body
The request body must wrap the delivery (or deliveries) to create under a PartnerPicking key
- either a single object, or an array to create several deliveries in one call:
{
"PartnerPicking": {
"companyId": integer,
"partnerId": integer,
"partner_code": string,
"reason": string,
"note": string,
"origin": string,
"autoValidate": boolean,
"autoCreateBatch": boolean,
"rsd_deserialization": boolean,
"global_import": boolean,
"international_export": boolean,
"lines": [
{
"productId": integer,
"default_code": string,
"productQty": integer,
"batch": string,
"expiry": string
}
]
}
}
Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
companyId | integer | Yes | The company creating the delivery. |
partnerId | integer | No* | The customer/partner receiving the delivery. Required unless partner_code is provided. |
partner_code | string | No* | Alternate lookup for the partner by its reference code, instead of partnerId. |
reason | string | No | Free-text reason, stored on the picking's internal code field. |
note | string | No | Free-text note. Some companies have duplicate-note protection enabled (see Errors below). |
origin | string | No | An external reference/origin identifier. Some companies have duplicate-origin protection enabled per picking type. |
autoValidate | boolean | No (default false) | Automation field. When true, the picking is automatically validated a few seconds after creation - you don't need to call Validate a Picking yourself. |
autoCreateBatch | boolean | No (default false) | Automation field. When true, a missing batch/lot named in a line's batch is created automatically (requires expiry on that line). |
rsd_deserialization | boolean | No | Marks the delivery for external RSD (track-and-trace) deserialization. May be overridden by a company-level setting. |
global_import | boolean | No | Marks the delivery as a global import, for government/track-and-trace reporting. |
international_export | boolean | No | Marks the delivery as an international export, for government/track-and-trace reporting. |
lines | array | Yes | The products being delivered. See the line field table below. |
Line fields (lines[])
| Field | Type | Required | Description |
|---|---|---|---|
productId | integer | No* | The product being delivered. Required unless default_code is provided instead. |
default_code | string | No* | Alternate lookup for the product by its internal reference/code, instead of productId. |
productQty | integer | Yes | Quantity being delivered. |
batch | string | Required if the product is lot/serial-tracked | The batch/lot number to deduct stock from. Required for tracked products unless autoCreateBatch is used. |
expiry | string | Required when creating a new batch | Expiry date for the batch, required when batch doesn't exist yet and is being auto-created. |
Errors
In addition to standard validation errors, this endpoint can return:
A picking with the same origin already exists with id {id}- if origin-duplicate protection is enabled for your company/picking type andoriginmatches an existing delivery.A picking with the same note already exists with id {id}- if note-duplicate protection is enabled andnotematches an existing delivery.No valid products found for the provided lines.- none of theproductId/default_codevalues inlinesmatched a product.Product id {id} not found- a specific line's product couldn't be resolved.Batch/Lot is required for product id {id} as it is a tracked product- the product requires abatch, but none was provided.Expiry date is required to create batch/lot {batch} for product id {id}-autoCreateBatchwas used (or the picking type isRECEIPTS) butexpirywas missing.partner_code {code} not found- thepartner_codeprovided didn't match a partner.
Response
- 201 OK: The requested resource has been created.
- 400 Bad Request: Bad request.
- 401 Unauthorized: Unauthorized.
Response Body
{
"data": {
...record fields
}
}
Example
Request
- NodeJS
- curl
- python
- java
const axios = require('axios');
const accountName = process.env.ACCOUNT_NAME;
const apiKey = process.env.API_KEY;
axios.post(`https://${accountName}.juleb.com/api/v1/inventory/picking/delivery`, {
PartnerPicking: {
companyId: 1,
partnerId: 51,
autoValidate: true,
lines: [
{
productId: 34969,
productQty: 60,
batch: "13200001",
expiry: "02-12-2026"
}
]
}
}, {
headers: {
'accept': '*/*',
'Authorization': `TOKEN`,
'Content-Type': 'application/json'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
curl -X POST \
-H "accept: */*" \
-H "Authorization: ******" \
-H "Content-Type: application/json" \
-d '{
"PartnerPicking": {
"companyId": 1,
"partnerId": 51,
"autoValidate": true,
"lines": [
{
"productId": 34969,
"productQty": 60,
"batch": "13200001",
"expiry": "02-12-2026"
}
]
}
}' \
"https://$ACCOUNT_NAME.juleb.com/api/v1/inventory/picking/delivery"
import os
import requests
account_name = os.getenv('ACCOUNT_NAME')
api_key = os.getenv('API_KEY')
url = f'https://{account_name}.juleb.com/api/v1/inventory/picking/delivery'
headers = {
'accept': '*/*',
'Authorization': f'******',
'Content-Type': 'application/json'
}
data = {
'PartnerPicking': {
'companyId': 1,
'partnerId': 51,
'autoValidate': True,
'lines': [
{
'productId': 34969,
'productQty': 60,
'batch': '13200001',
'expiry': '02-12-2026'
}
]
}
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 201:
print(response.json())
else:
print(f'Error: {response.status_code}', response.text)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
public class Main {
public static void main(String[] args) throws Exception {
String accountName = System.getenv("ACCOUNT_NAME");
String apiKey = System.getenv("API_KEY");
String json = "{"
+ "\"PartnerPicking\": {"
+ "\"companyId\": 1,"
+ "\"partnerId\": 51,"
+ "\"autoValidate\": true,"
+ "\"lines\": [{"
+ "\"productId\": 34969,"
+ "\"productQty\": 60,"
+ "\"batch\": \"13200001\","
+ "\"expiry\": \"02-12-2026\""
+ "}]"
+ "}"
+ "}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://" + accountName + ".juleb.com/api/v1/inventory/picking/delivery"))
.header("accept", "*/*")
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
if (response.statusCode() == 201) {
System.out.println(response.body());
} else {
System.out.println("Error: " + response.statusCode() + ", " + response.body());
}
}
}
Response
{
"data": {
"id": 11004,
"name": "Demo/OUT/01187",
"origin": null,
"note": null,
"move_type": "direct",
"state": "assigned",
"scheduled_date": "2024-09-04T00:57:17.000Z",
"location_id": 11,
"location_dest_id": 5,
"picking_type_id": 2,
"partner_id": 51,
"company_id": 1,
"is_return": false,
"dest_company_id": null,
"reason": null,
"global_import": null,
"rsd_deserialization": true,
"international_export": null
}
}