Agent-friendly CLI over the Zoho Inventory API. Generated by clify.
Covers 29 resources / 316 endpoints — items, contacts, sales orders, packages, shipments, invoices, retainer invoices, customer payments, sales returns, credit notes, purchase orders, purchase receives, bills, vendor credits, locations, taxes, currencies, reporting tags, and the rest of the Zoho Inventory module surface.
Auto-refreshes OAuth on every run; injects organization_id automatically; honors all eight Zoho data-centers.
git clone <repo-url>
cd zoho-inventory-cli
npm install
npm link
zoho-inventory-cli --versionzoho-inventory-cli/
├── bin/zoho-inventory-cli.mjs thin dispatcher
├── lib/
│ ├── api.mjs apiRequest + page pagination + Zoho DC routing
│ ├── auth.mjs OAuth refresh-token flow + Zoho-oauthtoken header
│ ├── config.mjs ~/.config/zoho-inventory-cli/credentials.json
│ ├── env.mjs .env loader (zero-dep)
│ ├── args.mjs splitGlobal, parseArgs adapters
│ ├── help.mjs --help generators
│ ├── output.mjs output, errorOut
│ └── payload.mjs shared body-builder
├── commands/ one .mjs per Zoho resource (29 + login)
├── skills/ zoho-inventory-cli umbrella skill
├── knowledge/ business rules and quirks (read these first)
├── test/ smoke + integration + auth, mock-server-driven
├── scripts/ gen-resources.mjs, gen-clify-meta.mjs (regen helpers)
├── .clify.json clify metadata (regenerable)
├── coverage.json every endpoint, with action mapping
├── .env.example required & optional env vars
└── .github/workflows/test.yml Node 20 + 22 CI
- Mint Zoho OAuth credentials. Open the API Console for your DC (e.g.
https://api-console.zoho.in/), create a Self Client, and generate a refresh token with scopeZohoInventory.fullaccess.all. Full walkthrough inskills/zoho-inventory-cli-auth/SKILL.md. - Set env vars (or copy
.env.exampleto.env):ZOHO_INVENTORY_REFRESH_TOKEN=1000.xxxx ZOHO_INVENTORY_CLIENT_ID=1000.yyyy ZOHO_INVENTORY_CLIENT_SECRET=zzzz ZOHO_INVENTORY_ORG_ID=60030298567 ZOHO_INVENTORY_DC=in - Verify:
zoho-inventory-cli login --status --json.
# List + paginate
zoho-inventory-cli items list --all --json | jq '.[].name'
# Get a single contact
zoho-inventory-cli contacts get --id 460000123456 --json
# Run the SO cycle
zoho-inventory-cli sales-orders create --customer_id 460000... --body '{"line_items":[{"item_id":"...","quantity":1}]}'
zoho-inventory-cli packages create --salesorder_id 460000... --body '{"line_items":[...]}'
zoho-inventory-cli shipment-orders create --salesorder_id 460000... --body '{"package_ids":["..."],"delivery_method":"DTDC"}'
zoho-inventory-cli invoices create --customer_id 460000... --body '{"line_items":[...]}'
# Attach a courier waybill PDF
zoho-inventory-cli invoices add-attachment --id 460000... --file ./waybill.pdf
# Bulk operations
zoho-inventory-cli sales-orders bulk-confirm --salesorder_ids "id1,id2,id3"
# Override organization per-call
zoho-inventory-cli contacts list --organization-id 60020000000
# Dry-run any command
zoho-inventory-cli invoices create --dry-run --customer_id 1 --body '{"line_items":[]}'Full per-action flag reference: zoho-inventory-cli <resource> <action> --help.
- Resource × action. Path templates use
:idfor the primary id and named placeholders for nested ids (--commentId,--documentId,--refundId,--templateId,--paymentId,--billId,--invoiceId,--contactId,--taxGroupId,--taxAuthorityId,--taxExemptionId,--optionId,--receiveId). - Pagination.
--page/--per_pageper call, or--allto walk every page (untilpage_context.has_more_pageis false). - Body. Top-level scalar flags for ergonomic create/update;
--body '<json>'as a raw escape hatch for nested shapes. - Multipart upload. Six actions take
--file <path>(item-groups create, invoices add-attachment, retainer-invoices email, retainer-invoices add-attachment, tasks add-attachment, delivery-challans add-attachment). - Errors. JSON to stderr, exit code 1. Codes:
auth_missing,auth_invalid,forbidden,not_found,validation_error,rate_limited(withretryAfter),server_error,network_error,timeout,conflict. The CLI does not retry — wrap in your agent loop.
See skills/zoho-inventory-cli-resources/SKILL.md for the full action quick-reference.
Read everything under knowledge/ before non-trivial workflows. The Zoho API has surprises:
header-format.md— wire prefix isZoho-oauthtoken, notBearer.oauth-refresh.md— access tokens expire hourly; CLI auto-refreshes from the trio.organization-id.md— required on every request; auto-injected from env.pagination.md— page-based, not cursor.india-gst-and-locations.md— Indian GST treatment, place_of_supply, Ahimamau warehouse rule.composite-items-vs-bundles.md— three concepts that look alike, model differently.sales-order-cycle.md— the SO → package → shipment → invoice → payment chain.url-quirks.md— singular/item/customfields,/settings/...prefix, status path inconsistencies.
npm test
Runs smoke, integration, and auth suites against an in-repo mock server. No network needed. CI runs the same on Node 20 and 22.
The resource registry is hand-maintained but regenerable from a small declarative table:
node scripts/gen-resources.mjs # rewrites commands/*.mjs from RESOURCES table
node scripts/gen-clify-meta.mjs # rewrites coverage.json + .clify.json from the live registry
If the Zoho API gains a new endpoint, edit scripts/gen-resources.mjs's RESOURCES table, re-run both, and validate.