Fob
Browse the docs

Organizations and tokens

One login, many organizations#

A Zoho refresh token belongs to your Zoho user, not to one organization. If your login can see several Zoho Books organizations (say your company, a client and a test org), one Self Client and one refresh token reach all of them. fob-zb chooses the organization per request with organization_id.

So for a second organization you don't need a new Self Client or a new grant code. Copy an existing profile's credentials and point the copy at the other organization:

fob-zb organizations list                          # IDs of every org your login can see
fob-zb config profiles add client-co --from myorg --organization-id 60012xxxxx
fob-zb config profiles list

Then switch between them:

fob-zb config profiles use client-co               # change the default
fob-zb invoices list --profile myorg               # or pick one for a single command

Revoking access#

Profiles copied with --from share one refresh token, so revoking it disconnects all of them.

ActionEffect
fob-zb auth logoutRevokes the profile's refresh token at Zoho and clears it locally. Every profile that shares that token stops working
fob-zb config profiles remove nameDeletes the profile locally only. The token keeps working for the other profiles
Delete the Self Client in the API ConsoleRevokes every token issued to it, for every profile and worker using it

To stop using one organization, use config profiles remove. Use auth logout only when you mean to cut off every profile on that token.

Choosing scopes#

ZohoBooks.fullaccess.all lets fob-zb read and write everything it supports. Zoho also offers narrower scopes in the form ZohoBooks.module.OPERATION, where the operation is READ, CREATE, UPDATE, DELETE or ALL. The modules are listed in Zoho's OAuth documentation:

contacts, settings, estimates, invoices, customerpayments, creditnotes, projects, expenses, salesorders, purchaseorders, bills, debitnotes, vendorpayments, banking, accountants

Read-only scopes#

For an AI agent that should answer questions but never change your books, generate the grant code with read scopes only. Enter them comma-separated in the Scope field:

ZohoBooks.contacts.READ,ZohoBooks.settings.READ,ZohoBooks.estimates.READ,ZohoBooks.invoices.READ,ZohoBooks.customerpayments.READ,ZohoBooks.creditnotes.READ,ZohoBooks.projects.READ,ZohoBooks.expenses.READ,ZohoBooks.salesorders.READ,ZohoBooks.purchaseorders.READ,ZohoBooks.bills.READ,ZohoBooks.debitnotes.READ,ZohoBooks.vendorpayments.READ,ZohoBooks.banking.READ,ZohoBooks.accountants.READ

Write commands then fail with an authorization error from Zoho. Put this in its own profile, such as myorg-readonly, and keep it separate from a full-access profile.

Where credentials are stored#

Used byLocationContains
CLI~/.fob/fob-zb/config.yml, file mode 0600. Override the folder with FOB_ZB_CONFIG_DIRClient ID, client secret, refresh token, cached access token, organization ID and name, region
Workers and CIFOB_ZB_CLIENT_ID, FOB_ZB_CLIENT_SECRET, FOB_ZB_REFRESH_TOKEN, FOB_ZB_ORGANIZATION_ID, optional FOB_ZB_REGIONThe same, without the cache

When more than one source is available, fob-zb uses the first match: --profile flag, then a complete set of FOB_ZB_* variables, then the current profile. Treat the client secret and refresh token like passwords.