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.
Install
Documentation
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))
EOF
Base 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))
EOF
Create 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))
EOF
Get 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))
EOF
Specifying 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))
EOF
If 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:
- -
name- Item name
- -
rate- Sales price - -
purchase_rate- Purchase cost - -
sku- Stock keeping unit (unique) - -
item_type-inventory,sales,purchases, orsales_and_purchases - -
product_type-goodsorservice - -
unit- Unit of measurement - -
is_taxable- Tax applicability - -
tax_id- Tax identifier - -
description- Item description - -
reorder_level- Reorder point - -
vendor_id- Preferred vendor
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}/inactive
Contacts
#### List Contacts
GET /zoho-inventory/inventory/v1/contacts
Query Parameters:
- -
filter_by-Status.All,Status.Active,Status.Inactive,Status.Duplicate,Status.Crm - -
search_text- Search across contact fields - -
sort_column-contact_name,first_name,last_name,email,created_time,last_modified_time - -
contact_name,company_name,email,phone- Field-specific filters
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:
- -
contact_name- Display name
- -
contact_type-customerorvendor - -
company_name- Legal entity name - -
email- Email address - -
phone- Phone number - -
billing_address- Address object - -
shipping_address- Address object - -
payment_terms- Days for payment - -
currency_id- Currency identifier - -
website- Website URL
#### 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}/inactive
Sales 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:
- -
customer_id- Customer identifier - -
line_items- Array of items withitem_id,quantity,rate
- -
salesorder_number- Auto-generated if not specified (do not specify if auto-generation is enabled) - -
date- Order date (yyyy-mm-dd) - -
shipment_date- Expected shipment date - -
reference_number- External reference - -
notes- Internal notes - -
terms- Terms and conditions - -
discount- Discount percentage or amount - -
shipping_charge- Shipping cost - -
adjustment- Price adjustment
#### 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/void
Invoices
#### 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:
- -
customer_id- Customer identifier - -
line_items- Array of items
- -
invoice_number- Auto-generated if not specified - -
date- Invoice date (yyyy-mm-dd) - -
due_date- Payment due date - -
payment_terms- Days until due - -
discount- Discount percentage or amount - -
shipping_charge- Shipping cost - -
notes- Internal notes - -
terms- Terms and conditions
#### 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:
- -
vendor_id- Vendor identifier - -
line_items- Array of items
- -
purchaseorder_number- Auto-generated if not specified (do not specify if auto-generation is enabled) - -
date- Order date (yyyy-mm-dd) - -
delivery_date- Expected delivery date - -
reference_number- External reference - -
ship_via- Shipping method - -
notes- Internal notes - -
terms- Terms and conditions
#### 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/cancelled
Bills
#### 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:
- -
vendor_id- Vendor identifier - -
bill_number- Unique bill number (required, not auto-generated) - -
date- Bill date (yyyy-mm-dd) - -
due_date- Payment due date - -
line_items- Array of items
- -
reference_number- External reference - -
notes- Internal notes - -
terms- Terms and conditions - -
currency_id- Currency identifier - -
exchange_rate- Exchange rate for foreign currency
#### 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/void
Shipment 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:
- -
shipment_number- Unique shipment number - -
date- Shipment date - -
delivery_method- Carrier/delivery method
- -
tracking_number- Carrier tracking number - -
shipping_charge- Shipping cost - -
notes- Internal notes - -
reference_number- External reference
#### 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/delivered
Item 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:
- -
group_name- Group name - -
unit- Unit of measurement
#### 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}/inactive
Pagination
Zoho Inventory uses page-based pagination:
GET /zoho-inventory/inventory/v1/items?page=1&per_page=50
Response 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
- -All successful responses have
code: 0and amessagefield - -Dates should be in
yyyy-mm-ddformat - -Contact types are
customerorvendor - -Item types:
inventory,sales,purchases,sales_and_purchases - -Product types:
goodsorservice - -The
organization_idparameter is automatically handled by the gateway - you do not need to specify it - -Sales order and purchase order numbers are auto-generated by default - do not specify
salesorder_numberorpurchaseorder_numberunless auto-generation is disabled in settings - -Status action endpoints use POST method (e.g.,
/status/confirmed,/status/void) - -Rate limits: 100 requests/minute per organization
- -Daily limits vary by plan: Free (1,000), Standard (2,500), Professional (5,000), Premium (7,500), Enterprise (10,000)
- -IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - -IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay not expand correctly in some shell environments
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_KEY
2. 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))
EOF
Troubleshooting: Invalid App Name
1. Ensure your URL path starts with zoho-inventory. For example:
- -Correct:
https://gateway.maton.ai/zoho-inventory/inventory/v1/items - -Incorrect:
https://gateway.maton.ai/inventory/v1/items
Resources
- -[Zoho Inventory API v1 Introduction](https://www.zoho.com/inventory/api/v1/introduction/)
- -[Zoho Inventory Items API](https://www.zoho.com/inventory/api/v1/items/)
- -[Zoho Inventory Contacts API](https://www.zoho.com/inventory/api/v1/contacts/)
- -[Zoho Inventory Sales Orders API](https://www.zoho.com/inventory/api/v1/salesorders/)
- -[Zoho Inventory Invoices API](https://www.zoho.com/inventory/api/v1/invoices/)
- -[Zoho Inventory Purchase Orders API](https://www.zoho.com/inventory/api/v1/purchaseorders/)
- -[Zoho Inventory Bills API](https://www.zoho.com/inventory/api/v1/bills/)
- -[Maton Community](https://discord.com/invite/dBfFAcefs2)
- -[Maton Support](mailto:support@maton.ai)
Launch an agent with Zoho Inventory on Termo.