All posts
Guide·Jul 5, 2026·8 min read

Zoho Mail API guide: OAuth, sending, and reading mailboxes

Working with the Zoho Mail API: OAuth 2.0 setup, accountId discovery, sending messages, reading folders, and the limits to know - plus when a purpose-built email API is simpler.

Dvir Atias

Dvir Atias

Founder

The Zoho Mail API gives you programmatic access to mailboxes hosted on Zoho Mail - the mail side of the sprawling Zoho suite popular with small businesses. Like the Gmail API, it is a mailbox API: it operates on accounts that belong to human users of a mail product, with OAuth in front. This guide gets you from zero to sending and reading, and flags the friction points before you hit them.

Setup: Zoho API console and OAuth 2.0

  1. Register a client in the Zoho API console (Server-based Applications for web apps, or Self Client for scripts and internal tools).
  2. Note your region. Zoho runs separate data centers with separate endpoints - accounts.zoho.com / mail.zoho.com (US), .eu, .in, .com.au, and others. Tokens from one DC don't work against another; this is the Zoho equivalent of Mailgun's US/EU split and causes the same mysterious 401s.
  3. Request scopes shaped like ZohoMail.messages.CREATE, ZohoMail.messages.READ, ZohoMail.accounts.READ, and exchange the grant code for access + refresh tokens.

For a script, the Self Client flow is the fast path: generate a grant code in the console with your scopes, then:

curl -s -X POST https://accounts.zoho.com/oauth/v2/token \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d grant_type=authorization_code \
  -d code=GENERATED_GRANT_CODE

Access tokens live for an hour; the refresh token is long-lived. Authenticated calls pass Authorization: Zoho-oauthtoken {access_token}.

Find your accountId

Nearly every Mail API path is keyed by an accountId, so the first real call is always:

curl -s https://mail.zoho.com/api/accounts \
  -H "Authorization: Zoho-oauthtoken ACCESS_TOKEN"

The response lists each mailbox with its accountId, addresses, and aliases.

Send email

curl -s -X POST "https://mail.zoho.com/api/accounts/ACCOUNT_ID/messages" \
  -H "Authorization: Zoho-oauthtoken ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fromAddress": "you@yourdomain.com",
    "toAddress": "user@example.com",
    "subject": "Hello from the Zoho Mail API",
    "content": "<p>HTML content works here.</p>"
  }'

Nice touches: askReceipt for read receipts, and scheduled sending via isSchedule + scheduleType. Attachments are a two-step: upload to the attachments endpoint first, then reference the returned metadata in the send call.

Read folders and messages

Listing is folder-scoped, and like Gmail it's a two-step - list message metadata, then fetch content per message:

# folders
curl -s "https://mail.zoho.com/api/accounts/ACCOUNT_ID/folders" \
  -H "Authorization: Zoho-oauthtoken ACCESS_TOKEN"

# messages in a folder
curl -s "https://mail.zoho.com/api/accounts/ACCOUNT_ID/messages/view?folderId=FOLDER_ID&limit=25" \
  -H "Authorization: Zoho-oauthtoken ACCESS_TOKEN"

# one message's content
curl -s "https://mail.zoho.com/api/accounts/ACCOUNT_ID/folders/FOLDER_ID/messages/MESSAGE_ID/content" \
  -H "Authorization: Zoho-oauthtoken ACCESS_TOKEN"

There is no push webhook for new mail in the core Mail API - reacting to inbound means polling (or wiring Zoho Mail's admin-level integrations). If "email arrives → my code runs in milliseconds" is a requirement, that's a structural gap; see how email webhooks should work.

Limits worth knowing

  • OAuth token churn: hour-long access tokens mean refresh logic in every integration.
  • Per-DC endpoints: your code needs the user's region to construct URLs.
  • Rate limits: Zoho enforces per-app and per-account API limits; bulk workloads belong on their dedicated transactional product (ZeptoMail), not the Mail API.
  • Sending caps follow the mailbox's plan - this is a business-mail product, not a high-volume sender.

When to use it - and when not to

Use the Zoho Mail API when your users' mailboxes live on Zoho Mail and your product needs to act on them - a CRM logging correspondence for a Zoho-based business, internal tooling over company mailboxes, migrations.

Don't use it to give an application or AI agent an email address. You'd inherit OAuth, regional endpoints, folder plumbing, and polling for a mailbox designed around a human seat. The purpose-built alternative is one call:

curl -X POST https://api.agenticemail.dev/v1/inboxes \
  -H "Authorization: Bearer am_..." \
  -d '{"username": "agent"}'

AgenticEmail inboxes send, receive, and reply with automatic threading; inbound mail arrives as parsed JSON over signed webhooks or a WebSocket stream; and agents can drive everything through a hosted MCP server. Compare approaches in the 5 best email APIs or jump into the quickstart.

Talk to a real person