> For the complete documentation index, see [llms.txt](https://docs.simplespa.net/simplespa-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.simplespa.net/simplespa-documentation/api/simplespa-enterprise-api/write/product-inventory.md).

# Product Inventory

Note: API Beta Access, see [API Terms of Use](https://docs.simplespa.net/simplespa-documentation/api/simplespa-enterprise-api/integrations/api-terms-of-use)

***

### Overview

The Product Inventory Write API allows Enterprise accounts to **adjust product stock levels** programmatically using the same logic as the SimpleSpa back office UI.

This endpoint is designed for integrations that need to:

* Sync inventory with external POS systems
* Deduct stock when a sale occurs outside SimpleSpa
* Add stock when new inventory is received
* Record inventory adjustments (e.g., damaged, lost, manual corrections)

Each call creates an inventory transaction record and updates the product’s current quantity for the specific business location.

> 🧾 For reading products and their current stock levels, use the **Products Endpoint**:\
> `POST https://my.simplespa.com/api/v1/products.php`

***

### Endpoint

```http
POST https://my.simplespa.com/api/v1/write/product.php
```

### Authentication

You must include a valid Authorization header using your SimpleSpa API Key:

```http
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

> Replace YOUR\_API\_KEY with your SimpleSpa Enterprise API Key.\
> API Key Mode must be 2 (Write) or 3 (Read + Write) to use this endpoint.

***

### Rate Limiting

This endpoint has a strict rate limit of:

```
10 requests per 60 seconds per API key
```

If exceeded, the API will return a 429 response.

***

### Request Body

| Parameter    | Type    | Required | Description                                                                                                   |
| ------------ | ------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| product\_id  | string  | ✔        | The product ID.                                                                                               |
| qty          | integer | ✔        | Quantity change. Positive to add stock, negative to deduct stock. The final stock cannot go below 0.          |
| unit\_price  | number  | ✔        | Unit cost for this inventory movement (used for reporting and cost tracking).                                 |
| date         | string  | Optional | Inventory transaction date in YYYY-MM-DD format. If omitted, the current date/time is used.                   |
| vendor\_id   | integer | Optional | Existing vendor ID in SimpleSpa. If provided, this vendor will be used.                                       |
| vendor\_name | string  | Optional | Vendor name. If vendor\_id is not provided and vendor\_name is provided, a vendor may be created or matched.  |
| reason       | string  | Optional | Free-text reason or note for this adjustment (e.g., external\_pos\_sale, manual\_adjustment, damaged\_stock). |

> You should provide at least one of vendor\_id or vendor\_name when recording purchases or adjustments tied to a supplier or source.

***

### Example Request – Deduct Stock After External Sale

```bash
curl -X POST https://my.simplespa.com/api/v1/write/product.php \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "product_id": "a4f3e0c0c56d6ab3e9b0b51e77e9b123",
  "qty": -2,
  "unit_price": 15.50,
  "date": "2025-12-06",
  "vendor_name": "External POS",
  "reason": "external_pos_sale"
}'
```

In this example:

* Stock for the specified product will be reduced by 2 units.
* A new inventory transaction will be recorded using the provided unit\_price.
* If needed, a vendor entry named External POS may be created or reused.

***

### Example Request – Add Stock for New Purchase

```bash
curl -X POST https://my.simplespa.com/api/v1/write/product.php \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "product_id": "1234",
  "qty": 10,
  "unit_price": 8.00,
  "date": "2025-12-06",
  "vendor_id": 5,
  "reason": "new_shipment_from_supplier"
}'
```

In this example:

* Stock for product ID 1234 will be increased by 10 units.
* Vendor with ID 5 will be used for this inventory transaction.
* Cost and stock levels are updated for reporting and stock tracking.

***

### Example Response

```json
{
  "success": true,
  "product_id": "a4f3e0c0c56d6ab3e9b0b51e77e9b123",
  "product_id_raw": 1234,
  "old_stock": 5,
  "new_stock": 15,
  "qty_delta": 10,
  "reason": "new_shipment_from_supplier"
}
```

***

### Error Responses

Missing or Invalid Authorization

```json
{ "error": "Missing or invalid Authorization header" }
```

#### API Key Not Authorized

```json
{ "error": "This API key is not authorized for inventory write operations (requires mode 2 or 3)." }
```

#### Product Not Found

```json
{ "error": "Product not found for this business/location." }
```

#### Invalid Parameters

```json
{ "error": "product_id is required." }
```

```json
{ "error": "qty must be a non-zero integer." }
```

```json
{ "error": "Resulting stock cannot be negative." }
```

#### Rate Limit Exceeded

```json
{
  "error": "Rate limit exceeded for product inventory writes. Please slow down your requests.",
  "retry_after": 60
}
```

### Notes

* Use the Products Endpoint (/api/v1/products.php) to fetch product lists, labels, and current stock before writing.
* This endpoint is idempotent per call in the sense that each call records a separate inventory movement; it does notoverwrite stock, it adjusts it.
* Inventory writes are per business location. The API key’s lid determines which location’s stock is affected.
* Always store your API key securely on the server side.
* Do not expose your API key to client-side JavaScript, mobile apps, or public environments.

> ⚠️ IMPORTANT: For external POS or e-commerce integrations, ensure you only call this endpoint once per sale or stock event to avoid double-counting inventory changes.
>
> ⚠️ IMPORTANT: Never expose your private API key in client-side JavaScript, mobile apps, or public code repositories. Always perform API calls from secure, server-side code.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.simplespa.net/simplespa-documentation/api/simplespa-enterprise-api/write/product-inventory.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
