Zoho Inventory
name: zoho-inventory
by byungkyu · published 2026-03-22
$ claw add gh:byungkyu/byungkyu-zoho-inventory---
name: zoho-inventory
description: |
Zoho Inventory API integration with managed OAuth. Manage items, sales orders, invoices, purchase orders, bills, contacts, and shipments.
Use this skill when users want to read, create, update, or delete inventory items, sales orders, invoices, purchase orders, bills, or other inventory records in Zoho Inventory.
For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
Requires network access and valid Maton API key.
metadata:
author: maton
version: "1.0"
clawdbot:
emoji: 🧠
requires:
env:
- MATON_API_KEY
---
# Zoho Inventory
Access the Zoho Inventory API with managed OAuth authentication. Manage items, sales orders, invoices, purchase orders, bills, contacts, shipment orders, and item groups with full CRUD operations.
Quick Start
# List items
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/items')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOFBase URL
https://gateway.maton.ai/zoho-inventory/inventory/v1/{endpoint}The gateway proxies requests to `www.zohoapis.com/inventory/v1` and automatically injects your OAuth token.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY**Environment Variable:** Set your API key as `MATON_API_KEY`:
export MATON_API_KEY="YOUR_API_KEY"Getting Your API Key
1. Sign in or create an account at [maton.ai](https://maton.ai)
2. Go to [maton.ai/settings](https://maton.ai/settings)
3. Copy your API key
Connection Management
Manage your Zoho Inventory OAuth connections at `https://ctrl.maton.ai`.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=zoho-inventory&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOFCreate Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'zoho-inventory'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOFGet Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF**Response:**
{
"connection": {
"connection_id": "21fd90f9-5935-43cd-b6c8-bde9d915ca80",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "zoho-inventory",
"metadata": {}
}
}Open the returned `url` in a browser to complete OAuth authorization.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOFSpecifying Connection
If you have multiple Zoho Inventory connections, specify which one to use with the `Maton-Connection` header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/items')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '21fd90f9-5935-43cd-b6c8-bde9d915ca80')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOFIf omitted, the gateway uses the default (oldest) active connection.
API Reference
Available Modules
| Module | Endpoint | Description |
|--------|----------|-------------|
| Items | `/items` | Products and services |
| Item Groups | `/itemgroups` | Grouped product variants |
| Contacts | `/contacts` | Customers and vendors |
| Sales Orders | `/salesorders` | Sales orders |
| Invoices | `/invoices` | Sales invoices |
| Purchase Orders | `/purchaseorders` | Purchase orders |
| Bills | `/bills` | Vendor bills |
| Shipment Orders | `/shipmentorders` | Shipment tracking |
Items
#### List Items
GET /zoho-inventory/inventory/v1/items**Example:**
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/items')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF**Response:**
{
"code": 0,
"message": "success",
"items": [
{
"item_id": "1234567890000",
"name": "Widget",
"status": "active",
"sku": "WDG-001",
"rate": 25.00,
"purchase_rate": 10.00,
"is_taxable": true
}
],
"page_context": {
"page": 1,
"per_page": 200,
"has_more_page": false
}
}#### Get Item
GET /zoho-inventory/inventory/v1/items/{item_id}#### Create Item
POST /zoho-inventory/inventory/v1/items
Content-Type: application/json
{
"name": "Widget",
"rate": 25.00,
"purchase_rate": 10.00,
"sku": "WDG-001",
"item_type": "inventory",
"product_type": "goods",
"unit": "pcs",
"is_taxable": true
}**Required Fields:**
**Optional Fields:**
**Example:**
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"name": "Widget",
"rate": 25.00,
"purchase_rate": 10.00,
"sku": "WDG-001",
"item_type": "inventory",
"product_type": "goods",
"unit": "pcs"
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/items', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF**Response:**
{
"code": 0,
"message": "The item has been added.",
"item": {
"item_id": "1234567890000",
"name": "Widget",
"status": "active",
"rate": 25.00,
"purchase_rate": 10.00,
"sku": "WDG-001"
}
}#### Update Item
PUT /zoho-inventory/inventory/v1/items/{item_id}
Content-Type: application/json
{
"name": "Updated Widget",
"rate": 30.00
}#### Delete Item
DELETE /zoho-inventory/inventory/v1/items/{item_id}#### Item Status Actions
# Mark as active
POST /zoho-inventory/inventory/v1/items/{item_id}/active
# Mark as inactive
POST /zoho-inventory/inventory/v1/items/{item_id}/inactiveContacts
#### List Contacts
GET /zoho-inventory/inventory/v1/contacts**Query Parameters:**
**Example:**
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/contacts')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF#### Get Contact
GET /zoho-inventory/inventory/v1/contacts/{contact_id}#### Create Contact
POST /zoho-inventory/inventory/v1/contacts
Content-Type: application/json
{
"contact_name": "Acme Corporation",
"contact_type": "customer",
"company_name": "Acme Corp",
"email": "billing@acme.com",
"phone": "+1-555-1234"
}**Required Fields:**
**Optional Fields:**
#### Update Contact
PUT /zoho-inventory/inventory/v1/contacts/{contact_id}#### Delete Contact
DELETE /zoho-inventory/inventory/v1/contacts/{contact_id}#### Contact Status Actions
# Mark as active
POST /zoho-inventory/inventory/v1/contacts/{contact_id}/active
# Mark as inactive
POST /zoho-inventory/inventory/v1/contacts/{contact_id}/inactiveSales Orders
#### List Sales Orders
GET /zoho-inventory/inventory/v1/salesorders**Example:**
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/salesorders')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF#### Get Sales Order
GET /zoho-inventory/inventory/v1/salesorders/{salesorder_id}#### Create Sales Order
POST /zoho-inventory/inventory/v1/salesorders
Content-Type: application/json
{
"customer_id": "1234567890000",
"date": "2026-02-06",
"line_items": [
{
"item_id": "1234567890001",
"quantity": 5,
"rate": 25.00
}
]
}**Required Fields:**
**Optional Fields:**
#### Update Sales Order
PUT /zoho-inventory/inventory/v1/salesorders/{salesorder_id}#### Delete Sales Order
DELETE /zoho-inventory/inventory/v1/salesorders/{salesorder_id}#### Sales Order Status Actions
# Mark as confirmed
POST /zoho-inventory/inventory/v1/salesorders/{salesorder_id}/status/confirmed
# Mark as void
POST /zoho-inventory/inventory/v1/salesorders/{salesorder_id}/status/voidInvoices
#### List Invoices
GET /zoho-inventory/inventory/v1/invoices**Example:**
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/invoices')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF#### Get Invoice
GET /zoho-inventory/inventory/v1/invoices/{invoice_id}#### Create Invoice
POST /zoho-inventory/inventory/v1/invoices
Content-Type: application/json
{
"customer_id": "1234567890000",
"line_items": [
{
"item_id": "1234567890001",
"quantity": 5,
"rate": 25.00
}
]
}**Required Fields:**
**Optional Fields:**
#### Update Invoice
PUT /zoho-inventory/inventory/v1/invoices/{invoice_id}#### Delete Invoice
DELETE /zoho-inventory/inventory/v1/invoices/{invoice_id}#### Invoice Status Actions
# Mark as sent
POST /zoho-inventory/inventory/v1/invoices/{invoice_id}/status/sent
# Mark as draft
POST /zoho-inventory/inventory/v1/invoices/{invoice_id}/status/draft
# Void invoice
POST /zoho-inventory/inventory/v1/invoices/{invoice_id}/status/void#### Invoice Email
# Email invoice to customer
POST /zoho-inventory/inventory/v1/invoices/{invoice_id}/email
# Get email content template
GET /zoho-inventory/inventory/v1/invoices/{invoice_id}/email#### Invoice Payments
# List payments applied
GET /zoho-inventory/inventory/v1/invoices/{invoice_id}/payments
# Delete a payment
DELETE /zoho-inventory/inventory/v1/invoices/{invoice_id}/payments/{invoice_payment_id}#### Invoice Credits
# List credits applied
GET /zoho-inventory/inventory/v1/invoices/{invoice_id}/creditsapplied
# Apply credits
POST /zoho-inventory/inventory/v1/invoices/{invoice_id}/credits
# Delete applied credit
DELETE /zoho-inventory/inventory/v1/invoices/{invoice_id}/creditsapplied/{creditnotes_invoice_id}#### Invoice Comments
# List comments
GET /zoho-inventory/inventory/v1/invoices/{invoice_id}/comments
# Add comment
POST /zoho-inventory/inventory/v1/invoices/{invoice_id}/comments
# Update comment
PUT /zoho-inventory/inventory/v1/invoices/{invoice_id}/comments/{comment_id}
# Delete comment
DELETE /zoho-inventory/inventory/v1/invoices/{invoice_id}/comments/{comment_id}Purchase Orders
#### List Purchase Orders
GET /zoho-inventory/inventory/v1/purchaseorders**Example:**
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/purchaseorders')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF#### Get Purchase Order
GET /zoho-inventory/inventory/v1/purchaseorders/{purchaseorder_id}#### Create Purchase Order
POST /zoho-inventory/inventory/v1/purchaseorders
Content-Type: application/json
{
"vendor_id": "1234567890000",
"line_items": [
{
"item_id": "1234567890001",
"quantity": 100,
"rate": 10.00
}
]
}**Required Fields:**
**Optional Fields:**
#### Update Purchase Order
PUT /zoho-inventory/inventory/v1/purchaseorders/{purchaseorder_id}#### Delete Purchase Order
DELETE /zoho-inventory/inventory/v1/purchaseorders/{purchaseorder_id}#### Purchase Order Status Actions
# Mark as issued
POST /zoho-inventory/inventory/v1/purchaseorders/{purchaseorder_id}/status/issued
# Mark as cancelled
POST /zoho-inventory/inventory/v1/purchaseorders/{purchaseorder_id}/status/cancelledBills
#### List Bills
GET /zoho-inventory/inventory/v1/bills**Example:**
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/zoho-inventory/inventory/v1/bills')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF#### Get Bill
GET /zoho-inventory/inventory/v1/bills/{bill_id}#### Create Bill
POST /zoho-inventory/inventory/v1/bills
Content-Type: application/json
{
"vendor_id": "1234567890000",
"bill_number": "BILL-001",
"date": "2026-02-06",
"due_date": "2026-03-06",
"line_items": [
{
"item_id": "1234567890001",
"quantity": 100,
"rate": 10.00
}
]
}**Required Fields:**
**Optional Fields:**
#### Update Bill
PUT /zoho-inventory/inventory/v1/bills/{bill_id}#### Delete Bill
DELETE /zoho-inventory/inventory/v1/bills/{bill_id}#### Bill Status Actions
# Mark as open
POST /zoho-inventory/inventory/v1/bills/{bill_id}/status/open
# Mark as void
POST /zoho-inventory/inventory/v1/bills/{bill_id}/status/voidShipment Orders
#### Create Shipment Order
POST /zoho-inventory/inventory/v1/shipmentorders
Content-Type: application/json
{
"shipment_number": "SHP-001",
"date": "2026-02-06",
"delivery_method": "FedEx",
"tracking_number": "1234567890"
}**Required Fields:**
**Optional Fields:**
#### Get Shipment Order
GET /zoho-inventory/inventory/v1/shipmentorders/{shipmentorder_id}#### Update Shipment Order
PUT /zoho-inventory/inventory/v1/shipmentorders/{shipmentorder_id}#### Delete Shipment Order
DELETE /zoho-inventory/inventory/v1/shipmentorders/{shipmentorder_id}#### Mark as Delivered
POST /zoho-inventory/inventory/v1/shipmentorders/{shipmentorder_id}/status/deliveredItem Groups
#### List Item Groups
GET /zoho-inventory/inventory/v1/itemgroups#### Get Item Group
GET /zoho-inventory/inventory/v1/itemgroups/{itemgroup_id}#### Create Item Group
POST /zoho-inventory/inventory/v1/itemgroups
Content-Type: application/json
{
"group_name": "T-Shirts",
"unit": "pcs",
"items": [
{
"name": "T-Shirt - Small",
"rate": 20.00,
"purchase_rate": 8.00,
"sku": "TS-S"
},
{
"name": "T-Shirt - Medium",
"rate": 20.00,
"purchase_rate": 8.00,
"sku": "TS-M"
}
]
}**Required Fields:**
#### Update Item Group
PUT /zoho-inventory/inventory/v1/itemgroups/{itemgroup_id}#### Delete Item Group
DELETE /zoho-inventory/inventory/v1/itemgroups/{itemgroup_id}#### Item Group Status Actions
# Mark as active
POST /zoho-inventory/inventory/v1/itemgroups/{itemgroup_id}/active
# Mark as inactive
POST /zoho-inventory/inventory/v1/itemgroups/{itemgroup_id}/inactivePagination
Zoho Inventory uses page-based pagination:
GET /zoho-inventory/inventory/v1/items?page=1&per_page=50Response includes pagination info in `page_context`:
{
"code": 0,
"message": "success",
"items": [...],
"page_context": {
"page": 1,
"per_page": 50,
"has_more_page": true,
"sort_column": "name",
"sort_order": "A"
}
}Continue fetching while `has_more_page` is `true`, incrementing `page` each time.
Code Examples
JavaScript
const response = await fetch(
'https://gateway.maton.ai/zoho-inventory/inventory/v1/items',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();Python
import os
import requests
response = requests.get(
'https://gateway.maton.ai/zoho-inventory/inventory/v1/items',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()Notes
Error Handling
| Status | Meaning |
|--------|---------|
| 400 | Missing Zoho Inventory connection or invalid request |
| 401 | Invalid or missing Maton API key, or OAuth scope mismatch |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Zoho Inventory API |
Common Error Codes
| Code | Description |
|------|-------------|
| 0 | Success |
| 1 | Invalid value |
| 2 | Mandatory field missing |
| 3 | Resource does not exist |
| 5 | Invalid URL |
Troubleshooting: API Key Issues
1. Check that the `MATON_API_KEY` environment variable is set:
echo $MATON_API_KEY2. Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOFTroubleshooting: Invalid App Name
1. Ensure your URL path starts with `zoho-inventory`. For example:
Resources
More tools from the same signal band
Order food/drinks (点餐) on an Android device paired as an OpenClaw node. Uses in-app menu and cart; add goods, view cart, submit order (demo, no real payment).
Sign plugins, rotate agent credentials without losing identity, and publicly attest to plugin behavior with verifiable claims and authenticated transfers.
The philosophical layer for AI agents. Maps behavior to Spinoza's 48 affects, calculates persistence scores, and generates geometric self-reports. Give your...