Skip to Content
IntegrationsZoho Payments

Zoho Payments

Connect your Zoho Payments account so the chat composer’s icon can issue real payment links and ship them to your customers as a beautiful interactive WhatsApp message — Pay Now button on top, your hosted Zoho checkout below.

API reference: zoho.com/in/payments/api/v1/payment-links 

What you get

Event triggered by ZohoSplashify behaviour
Payment link paidStatus flips to paid in real-time, contact’s chat shows ✅, push notification
Payment link expired / cancelStatus updates everywhere, optional re-send via the Resend button

If you also use Zoho Billing for invoices, Splashify already wires that — this integration is only for the payment-link / payment-collection flow.

Prerequisites

  • Active Zoho Payments merchant account (zoho.com/in/payments )
  • Completed merchant onboarding (KYC + bank verification) — payment links don’t issue against an unverified account
  • Splashify WABA connected (Dashboard shows WABA connected)

Setup

1. Get your Zoho Payments Account ID

Zoho Payments dashboard → Settings → API & Webhooks. Copy the Account ID (also called X-com-zoho-payments-accountsid). It looks like a 14-digit number.

2. Create a Zoho Self-Client and get the OAuth triple

Zoho Payments uses Zoho’s standard OAuth 2.0. Access tokens expire after 60 minutes — Splashify needs a long-lived refresh token so it can mint fresh access tokens automatically. The Self-Client flow gives you all three credentials. Funds collected via these links go to YOUR bank, not ours — these credentials must be from your own Zoho account.

  1. Sign in to api-console.zoho.com  with the same Zoho account that owns your Zoho Payments merchant.
  2. Click Add Client → choose Self Client.
  3. After creation, copy the Client ID and Client Secret from the Self Client dashboard. These are long-lived — no expiry.
  4. Open the Generate Code tab. In the Scope field paste:
    ZohoPay.payments.CREATE,ZohoPay.payments.READ,ZohoPay.payments.UPDATE
    Time Duration = 10 minutes. Scope Description = anything (e.g. “Splashify Pro payment links”). Click Create.
  5. A grant code appears (looks like 1000.xxxxxxxxxxxxxxxx.yyyyyyyyyyyy). Copy it within 10 minutes — it expires.
  6. Exchange the grant code for a refresh token via curl:
    curl -X POST 'https://accounts.zoho.in/oauth/v2/token' \ -d 'grant_type=authorization_code' \ -d 'client_id=<your-client-id>' \ -d 'client_secret=<your-client-secret>' \ -d 'redirect_uri=https://app.splashifypro.com/integrations/zoho/callback' \ -d 'code=<the-grant-code-from-step-5>'
    The response is JSON containing access_token (1hr lifetime — discard) and refresh_token (long-lived — save this).

Splashify stores your refresh_token encrypted in our database. We use it on every API call to mint a fresh access_token automatically — you don’t have to repeat this exchange. Refreshed tokens are persisted back so the rotation is invisible to you.

3. Create a webhook secret

Zoho Payments dashboard → Settings → Webhooks → + Add Webhook.

FieldValue
URLhttps://apis.splashifypro.com/api/v1/webhooks/payments/zoho
Eventspayment_link.paid, payment_link.expired, payment_link.cancelled
Auth methodHMAC (recommended) or Token
SecretGenerate a 32+ character random string. Save this.

Click Save.

4. Connect in Splashify

Open Integrations → Zoho Payments .

FieldWhat to paste
Account IDFrom step 1
OAuth Client IDFrom step 2 (your Self-Client dashboard)
OAuth Client SecretFrom step 2 (your Self-Client dashboard)
OAuth Refresh TokenFrom step 2 (the curl exchange response)
Webhook Verification TokenThe secret from step 3

Hit Save Changes. From this point on Splashify rotates the access token automatically using your refresh token. Funds collected via every link go straight into your Zoho merchant account / linked bank — Splashify never holds the money.

Three ways:

A. From the chat composer

In Messages, open any conversation. Tap the green icon next to the emoji button. Fill in:

  • Amount (₹) — what you want to collect
  • Reason / Description — shown to the customer on the Zoho checkout page
  • Product (optional) — line-item name on the Zoho receipt
  • Gateway — if you have multiple connected, pick Zoho Payments

Hit Send payment link. The platform creates the link via Zoho’s POST /paymentlinks endpoint and ships an interactive WhatsApp message to the customer with a Pay Now button.

B. From the Public API

curl -X POST 'https://apis.splashifypro.com/api/v1/app/payments/links' \ -H 'Authorization: Bearer YOUR_APP_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "contact_phone": "919876543210", "contact_name": "Aditya", "amount": 500.00, "description": "Order #1234", "gateway": "zoho", "expires_in_hours": 168 }'

Returns the link_id, gateway_link_id (Zoho’s paymentlink_id), and the public short_url.

C. As a default

Set Zoho Payments as your default gateway:

curl -X POST 'https://apis.splashifypro.com/api/v1/app/payments/default-gateway' \ -H 'Authorization: Bearer YOUR_APP_TOKEN' \ -H 'Content-Type: application/json' \ -d '{"gateway": "zoho"}'

After this every link created without an explicit gateway field uses Zoho.

How the webhook works

Zoho POSTs to /api/v1/webhooks/payments/zoho with a signed payload. Splashify:

  1. Reads the raw body before parsing.
  2. Verifies X-Zoho-Webhook-Signature (HMAC-SHA256 over the body) against your stored secret. Falls back to X-Zoho-Webhook-Token equality if you set up token-mode auth.
  3. Looks up the link by payment_link.paymentlink_id → resolves your user_id.
  4. Idempotency-checks via the event_id → skips if already processed (Zoho retries on 5xx).
  5. Updates the link status, denormalises into the listing tables, pushes a real-time payment.received event to your WebSocket so the chat UI flips to ✅ without a refresh.

Always 200s back to Zoho on signature pass — internal failures get logged but don’t trigger Zoho’s retry storm.

Variables surfaced from Zoho payloads

When you build templates / chatbot flows on top of Zoho events:

VariableSource
customer.phone_numberCustomer phone (E.164)
customer.nameCustomer name
amountCollected amount (rupees)
paymentlink_idZoho’s paymentlink ID
payment_idZoho’s transaction ID (when status = paid)
statuspaid / expired / cancelled / refunded

Pricing

Zoho Payments charges per transaction (typically 2% UPI / 2.5-3% cards — check your contract). Splashify Pro doesn’t add a markup on payment-collection — you keep 100% of what Zoho passes through after their cut.

WhatsApp message charges still apply to the interactive message we ship to your customer — see Pricing .

Troubleshooting

SymptomLikely cause
Gateway not configured on link creationOne of Account ID / Client ID / Client Secret / Refresh Token is empty on the integration form
zoho 401: Not An Authorized UserRefresh token rejected by Zoho — re-run step 2 (the grant code may have expired before the curl exchange, or you used a different client_id when minting it)
zoho oauth: invalid_clientClient ID + Client Secret don’t match the Self-Client that issued the refresh token. Re-paste them from the same Self-Client dashboard.
Webhook returns 400 invalid signatureStored webhook secret doesn’t match what Zoho is signing with — regenerate
Customer gets a plain text message, not the CTAConversation is past the 24h customer-service window — restart by sending a template
Payment captured but Splashify still shows pendingWebhook not configured / wrong URL — check Zoho dashboard logs

For anything else email support@splashifypro.in.