Post POS Order
Endpoint Overview
This API endpoint provides a detailed overview of the endpoint responsible for creating a POS Order within the POS module of the Juleb ERP.
Order creation supports two ways of being triggered:
- Manual mode (default): you already manage your own POS session/config and pass
pos_session_id+payment_method_iddirectly. - Auto mode: you pass
autoCreateSession: true+company_idand let the API find-or-create a session/config/payment method/pricelist for you.
See the How to Integrate guide for a full walkthrough of both modes, including when to use each one.
Endpoint Details
- Method: POST
- URL:
/api/v1/pos/order
Parameters
- Path Parameters: None
- Query Parameters: None
Request Body
{
"pos_session_id": integer,
"pricelist_id": integer,
"payment_method_id": integer,
"partner_id": integer,
"company_id": integer,
"pos_reference": string,
"autoCreateSession": boolean,
"autoSessionConfig": {
"name": string,
"allowOutOfStock": boolean
},
"selectProductByGtin": boolean,
"lines": [
{
"product_id": integer,
"qty": integer,
"lot_name": string,
"qr_code": string[],
"price_unit": integer,
"discount_by_percent": integer
}
]
}
Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
pos_session_id | integer | Yes, unless autoCreateSession is true | ID of an existing, opened POS session to attach the order to. Required together with payment_method_id in manual mode. |
payment_method_id | integer | Yes, unless autoCreateSession is true | ID of the payment method used to settle the order. In auto mode this is resolved automatically from company_id. |
pricelist_id | integer | No | Pricelist to price the order lines with. Defaults to pricelist 1 (or the company's default pricelist in auto mode) if omitted. |
partner_id | integer | No | ID of the customer (partner) the order is attributed to. Omit or send false for an anonymous/walk-in sale. |
company_id | integer | Yes, when autoCreateSession is true | Company the order (and auto-created session) belongs to. Ignored in manual mode (it's derived from pos_session_id). |
pos_reference | string | No | Free-text reference stored on the order's internal note (e.g. an external/originating order number for traceability). |
autoCreateSession | boolean | No (default false) | Automation field. When true, the API finds or creates a POS config/session for company_id instead of requiring a pre-existing pos_session_id. See Options below. |
autoSessionConfig | object | No | Automation field. Only used when autoCreateSession is true. Lets you target/create a specific POS config instead of the first one found for the company. See Options. |
selectProductByGtin | boolean | No (default false) | Automation field. When true, every line is resolved from its qr_code values (GTIN + batch) instead of an explicit product_id/qty. See Options. |
lines | array (required) | Yes | The products sold. At least one line is required. See the line field table below. |
Line fields (lines[])
| Field | Type | Required | Description |
|---|---|---|---|
product_id | integer | Yes, unless qr_code is provided on this line | The product being sold. |
qty | integer | Yes, unless qr_code is provided on this line | Quantity sold. Must be at least 1. |
lot_name | string | No | Batch/lot number to deduct stock from. Required for lot/serial-tracked products unless the session's config allows selling out of stock. |
qr_code | string[] | Depends on mode — see Options | One or more scanned 2D GS1 codes. Used either for serial-number traceability (manual mode) or full product/lot resolution (when selectProductByGtin is true). |
price_unit | integer | No | Overrides the unit price instead of using the pricelist price. |
discount_by_percent | integer | No (default 0) | Per-line discount percentage, between 0 and 100. |
autoCreateSession options
false/ omitted (default): manual mode — you must supply a valid, openpos_session_idandpayment_method_idyourself.true: auto mode —company_idbecomes required. The API will:- Look for an existing POS config for
company_id(optionally narrowed byautoSessionConfig), creating one if none matches. - Reuse an existing opened session for that config, or open a new one.
- Auto-fill
payment_method_idandpricelist_idfor you if they weren't provided.
- Look for an existing POS config for
autoSessionConfig options
Only read when autoCreateSession is true. An object with:
name(string, optional): match/create the POS config with this exact name. If omitted, a default name ofapi-session-{company_id}is used when a new config needs to be created.allowOutOfStock(boolean, optional, defaultfalse): match/create a config that allows (or disallows) selling products without available stock/lot.
selectProductByGtin options
false/ omitted (default): you provideproduct_id+qtyper line yourself. You may still attachqr_codeto a line purely for serial-number traceability — it will be recorded against the line without affecting product/quantity resolution.true: every line in the request must provideqr_codeinstead ofproduct_id/qty. Each code is parsed for its GTIN and batch number, the matching product is looked up automatically, and codes sharing the same batch + GTIN are grouped together withqtyset to the number of codes scanned for that batch.
Response
- 201 OK: Successfully created the record.
- 400 Bad Request: Bad request.
- 401 Unauthorized: Unauthorized.
Response Body
{
"data": {
"id": integer,
"pos_reference": string
}
}
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/pos/order`, {
pos_session_id: 1799,
pricelist_id: 1,
payment_method_id: 5,
partner_id: false,
pos_reference: 'EXT-ORDER-10293',
lines: [
{
product_id: 91,
qty: 1,
lot_name: "923190297493",
discount_by_percent: 0,
qr_code: ['010628602300100021557558631092319029749317270915']
}
]
}, {
headers: {
'accept': '*/*',
'Authorization': `******`,
'Content-Type': 'application/json'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
curl -X POST \
-H "accept: */*" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pos_session_id": 1799,
"pricelist_id": 1,
"payment_method_id": 5,
"partner_id": 1,
"pos_reference": "EXT-ORDER-10293",
"lines": [
{
"product_id": 91,
"qty": 1,
"lot_name": "923190297493",
"discount_by_percent": 0,
"qr_code": ["010628602300100021557558631092319029749317270915"]
}
]
}' \
"https://$ACCOUNT_NAME.juleb.com/api/v1/pos/order"
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/pos/order'
headers = {
'accept': '*/*',
'Authorization': f'******',
'Content-Type': 'application/json'
}
data = {
'pos_session_id': 1799,
'pricelist_id': 1,
'payment_method_id': 5,
'partner_id': False,
'pos_reference': 'EXT-ORDER-10293',
'lines': [
{
'product_id': 91,
'qty': 1,
'lot_name': '923190297493',
'discount_by_percent': 0,
'qr_code': ['010628602300100021557558631092319029749317270915']
}
]
}
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 = "{\n" +
" \"pos_session_id\": 1799,\n" +
" \"pricelist_id\": 1,\n" +
" \"payment_method_id\": 5,\n" +
" \"partner_id\": 1,\n" +
" \"pos_reference\": \"EXT-ORDER-10293\",\n" +
" \"lines\": [\n" +
" {\n" +
" \"product_id\": 91,\n" +
" \"qty\": 1,\n" +
" \"lot_name\": \"923190297493\",\n" +
" \"discount_by_percent\": 0,\n" +
" \"qr_code\": [\"010628602300100021557558631092319029749317270915\"]\n" +
" }\n" +
" ]\n" +
"}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://" + accountName + ".juleb.com/api/v1/pos/order"))
.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
[
{
"id": 7155,
"pos_reference": "Order 01799-006-0004"
}
]