Back to list
Qmop1967

zoho-api

by Qmop1967

0🍴 0📅 Jan 24, 2026

SKILL.md


name: zoho-api description: | Zoho Books and Zoho Inventory API integration for TSH Clients Console. Use when: (1) Creating new API routes that call Zoho endpoints (2) Debugging API errors, token issues, or rate limits (3) Adding new Zoho data fetching functions (4) Understanding OAuth token caching with Upstash Redis (5) Working with products, orders, invoices, payments, or credit notes (6) Troubleshooting "Contact for price" or stock display issues

Zoho API Integration

Quick Reference

APIBase URL
Zoho Inventoryhttps://www.zohoapis.com/inventory/v1
Zoho Bookshttps://www.zohoapis.com/books/v3

Organization ID: 748369814

Code Files

FilePurpose
src/lib/zoho/client.tsOAuth client, token caching, zohoFetch
src/lib/zoho/products.tsProducts, stock extraction
src/lib/zoho/price-lists.tsPrice list constants and fetching
src/lib/zoho/customers.tsCustomer lookup by email
src/lib/zoho/orders.tsSales orders
src/lib/zoho/invoices.tsInvoices
src/lib/zoho/payments.tsPayments
src/lib/zoho/credit-notes.tsCredit notes

Using zohoFetch

import { zohoFetch } from '@/lib/zoho/client';

// GET request
const data = await zohoFetch('/inventory/v1/items', {
  params: {
    organization_id: process.env.ZOHO_ORGANIZATION_ID,
    page: 1,
    per_page: 100,
  },
});

// Single item with locations
const item = await zohoFetch(`/inventory/v1/items/${itemId}`, {
  params: { organization_id: process.env.ZOHO_ORGANIZATION_ID },
});

Token Caching (CRITICAL)

Memory Cache → Upstash Redis → Zoho OAuth Refresh
              (50-min TTL)    (rate limit: 10s guard)

If all prices show "Contact for price", check:

  1. Upstash env vars in Vercel
  2. UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN
  3. Run: curl https://www.tsh.sale/api/debug/token

Common Endpoints

Inventory API

GET /items                      # List products
GET /items/{id}                 # Single product (includes locations)
GET /categories                 # List categories
GET /pricebooks/{id}            # Pricebook with items

Books API

GET /contacts                   # List customers
GET /salesorders                # Sales orders
GET /invoices                   # Invoices
GET /customerpayments           # Payments
GET /creditnotes                # Credit notes

Caching with unstable_cache

import { unstable_cache } from 'next/cache';

const getCachedProducts = unstable_cache(
  async () => await fetchProducts(),
  ['products'],
  { revalidate: 3600, tags: ['products'] }
);

Revalidate cache:

curl "https://www.tsh.sale/api/revalidate?tag=products&secret=tsh-revalidate-2024"

Error Handling Pattern

try {
  const data = await zohoFetch('/inventory/v1/items', { ... });
} catch (error) {
  if (error.message.includes('401')) {
    // Token expired - auto-refreshes
  } else if (error.message.includes('429')) {
    // Rate limited - wait and retry
  }
}

Creating New API Route

// src/app/api/zoho/[resource]/route.ts
import { NextResponse } from 'next/server';
import { zohoFetch } from '@/lib/zoho/client';

export async function GET(request: Request) {
  const data = await zohoFetch('/inventory/v1/items', {
    params: {
      organization_id: process.env.ZOHO_ORGANIZATION_ID,
    },
  });

  return NextResponse.json(data);
}

Rate Limits

APILimit
OAuth Refresh~100/minute
Inventory API100/minute
Books API100/minute

Debug Commands

# Check token
curl "https://www.tsh.sale/api/debug/token"

# Check prices
curl "https://www.tsh.sale/api/debug/prices"

# Check stock
curl "https://www.tsh.sale/api/debug/stock"

# Revalidate cache
curl "https://www.tsh.sale/api/revalidate?tag=all&secret=tsh-revalidate-2024"

Score

Total Score

50/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon