How to Integrate
This guide walks through integrating with the Juleb API to create prescriptions, track their status, and retrieve the dispensed order once the pharmacy fulfills them — end to end, with a full example of each step.
Prerequisites
- A valid API key — see the Authentication Guide.
- All requests are made to
https://{account-name}.juleb.com/api/v1. - All examples below send
Authorization: ******— replace it with your real API key.
Step 1 — Gather the Required IDs
Before creating a prescription you may need up to four IDs. Each has a dedicated lookup
endpoint. doctor_id and trade_product_id are optional.
1.1 doctor_id — Clinic Doctor (optional)
Omit it if the prescription isn't tied to a specific clinic doctor. When provided, it must be a
system user whose linked partner has is_clinic_doctor = true, otherwise prescription
creation fails with Doctor with ID {id} not found or is not a clinic doctor.
GET /resources/res-users?filter=login=doctor@example.com&fields=id,login
See Get Many Users. Pick the id — this
becomes doctor_id.
1.2 selected_branch_id — Company / Branch (required)
GET /resources/company?fields=id,name
See Get Many Companies. Pick the id of
the target branch — this becomes selected_branch_id.
1.3 patient_id — Patient Partner (optional)
If you already have the patient in the system, look them up by phone. If you don't supply
patient_id, the API automatically creates a new patient from the patient object you provide
(see Step 2).
GET /resources/partner?filter=phone=0501234567&is_patient=true&fields=id,name,phone
See Get Many Partners. Pick the
id — this becomes patient_id.
1.4 trade_product_id — Product (optional)
trade_product_id is the id from inventory/product (the sellable variant), not the
product template id. It's optional on a line, but each line must supply either
trade_product_id or generic_name — use generic_name for a generic/compounded medication
that isn't tied to a specific product record.
GET /inventory/product?filter=default_code=ALAX-001&fields=id,name,default_code
See Get Many Products. Pick the
id — this becomes trade_product_id on each prescription line.
Step 2 — Create a Prescription
POST /rx
See the full field reference on Post Prescription. A typical 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/rx`, {
doctor_id: 2,
selected_branch_id: 1,
patient_id: 99,
exp_date: '2026-09-01T00:00:00.000Z',
procedure: 'annual checkup',
ship_to: 'patient',
notes: 'ERP-REF-20260811',
lines: [
{
trade_product_id: 180,
trade_qty: 1,
instruction_name: 'Once daily',
refills: 0
}
]
}, {
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 '{
"doctor_id": 2,
"selected_branch_id": 1,
"patient_id": 99,
"exp_date": "2026-09-01T00:00:00.000Z",
"procedure": "annual checkup",
"ship_to": "patient",
"notes": "ERP-REF-20260811",
"lines": [
{
"trade_product_id": 180,
"trade_qty": 1,
"instruction_name": "Once daily",
"refills": 0
}
]
}' \
"https://$ACCOUNT_NAME.juleb.com/api/v1/rx"
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/rx'
headers = {
'accept': '*/*',
'Authorization': f'******',
'Content-Type': 'application/json'
}
data = {
'doctor_id': 2,
'selected_branch_id': 1,
'patient_id': 99,
'exp_date': '2026-09-01T00:00:00.000Z',
'procedure': 'annual checkup',
'ship_to': 'patient',
'notes': 'ERP-REF-20260811',
'lines': [
{
'trade_product_id': 180,
'trade_qty': 1,
'instruction_name': 'Once daily',
'refills': 0
}
]
}
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 = "{"
+ "\"doctor_id\": 2,"
+ "\"selected_branch_id\": 1,"
+ "\"patient_id\": 99,"
+ "\"exp_date\": \"2026-09-01T00:00:00.000Z\","
+ "\"procedure\": \"annual checkup\","
+ "\"ship_to\": \"patient\","
+ "\"notes\": \"ERP-REF-20260811\","
+ "\"lines\": [{"
+ "\"trade_product_id\": 180,"
+ "\"trade_qty\": 1,"
+ "\"instruction_name\": \"Once daily\","
+ "\"refills\": 0"
+ "}]"
+ "}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://" + accountName + ".juleb.com/api/v1/rx"))
.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
1394
Store this id — you'll use it to poll status and find the POS order.
Scenario — No Doctor, Generic Medication Line
doctor_id can be omitted entirely, and a line can use generic_name instead of
trade_product_id when there's no matching product record (e.g. a compounded or generic drug):
{
"selected_branch_id": 1,
"patient_id": 99,
"procedure": "annual checkup",
"ship_to": "patient",
"notes": "ERP-REF-20260811",
"lines": [
{
"generic_name": "Amoxicillin 500mg",
"trade_qty": 1,
"instruction_name": "Once daily",
"refills": 0
}
]
}
Patient Creation — Option A: Pre-create via Partner
Create the patient first, then pass the returned id as patient_id. This gives you full
control over the partner record before the prescription is submitted.
POST /resources/partner
{
"name": "John Doe",
"phone": "0501234567",
"email": "john@example.com",
"is_patient": true
}
See Create a Partner. The response is
the new partner id — use it as patient_id in the prescription body.
Patient Creation — Option B: Inline Auto-Create
Omit patient_id and provide a patient object instead. The API looks the patient up by
phone; if not found, it creates a new partner record automatically:
{
"doctor_id": 2,
"selected_branch_id": 1,
"patient": {
"name": "John Doe",
"phone": "0501234567",
"email": "john@example.com"
},
"lines": [
{
"trade_product_id": 180,
"trade_qty": 2,
"instruction_name": "Twice daily"
}
]
}
patient_id or patient.phone is requiredIf neither is provided, the request fails with
Patient information is incomplete. Either patient_id or patient.phone is required.
Optional Shipping Service Line
To add a delivery fee, include shipping_service_id — the id of a product with
type = 'service' from inventory/product:
{
"shipping_service_id": 45
}
Using notes as an External Reference
notes is a free-text field you can use to store your own ERP's internal order/reference
number. It's persisted on the prescription record and is filterable, so you can look up a
prescription by your own reference without storing the Juleb id locally:
{
"notes": "ERP-REF-20260811"
}
To retrieve it later:
GET /rx?filter=notes=ERP-REF-20260811
Step 3 — Check Prescription Status & Lines
Get the Prescription
GET /rx/1394
See Get One Prescription.
Get Prescription Lines
GET /rx/1394/lines
See Get Prescription Lines. Each line has a line_state:
| Value | Meaning |
|---|---|
ready | Awaiting dispensing. |
dispensed | Medication has been dispensed. |
cancelled | Dispensing was cancelled. |
Step 4 — Fetch the POS Order After Dispensing
Once a prescription line is dispensed, the pharmacy creates a POS Order
linked via rx_id. Use this to retrieve pricing and the actual dispensed products.
Find the Order by rx_id
GET /pos/order?filter=rx_id=1394&fields=id,name,state,amount_total,partner_id,rx_id
See Get Many Orders.
Get the Order Lines
GET /pos/order/9091/line?fields=id,product_id,qty,price_unit,rx_line_id,medication_instruction
See Get Many Lines. The rx_line_id on each
order line links back to the specific prescription line that was dispensed. The product_id
here is the actual product dispensed by the pharmacist — it may differ from the prescribed
trade_product_id if a substitution was made.
Product Management
Product Model Relationship
product_template (1)
|
+---- product_product (many variants)
id <- used as trade_product_id
product_tmpl_id (FK to product_template)
default_code (SKU / barcode)
When you create a product template, one product_product variant is automatically created for
it — you can look up the variant via product_tmpl_id or default_code.
Create a Product Template
POST /inventory/product-template
{
"name": "A-Lax Cap",
"type": "product",
"categ_id": 5,
"list_price": 1770,
"default_code": "ALAX-001",
"uom_id": 1,
"uom_po_id": 1,
"taxes_id": [],
"j_active_ingredient": []
}
See Create a Product Template
for the full field reference (categ_id comes from
Product Category, taxes_id from
Account Tax, and j_active_ingredient from
Active Ingredient).
Retrieve the Product (product_product) id After Creation
GET /inventory/product?filter=default_code=ALAX-001&fields=id
The id returned is the trade_product_id to use in prescription lines. Alternatively, query
by the template relation:
GET /inventory/product?filter=product_tmpl_id=9123&fields=id
Error Handling
| Status | Message | Cause |
|---|---|---|
| 400 | Prescription lines are required. | lines was missing or empty. |
| 400 | Line {n} is missing required fields. | A line had neither trade_product_id nor generic_name, or trade_qty was missing/<= 0. |
| 400 | Product with ID {id} not found. | trade_product_id didn't resolve to an active product. |
| 400 | Shipping service with ID {id} not found. | shipping_service_id didn't resolve to a product with type = 'service'. |
| 400 | Patient information is incomplete. Either patient_id or patient.phone is required. | Neither patient_id nor patient.phone was provided. |
| 400 | Patient with ID {id} not found. | patient_id didn't match an existing partner. |
| 400 | Doctor with ID {id} not found or is not a clinic doctor. | doctor_id didn't match a user whose partner has is_clinic_doctor = true. |
| 400 | Selected branch ID is required. | selected_branch_id was missing. |
| 400 | Branch with ID {id} not found. | selected_branch_id didn't match an existing company. |
| 400 | Invalid expiration date format. | exp_date couldn't be parsed as a date. |
| 401 | Unauthorized | Missing or invalid Authorization header. |
| 404 | Record not found | The id requested on a GET endpoint doesn't exist, or a line doesn't belong to the given parent prescription. |
Quick Reference
| Purpose | Method | Endpoint |
|---|---|---|
| List doctors | GET | /resources/res-users |
| List branches | GET | /resources/company |
| List / find patients | GET | /resources/partner |
| Create a patient | POST | /resources/partner |
| List products (variants) | GET | /inventory/product |
| List / create product templates | GET / POST | /inventory/product-template |
| Create a prescription | POST | /rx |
| Get a prescription | GET | /rx/:id |
| Get prescription lines | GET | /rx/:id/lines |
Find the POS order by rx_id | GET | /pos/order?filter=rx_id=:rxId |
| Get POS order lines | GET | /pos/order/:orderId/line |
Querying the Data Afterward
Every GET list endpoint referenced above supports fields/filter/page/limit — see
Mastering API Queries for the full syntax.