Integrations
How-to

Connect Zoho

Connect Zoho Mail to an Agent with read-only OAuth access for listing and reading inbox messages.

For
Zoho Mail administrators, Agent operators, and Organization administrators
On this page
  1. Supported Zoho services
  2. What you will configure
  3. Before you begin
  4. Check your Zoho data center
  5. Plan OAuth scopes
  6. 1. Create a Self Client
  7. 2. Generate an authorization code
  8. 3. Exchange the code for tokens
  9. 4. Find the account ID
  10. 5. Connect Zoho Mail
  11. 6. Assign the Zoho Mail Skill
  12. 7. Verify Agent access
  13. Validation behavior
  14. Runtime behavior
  15. Use a Shared Credential
  16. Rotate or remove the credential
  17. API reference
  18. Troubleshooting
  19. Security practices
  20. Next steps
  • Integrations
  • 15–20 minutes
  • Requires a Zoho Mail OAuth Self Client

Connect Zoho Mail to let an Agent list inbox messages, filter them by date, and read individual messages.

Agent Barn stores the OAuth client secret and refresh token as encrypted Agent Secrets. The Agent accesses Zoho Mail through the built-in Zoho Mail Skill and the aai-cli email command group. This integration is read-only.

Supported Zoho services

Zoho Mail

Supported — read-only access.

Supported: listing inbox messages, filtering listed messages by received date, reading an individual message by its Zoho message ID, and returning decoded subjects, addresses, dates, and bodies.

Not supported: sending or replying to email, moving, archiving, labeling, or deleting messages, marking messages read or unread, managing folders, and accessing administrative Zoho Mail settings.

Zoho Calendar

Not currently configurable — not available in the Agent Barn integration selector.

Although zoho_calendar exists as an internal provider model, it is disabled in the UI, and does not have a mounted Agent Skill or a verified Agent command surface.

Do not configure a Zoho Calendar credential through the API expecting it to work as a supported Agent integration.

What you will configure

  1. Zoho Mail account
  2. OAuth Self Client
  3. Authorization code
  4. Refresh token
  5. Encrypted Agent Secret
  6. Zoho Mail Skill
Complete setup path
Zoho Mail account


Zoho OAuth Self Client

        ├── Client ID
        ├── Client secret
        └── Read-only scopes


         Authorization code


       Access + refresh tokens

                  ├── Access token used temporarily
                  │   to find the Account ID

                  └── Refresh token saved in Agent Barn


                     Encrypted Agent Secret


                      Zoho Mail Skill + aai-cli

At the end of this guide, the Agent will have:

  • A zoho_mail credential
  • The built-in Zoho Mail Skill
  • A generated zoho-mail-rest profile
  • Read-only access to the selected Zoho Mail account
  • Automatic access-token refresh during runtime requests

Before you begin

You need:

  • An Agent Barn Organization
  • An existing Agent, or permission to hire one
  • Permission to update the Agent and manage its Secrets
  • A Zoho Mail account
  • Access to the Zoho API Console for that account
  • A terminal with curl
  • Permission to authorize read access to the intended mailbox

Use a dedicated mailbox when the Agent should not inherit a person’s complete inbox.

Official references:

Check your Zoho data center

The current Agent Barn profile does not include a Zoho data-center field. Its runtime defaults are:

Runtime defaults
OAuth server: https://accounts.zoho.com
Mail API:     https://mail.zoho.com

This is the US/global .com Zoho data center. After signing in to Zoho Mail, check the domain in the browser.

Browser domain Data center Current Agent Barn support
mail.zoho.com US/global Supported
mail.zoho.eu Europe Not currently configurable
mail.zoho.in India Not currently configurable
mail.zoho.com.au Australia Not currently configurable
mail.zoho.jp Japan Not currently configurable
mail.zohocloud.ca Canada Not currently configurable
mail.zoho.com.cn China Not currently configurable
mail.zoho.ae United Arab Emirates Not currently configurable
mail.zoho.sa Saudi Arabia Not currently configurable

Plan OAuth scopes

Request these two read-only scopes.

Scope Purpose Required
ZohoMail.accounts.READLists the user’s Zoho Mail accounts and identifies the account IDYes
ZohoMail.messages.READLists and reads messagesYes

Enter the scopes as one comma-separated value:

Scopes
ZohoMail.accounts.READ,ZohoMail.messages.READ

Do not request ALL, CREATE, UPDATE, or DELETE scopes for this integration. The current Agent Skill is read-only, so broader scopes do not add supported Agent capabilities.

Create a Self Client

  1. Sign in to the Zoho account that owns the mailbox.
  2. Open the Zoho API Console.
  3. Select Get Started or Add Client.
  4. Select Self Client.
  5. Select Create Now.
  6. Confirm creation.
  7. Open the Client Secret tab.
  8. Copy the Client ID.
  9. Copy the Client Secret into a secure temporary location.

The values resemble:

Self Client values
Client ID
1000.EXAMPLECLIENTID

Client Secret
REDACTED

A Self Client is appropriate because this is a backend automation integration for a mailbox you control. Agent Barn does not currently provide a user-facing Zoho OAuth callback flow.

Generate an authorization code

  1. Open the Self Client in the Zoho API Console.
  2. Select Generate Code.
  3. Enter the two read-only scopes.
  4. Choose a short duration, such as 10 minutes.
  5. Enter a description such as Agent Barn read-only Zoho Mail integration.
  6. Select Create.
  7. Review and approve the requested access.
  8. Copy the authorization code immediately.
Scopes
ZohoMail.accounts.READ,ZohoMail.messages.READ

Exchange the code for tokens

Use the authorization code, client ID, and client secret to request an access token and refresh token.

To avoid putting secrets directly into shell history, collect them through prompts:

Shell
read -r "ZOHO_CLIENT_ID?Zoho client ID: "
read -s "ZOHO_CLIENT_SECRET?Zoho client secret: "
echo
read -s "ZOHO_AUTH_CODE?Zoho authorization code: "
echo

Exchange the authorization code:

Shell
curl --silent --show-error \
  --request POST \
  "https://accounts.zoho.com/oauth/v2/token" \
  --data-urlencode "code=${ZOHO_AUTH_CODE}" \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "client_id=${ZOHO_CLIENT_ID}" \
  --data-urlencode "client_secret=${ZOHO_CLIENT_SECRET}" \
  --data-urlencode "redirect_uri=https://api-console.zoho.com/callback"

A successful response resembles:

Response
{
  "access_token": "REDACTED",
  "refresh_token": "REDACTED",
  "api_domain": "https://www.zohoapis.com",
  "token_type": "Bearer",
  "expires_in": 3600
}

Save these values:

Values to keep
client_id
client_secret
refresh_token

Keep the temporary access_token long enough to retrieve the mailbox’s account ID.

Find the Zoho Mail account ID

Zoho Mail API requests use a numeric account ID rather than the email address alone.

Store the temporary access token without placing it directly into the next command:

Shell
read -s "ZOHO_ACCESS_TOKEN?Temporary Zoho access token: "
echo

List the accounts available to the authorized user:

Shell
curl --silent --show-error \
  "https://mail.zoho.com/api/accounts" \
  --header "Accept: application/json" \
  --header "Authorization: Zoho-oauthtoken ${ZOHO_ACCESS_TOKEN}"

The response contains an account collection. Find the entry matching the mailbox email and copy its accountId. A shortened example looks like:

Response
{
  "status": {
    "code": 200,
    "description": "success"
  },
  "data": [
    {
      "accountId": "56218000000008002",
      "primaryEmailAddress": "[email protected]"
    }
  ]
}

Record:

Recorded values
Email: [email protected]
Account ID: 56218000000008002

Then remove the temporary access token from the shell with unset ZOHO_ACCESS_TOKEN.

The account ID is not the Zoho Organization ID, User ID, or folder ID. Use the value named accountId.

Connect Zoho Mail

  1. In Agent Barn, open Agents.
  2. Select the Agent that needs mailbox access.
  3. Open the Agent’s Configuration.
  4. Select Keys & integrations.
  5. Select Edit.
  6. Under Integration credentials, add Zoho Mail.
  7. Select Manual credential.
  8. Complete all Zoho Mail fields.
  9. Apply the configuration.
Agent Barn field Required Value
EmailYesThe authorized Zoho Mail address
Account IDYesThe numeric accountId returned by the Accounts API
Client IDYesThe OAuth Self Client ID
Client secretYesThe OAuth Self Client secret
Refresh tokenYesThe refresh token returned by the authorization-code exchange

Example:

Completed fields
Email
[email protected]

Account ID
56218000000008002

Client ID
1000.EXAMPLECLIENTID

Client secret
••••••••••••••••

Refresh token
••••••••••••••••

If the Agent is running, use the website’s restart-aware apply flow. The runtime profile becomes available after restart.

Assign the Zoho Mail Skill

The credential supplies authentication. The Skill supplies the supported command instructions.

  1. Open the Agent’s Skills configuration.
  2. Select Edit.
  3. Add the built-in Zoho Mail Skill.
  4. Apply the change.
  5. Restart the Agent if prompted.

The mounted Skill is available at:

Mounted Skill
./skills/aai-cli/zoho_mail_skill.md

The supported runtime interface is aai-cli email, and every Zoho Mail command must include --profile zoho-mail-rest.

Agent Barn requires a zoho_mail credential while the Zoho Mail Skill is assigned.

Verify Agent access

Zoho Mail does not currently have an Agent Barn live credential validator. Verify the integration by running a real read operation after the Agent starts.

List three inbox messages:

Shell
aai-cli email messages list \
  --limit 3 \
  --profile zoho-mail-rest

A successful response resembles:

Response
{
  "data": [
    {
      "folderId": "56218000000008014",
      "fromAddress": "[email protected]",
      "messageId": "1781850728498141700",
      "receivedTime": "1781850728475",
      "subject": "Example notification",
      "summary": "A short preview of the message..."
    }
  ],
  "status": {
    "code": 200,
    "description": "success"
  }
}

Use a returned messageId to read one message:

Shell
aai-cli email messages get 1781850728498141700 \
  --profile zoho-mail-rest

A successful response resembles:

Response
{
  "id": "1781850728498141700",
  "subject": "Example notification",
  "from": "Notifications <[email protected]>",
  "to": "Agent <[email protected]>",
  "date": "Fri, 19 Jun 2026 06:32:07 +0000",
  "body": "The decoded message body.",
  "body_type": "text"
}

Filter listed messages by date:

Shell
aai-cli email messages list \
  --limit 20 \
  --received-after 2026-08-01 \
  --received-before 2026-09-01 \
  --profile zoho-mail-rest

The lower date is inclusive, and the upper date is exclusive.

Date filtering is performed after fetching up to 200 messages. A response containing "truncated": true means more possible matches exist beyond the fetched page.

Validation behavior

Live validation is not currently implemented for zoho_mail.

For an Agent-owned credential, the integration validation endpoint is not a supported connectivity test. It currently returns an error equivalent to:

Validator response
{
  "detail": "No validator available for zoho_mail"
}

Shared Credential validation reports that live validation is unsupported.

This does not, by itself, mean the saved OAuth values are invalid. The authoritative verification is a successful runtime command.

HTTP
POST /api/v1/organizations/{organization_id}/agents/{agent_id}/integrations/zoho_mail/validate
Shell
aai-cli email messages list --limit 1 --profile zoho-mail-rest

Runtime behavior

When the Agent starts, Agent Barn:

  1. Decrypts the Zoho Mail credential.
  2. Stores the client secret and refresh token in the encrypted aai-cli secret store.
  3. Generates the zoho-mail-rest profile.
  4. Mounts the built-in Zoho Mail Skill.
  5. Adds the configured integration to the Agent’s tool context.

The generated profile resembles:

Generated profile
[profiles.zoho-mail-rest]
provider = "zoho"
auth_type = "zoho_oauth"
email = "[email protected]"
account_id = "56218000000008002"
client_id = "1000.EXAMPLECLIENTID"
client_secret_secret = "zoho.client_secret"
refresh_token_secret = "zoho.mail_refresh_token"

The actual secret values are not embedded in the profile. The secret references are zoho.client_secret and zoho.mail_refresh_token.

For each request, aai-cli:

  1. Reads the client ID, client secret, and refresh token.
  2. Requests a fresh short-lived access token from Zoho.
  3. Calls the Zoho Mail API using that access token.
  4. Returns successful output as JSON.
  5. Returns failures as structured JSON on standard error.
Runtime path
Encrypted refresh token


   aai-cli request


accounts.zoho.com OAuth token endpoint


Short-lived access token


mail.zoho.com API

Agent Barn does not store a temporary access token. No cron job or manual access-token refresh is required, and credential changes take effect after the Agent restarts.

Use a Shared Credential

Zoho Mail supports Organization-owned Shared Credentials. Use one when:

  • Multiple Agents should read the same mailbox
  • An Organization administrator should own OAuth rotation
  • Agent operators should not handle the client secret or refresh token
  • The same Zoho account ID applies to each attached Agent

To attach one:

  1. Create or locate the Zoho Mail Shared Credential in the Organization.
  2. Open the Agent’s Keys & integrations configuration.
  3. Add Zoho Mail.
  4. Switch from Manual credential to Shared Credential.
  5. Select the intended credential.
  6. Apply the change.
  7. Restart the Agent if prompted.
  8. Run a real aai-cli email command.

An Agent can use either a manual Zoho Mail credential or a Shared Zoho Mail Credential, not both simultaneously.

Live validation remains unsupported for the Shared Credential. Verify it from an attached Agent after restart.

Continue to Use shared credentials for the complete ownership model.

Rotate or remove the credential

Rotate the refresh token

  1. Open the existing Self Client in the Zoho API Console.
  2. Generate a new authorization code with both read-only scopes.
  3. Exchange the new code for tokens.
  4. Confirm that the response includes a new refresh token.
  5. Replace the complete Zoho Mail credential in Agent Barn.
  6. Restart the Agent.
  7. Run messages list.
  8. Revoke the old refresh token after the new credential works.

Rotate the client secret

If Zoho provides a new client secret:

  1. Record the new client ID or secret.
  2. Generate a new authorization code for that client.
  3. Exchange it for a new refresh token.
  4. Replace the Agent Barn credential as one unit.
  5. Restart and verify the Agent.
  6. Revoke the old OAuth credentials.

A refresh token is associated with the client that issued it. Do not combine a refresh token from one Self Client with another client’s ID or secret.

Remove the credential

Before removing Zoho Mail:

  1. Remove or replace any assigned Skill that requires zoho_mail.
  2. Stop the Agent, or use the website’s restart-aware apply flow.
  3. Open Keys & integrations.
  4. Mark the Zoho Mail credential for removal.
  5. Apply the change.
  6. Restart and verify the Agent.

Agent Barn blocks removal while an assigned Skill still requires the zoho_mail provider.

API reference

Add or replace a manual Zoho Mail credential

The Agent must be stopped when using the raw update endpoint.

HTTP
PATCH /api/v1/organizations/{organization_id}/agents/{agent_id}
Content-Type: application/json
Request body
{
  "secrets": [
    {
      "provider": "zoho_mail",
      "content": {
        "email": "[email protected]",
        "account_id": "56218000000008002",
        "client_id": "1000.EXAMPLECLIENTID",
        "client_secret": "REDACTED",
        "refresh_token": "REDACTED"
      }
    }
  ]
}

Attach a Shared Credential

Request body
{
  "shared_credentials": [
    {
      "shared_credential_id": "00000000-0000-0000-0000-000000000000"
    }
  ]
}

Remove the credential

Request body
{
  "removed_secret_providers": [
    "zoho_mail"
  ]
}

Credential operations require access to the Agent and the relevant update and secret-management permissions, including agent.secret.manage.

Troubleshooting

The token exchange does not return a refresh token

Wrong grant, or an expired code

Confirm that you:

  • Used a Self Client authorization code
  • Used the authorization-code grant
  • Did not use the client-credentials grant
  • Exchanged the code before it expired
  • Used the client ID and secret belonging to the same Self Client
  • Used the .com API Console and Accounts endpoint
  • Requested the code for the correct Zoho account

Generate a new authorization code and exchange it immediately.

Zoho reports an invalid code

Codes are short-lived and single-use

Generate another code in the Self Client and exchange it before its selected duration expires.

Zoho reports an invalid client

Client values or data center mismatch

Check that:

  • The client ID is complete
  • The client secret is complete
  • Both values belong to the same Self Client
  • The token request uses https://accounts.zoho.com
  • The Self Client was created in the US/global data center

The Accounts API returns a scope error

Both scopes are required

Generate a new authorization code containing both scopes:

Scopes
ZohoMail.accounts.READ,ZohoMail.messages.READ

A token containing only the message scope cannot reliably discover the account ID.

The Agent reports an authentication error

Check the stored values and restart

Check that:

  • The refresh token was entered, not the temporary access token
  • The client ID, client secret, and refresh token belong to the same Self Client
  • The refresh token has not been revoked
  • The mailbox uses the .com Zoho data center
  • The Agent was restarted after the credential changed

The Agent reports an invalid account ID

Use the accountId value

Call GET https://mail.zoho.com/api/accounts with a temporary access token, and copy the accountId matching the configured mailbox.

Do not use the Organization ID, Zoho User ID, folder ID, or message ID.

The mailbox is hosted at a regional Zoho domain

Regional endpoints are not configurable

The current Agent Barn credential does not expose regional OAuth or Mail API endpoints. The generated runtime defaults to https://accounts.zoho.com and https://mail.zoho.com.

Regional Zoho Mail accounts are not currently supported through this configuration page. Regional support requires product changes to store and generate the correct Accounts and Mail API base URLs.

Listing messages works but expected messages are missing

Inbox listing, not mailbox search

The current command lists inbox messages rather than providing a complete mailbox-wide search. Also note:

  • --limit restricts returned results
  • Date filtering fetches at most 200 messages before filtering
  • truncated: true means additional matches may exist
  • Messages in another folder may not appear

Message bodies contain simplified formatting

HTML is stripped to text

messages get returns decoded plain text when available. If only HTML is available, the command strips tags and reports "body_type": "html".

Validate reports that no validator is available

Expected for this provider

This is expected for the current zoho_mail integration. Restart the Agent and run:

Shell
aai-cli email messages list --limit 1 --profile zoho-mail-rest

The credential cannot be removed

A Skill still requires it

A remaining assigned Skill requires Zoho Mail. Remove the Zoho Mail Skill before removing the credential.

Updated credentials are not being used

Artifacts are produced at startup

Restart the Agent. Encrypted runtime Secrets, the zoho-mail-rest profile, mounted Skills, and generated tool context are created during Agent startup.

Security practices

  • Use a dedicated mailbox when possible
  • Request only ZohoMail.accounts.READ and ZohoMail.messages.READ
  • Do not request write or administrative scopes
  • Protect both the client secret and refresh token
  • Never store an access token, refresh token, authorization code, or client secret in source control
  • Do not place secrets directly in shell commands saved to history
  • Do not send OAuth values through Agent conversations
  • Prefer Shared Credentials when administrators should own rotation
  • Use separate OAuth clients for separate security boundaries
  • Restart and test after every credential rotation
  • Revoke unused refresh tokens
  • Replace the Self Client immediately if its client secret is exposed
  • Treat mailbox content as sensitive data when reviewing Agent logs and outputs

Next steps

Documentation