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 Zoho | Splashify behaviour |
|---|---|
| Payment link paid | Status flips to paid in real-time, contact’s chat shows ✅, push notification |
| Payment link expired / cancel | Status 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.
- Sign in to api-console.zoho.com with the same Zoho account that owns your Zoho Payments merchant.
- Click Add Client → choose Self Client.
- After creation, copy the Client ID and Client Secret from the Self Client dashboard. These are long-lived — no expiry.
- Open the Generate Code tab. In the Scope field paste:
Time Duration = 10 minutes. Scope Description = anything (e.g. “Splashify Pro payment links”). Click Create.
ZohoPay.payments.CREATE,ZohoPay.payments.READ,ZohoPay.payments.UPDATE - A grant code appears (looks like
1000.xxxxxxxxxxxxxxxx.yyyyyyyyyyyy). Copy it within 10 minutes — it expires. - Exchange the grant code for a refresh token via curl:
The response is JSON containing
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>'access_token(1hr lifetime — discard) andrefresh_token(long-lived — save this).
Splashify stores your
refresh_tokenencrypted in our database. We use it on every API call to mint a freshaccess_tokenautomatically — 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.
| Field | Value |
|---|---|
| URL | https://apis.splashifypro.com/api/v1/webhooks/payments/zoho |
| Events | payment_link.paid, payment_link.expired, payment_link.cancelled |
| Auth method | HMAC (recommended) or Token |
| Secret | Generate a 32+ character random string. Save this. |
Click Save.
4. Connect in Splashify
Open Integrations → Zoho Payments .
| Field | What to paste |
|---|---|
| Account ID | From step 1 |
| OAuth Client ID | From step 2 (your Self-Client dashboard) |
| OAuth Client Secret | From step 2 (your Self-Client dashboard) |
| OAuth Refresh Token | From step 2 (the curl exchange response) |
| Webhook Verification Token | The 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.
Sending a payment link
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:
- Reads the raw body before parsing.
- Verifies
X-Zoho-Webhook-Signature(HMAC-SHA256 over the body) against your stored secret. Falls back toX-Zoho-Webhook-Tokenequality if you set up token-mode auth. - Looks up the link by
payment_link.paymentlink_id→ resolves youruser_id. - Idempotency-checks via the
event_id→ skips if already processed (Zoho retries on 5xx). - Updates the link status, denormalises into the listing tables, pushes a real-time
payment.receivedevent 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:
| Variable | Source |
|---|---|
customer.phone_number | Customer phone (E.164) |
customer.name | Customer name |
amount | Collected amount (rupees) |
paymentlink_id | Zoho’s paymentlink ID |
payment_id | Zoho’s transaction ID (when status = paid) |
status | paid / 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
| Symptom | Likely cause |
|---|---|
Gateway not configured on link creation | One of Account ID / Client ID / Client Secret / Refresh Token is empty on the integration form |
zoho 401: Not An Authorized User | Refresh 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_client | Client 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 signature | Stored webhook secret doesn’t match what Zoho is signing with — regenerate |
| Customer gets a plain text message, not the CTA | Conversation is past the 24h customer-service window — restart by sending a template |
| Payment captured but Splashify still shows pending | Webhook not configured / wrong URL — check Zoho dashboard logs |
For anything else email support@splashifypro.in.