Purchase Invoice API
The Purchase Invoice API allows you to create purchase invoices that can either create new products or update existing products with additional inventory. This endpoint supports file uploads for product variant images and handles brand creation automatically.
This endpoint uses multipart/form-data format to support file uploads. Make sure to include the proper headers when making requests.
Endpoint Details
Endpoint: POST /purchase-invoices
Content-Type: multipart/form-data
Base URL: https://jethings-backend.fly.dev
x-store-id: <store_id>
Authorization: Bearer <token>
Request Structure
The request uses multipart/form-data format with:
jsonData : A JSON string containing the purchase invoice data
Files : Product variant images uploaded with specific field names
Action Types
The API supports two action types:
Use CREATE when introducing a brand new product to your inventory. {
"actionType" : "CREATE" ,
"warehouseId" : "uuid" ,
"supplierId" : "uuid" ,
"purchaseDate" : "2024-01-15" ,
"referenceNumber" : "REF-001" ,
"amountPaid" : 100.80 ,
"isShipped" : false ,
"isPaid" : false ,
"productTypeId" : "uuid" ,
"product" : {
"title" : "Product Name" ,
"ref" : "PROD-001" ,
"description" : "Product description" ,
"brandName" : "Nike"
},
"variants" : [
{
"itemName" : "Blue T-Shirt" ,
"color" : "Blue" ,
"pointer" : [
{ "qty" : 49 , "value" : 30 , "barcode" : "PSH-BLUE-30" }
]
}
],
"barcodes" : [ "B001" , "B002" ]
}
Required fields for CREATE:
actionType: "CREATE"
product.title: Product name
variants: Array of variant objects
warehouseId, supplierId, purchaseDate, referenceNumber, amountPaid, productTypeId, isShipped, isPaid
Use UPDATE when adding stock to an existing product. {
"actionType" : "UPDATE" ,
"productId" : "existing-product-uuid" ,
"warehouseId" : "uuid" ,
"supplierId" : "uuid" ,
"purchaseDate" : "2024-01-15" ,
"referenceNumber" : "REF-002" ,
"amountPaid" : 150.50 ,
"isShipped" : false ,
"isPaid" : false ,
"productTypeId" : "uuid" ,
"variants" : [
{
"itemId" : "existing-item-uuid" ,
"itemName" : "Blue T-Shirt" ,
"color" : "Blue" ,
"pointer" : [
{ "qty" : 49 , "value" : 30 }
]
}
]
}
Required fields for UPDATE:
actionType: "UPDATE"
productId: UUID of existing product (required for UPDATE)
variants: Array of variant objects
Data Structures
Product Object
The product object is used in CREATE actions to define product details.
Field Type Required Description
titlestring ✅ Yes Product title/name (e.g., “Premium T-Shirt”) refstring No Product reference code (e.g., “TSH-001”) descriptionstring No Product description brandIdstring (UUID) No UUID of an existing brand brandNamestring No Brand name (will create brand if it doesn’t exist)
For brand selection, you can use either brandId (existing brand) or brandName (auto-create brand). If both are provided, brandName takes precedence.
Variant Structure
The variants array contains items and their sizes with quantities.
Field Type Required Description
itemIdstring No For UPDATE only: UUID of existing item to add inventory toitemNamestring ✅ Yes Name for the item variant (e.g., “Blue T-Shirt”, “Red Shirt”) colorstring ✅ Yes Color variant (e.g., “Blue”, “Green”, “Red”) pointerarray ✅ Yes Array of pointer values (sizes, etc.)
Pointer Structure
Each pointer represents a size with quantity:
{
"qty" : 49 , // Quantity for this size
"value" : 30 , // Pointer value (e.g., size 30)
"barcode" : "PSH-BLUE-30" // Optional barcode for this pointer
}
File Upload Mechanism
Naming Convention
Product variant images must be uploaded using this naming pattern:
CREATE Actions
UPDATE Actions
Upload images for all variants: variant_0_images: [image1.jpg, image2.jpg]
variant_1_images: [image1.jpg, image2.jpg]
variant_2_images: [image1.jpg]
Upload images only for NEW items (items without itemId): variant_0_images: [new-item-image.jpg] # First new item
variant_1_images: [another-new-item.jpg] # Second new item
Important: Don’t upload images for existing items (with itemId). The index counts only NEW items.
Multiple Images per Variant
You can upload multiple images for each variant by sending multiple files with the same field name:
variant_0_images: [image1.jpg, image2.jpg, image3.jpg]
variant_1_images: [image1.jpg, image2.jpg]
jpg, jpeg, png, gif, webp
Complete Examples
This section provides detailed examples for both CREATE and UPDATE action types.
CREATE Action Examples
Example 1: CREATE - New Product with Brand Creation
This example creates a new product with auto-brand creation.
Use when: You’re introducing a brand new product to your inventory that doesn’t exist yet.
curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
-H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
-H "Authorization: Bearer <token>" \
-F 'jsonData={"actionType":"CREATE","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-001","amountPaid":100.80,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","product":{"title":"Premium Cotton T-Shirt","ref":"TSH-001","description":"High-quality cotton t-shirt with premium finish","brandName":"Nike"},"variants":[{"itemName":"Blue T-Shirt","pointer":[{"qty":49,"value":30,"barcode":"PSH-BLUE-30"}],"color":"Blue"},{"itemName":"Green T-Shirt","pointer":[{"qty":49,"value":30,"barcode":"PSH-GREEN-30"}],"color":"Green"}],"barcodes":["0988-TY","09877-GB"]}' \
-F '[email protected] ' \
-F '[email protected] ' \
-F '[email protected] '
Success Response:
{
"purchaseInvoice" : {
"id" : "invoice-uuid" ,
"supplierId" : "cjdtw2flpntu6jmsh0row6yc" ,
"storeId" : "x1vt8qlr0l7ju7tbe2an6ov0" ,
"supplierInvoiceNo" : "REF-2024-001" ,
"priceList" : "default" ,
"postingTime" : "2024-01-15T10:00:00.000Z" ,
"warehouseId" : "x1vt8qlr0l7ju7tbe2an6ov0" ,
"amountPaid" : 100.80 ,
"createAt" : "2024-01-15T10:00:00.000Z"
},
"product" : {
"success" : true ,
"message" : "Product and items created successfully" ,
"product" : {
"id" : "product-uuid" ,
"title" : "Premium Cotton T-Shirt" ,
"ref" : "TSH-001" ,
"description" : "High-quality cotton t-shirt with premium finish" ,
"brandId" : "brand-uuid"
},
"items" : [
{
"item" : {
"id" : "item-uuid-1" ,
"productId" : "product-uuid"
},
"itemVariants" : [
{
"pointer" : 30 ,
"color" : "Blue" ,
"qty" : 49 ,
"barcode" : "PSH-BLUE-30"
}
],
"images" : [
{
"success" : true ,
"filename" : "blue-image-1.jpg" ,
"url" : "https://storage.example.com/products/items/image.jpg"
}
]
}
]
}
}
Example 2: CREATE - Using Existing Brand
This example creates a new product using an existing brand ID instead of creating a new brand.
Use when: Creating a new product and want to link to an existing brand in your system.
curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
-H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
-H "Authorization: Bearer <token>" \
-F 'jsonData={"actionType":"CREATE","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-002","amountPaid":150.50,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","product":{"title":"Premium Jeans","ref":"JEAN-001","description":"Classic fit jeans","brandId":"existing-brand-uuid"},"variants":[{"itemName":"Blue Jeans","color":"Blue","pointer":[{"qty":30,"value":32,"barcode":"JEAN-BLUE-32"}]}]}' \
-F '[email protected] '
UPDATE Action Examples
Example 3: UPDATE - Add Inventory to Existing Item
Use this when adding more stock to an existing color/variant.
Use when: Adding inventory to an existing item variant. No file uploads needed.
curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
-H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
-H "Authorization: Bearer <token>" \
-F 'jsonData={"actionType":"UPDATE","productId":"a7hkmoj8p142p2vtp450byk2","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-003","amountPaid":100.80,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","variants":[{"itemId":"existing-blue-item-uuid","itemName":"Blue T-Shirt","color":"Blue","pointer":[{"qty":49,"value":30}]}]}'
Note: No file uploads needed when using itemId for existing items.
Example 4: UPDATE - Create New Item (Different Color)
Use this when adding a new color variant to an existing product.
Use when: Creating a new item variant (new color) for an existing product. Requires file uploads.
curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
-H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
-H "Authorization: Bearer <token>" \
-F 'jsonData={"actionType":"UPDATE","productId":"a7hkmoj8p142p2vtp450byk2","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-004","amountPaid":75.25,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","variants":[{"itemName":"Red T-Shirt","color":"Red","pointer":[{"qty":25,"value":30,"barcode":"PSH-RED-30"}]}]}' \
-F '[email protected] '
Note: When creating a new item (different color) in UPDATE action, you must provide itemName and upload images using variant_0_images.
Example 5: UPDATE - Mixed (Existing + New Items)
Adding inventory to Blue item and creating Red and Green items.
Use when: Adding inventory to existing items AND creating new item variants in the same request.
curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
-H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
-H "Authorization: Bearer <token>" \
-F 'jsonData={"actionType":"UPDATE","productId":"a7hkmoj8p142p2vtp450byk2","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-005","amountPaid":200.00,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","variants":[{"itemId":"existing-blue-item-uuid","itemName":"Blue T-Shirt","color":"Blue","pointer":[{"qty":30,"value":30}]},{"itemName":"Red T-Shirt","color":"Red","pointer":[{"qty":25,"value":30,"barcode":"PSH-RED-30"}]},{"itemName":"Green T-Shirt","color":"Green","pointer":[{"qty":20,"value":30,"barcode":"PSH-GREEN-30"}]}]}' \
-F '[email protected] ' \
-F '[email protected] '
The file indices (variant_0_images, variant_1_images) correspond to NEW items only (Red and Green), not the existing Blue item.
Response Structure
Success Response
{
"purchaseInvoice" : {
"id" : "invoice-uuid" ,
"supplierId" : "cjdtw2flpntu6jmsh0row6yc" ,
"storeId" : "x1vt8qlr0l7ju7tbe2an6ov0" ,
"supplierInvoiceNo" : "REF-2024-001" ,
"priceList" : "default" ,
"postingTime" : "2024-01-15T10:00:00.000Z" ,
"dueTime" : "2024-01-15T00:00:00.000Z" ,
"updateStock" : true ,
"warehouseId" : "x1vt8qlr0l7ju7tbe2an6ov0" ,
"amountPaid" : 100.80 ,
"createAt" : "2024-01-15T10:00:00.000Z" ,
"updateAt" : "2024-01-15T10:00:00.000Z"
},
"purchaseInvoiceItems" : [
{
"id" : "item-1-uuid" ,
"purchaseInvoiceId" : "invoice-uuid" ,
"itemVariantId" : "variant-1-uuid" ,
"quantity" : 49 ,
"unitPrice" : 2.06 ,
"totalPrice" : 101.06 ,
"isActive" : true ,
"createdAt" : "2024-01-15T10:00:00.000Z" ,
"updatedAt" : "2024-01-15T10:00:00.000Z"
}
],
"product" : {
"success" : true ,
"message" : "Product and items created successfully" ,
"product" : {
"id" : "product-uuid" ,
"storeId" : "x1vt8qlr0l7ju7tbe2an6ov0" ,
"productTypeId" : "ywb1l1vyre5nm27n2fr8vpwz" ,
"brandId" : "brand-uuid" ,
"title" : "Premium Cotton T-Shirt" ,
"ref" : "TSH-001" ,
"description" : "High-quality cotton t-shirt with premium finish" ,
"isActive" : true ,
"createdAt" : "2024-01-15T10:00:00.000Z" ,
"updatedAt" : "2024-01-15T10:00:00.000Z"
},
"items" : [
{
"item" : {
"id" : "item-uuid-1" ,
"productId" : "product-uuid" ,
"description" : "Item variant 1" ,
"isActive" : true
},
"itemVariants" : [
{
"itemVariant" : {
"id" : "item-variant-uuid"
},
"pointer" : 30 ,
"color" : "Blue" ,
"qty" : 49 ,
"barcode" : "PSH-BLUE-30"
}
],
"images" : [
{
"success" : true ,
"filename" : "blue-image-1.jpg" ,
"url" : "https://storage.example.com/products/items/image.jpg"
}
]
}
]
}
}
Error Responses
400 Bad Request
{
"statusCode" : 400 ,
"message" : "Product type not found" ,
"error" : "Bad Request"
}
403 Forbidden
{
"statusCode" : 403 ,
"message" : "You do not have access to this store" ,
"error" : "Forbidden"
}
404 Not Found
{
"statusCode" : 404 ,
"message" : "Item with id xyz not found" ,
"error" : "Not Found"
}
Important Notes
CREATE vs UPDATE
Creates a new product and its items/variants
All variants get new items with the provided itemName
Requires uploading images for all variants
Use when introducing completely new products
Updates an existing product
Can add to existing items (with itemId) or create new items (without itemId)
Only upload images for new items (without itemId)
Use when restocking existing products
itemName Field
Always required for all variants in both CREATE and UPDATE actions
This name is stored in the itemVariant.name column in the database
Examples: “Blue T-Shirt”, “Red Shirt”, “Green Variant”
itemId Usage in UPDATE
With itemId Add inventory to an existing item No file uploads needed
Without itemId Create a new item Requires file uploads
File Upload Rules
CREATE Actions
UPDATE with itemId
UPDATE without itemId
Upload images for ALL variants: variant_0_images : [ variant - 0 - img1 . jpg , variant - 0 - img2 . jpg ]
variant_1_images : [ variant - 1 - img1 . jpg ]
variant_2_images : [ variant - 2 - img1 . jpg , variant - 2 - img2 . jpg ]
No uploads needed for existing items:// If all variants have itemId, no file uploads required
Upload only for NEW items . Index counts only new items: // Example: Blue has itemId, Red and Green are new
variants : [
{ itemId: "blue-id" , ... }, // Existing - no upload
{ itemName: "Red T-Shirt" , ... }, // New - variant_0_images
{ itemName: "Green T-Shirt" , ... } // New - variant_1_images
]
Stock Management
Quantities (qty in pointer) automatically update warehouse stock
Stock is distributed across warehouse bins
updateStock: true enables real-time stock updates
Brand Handling
Using Existing Brand
Auto-Create Brand
Priority Rule
{
"product" : {
"title" : "Product Name" ,
"brandId" : "existing-brand-uuid"
}
}
Use brandId to reference an existing brand {
"product" : {
"title" : "Product Name" ,
"brandName" : "Nike"
}
}
Use brandName to auto-create a brand if it doesn’t exist If both brandId and brandName are provided, brandName takes precedence {
"product" : {
"brandId" : "old-uuid" ,
"brandName" : "New Brand" // This wins!
}
}
Barcode Assignment
The API supports two methods for barcode assignment:
Individual barcodes in pointer values - Specific to each size
Global barcodes array - Applied to all item variants
Both methods work simultaneously.
Summary
Choose Action Type
Select CREATE for new products or UPDATE for existing products
Prepare Data
Structure your JSON data with product info, variants, and inventory details
Upload Files
Follow the naming convention for variant images based on your action type
Send Request
Use multipart/form-data with proper headers
Handle Response
Receive complete purchase invoice, product, and stock information
This API provides a flexible way to manage purchase invoices while automatically handling product creation, variant management, inventory updates, and file uploads. Choose the appropriate action type based on whether you’re introducing a new product (CREATE) or restocking an existing one (UPDATE).