Kaizen #84 - PHP SDK [Part I]

Kaizen #84 - PHP SDK [Part I]

Hello and welcome to another Kaizen week!

In this week's post, we'll show you how to get started with Zoho CRM's PHP SDK, and walk you through the configuration and initialization process.

PHP Software Development Kit

PHP SDK allows you to create client PHP applications that can be integrated with Zoho CRM effortlessly. It serves as a wrapper for the REST APIs, thus making it easier to use the services of Zoho CRM.

Why PHP SDK?

Easy authentication: You don't have to worry about manually managing authentication because the PHP SDK takes care of generating access/refresh tokens for you.
Easy and Efficient data exchange: With the PHP SDK, you can easily exchange data between Zoho CRM and your client PHP application, where the CRM entities are modelled as classes. You can declare and define CRM API equivalents as simple functions in your PHP application.

Prerequisites 

  • The client app must have PHP 7 or above with a cURL extension. cURL extension is used to connect and communicate with the Zoho CRM APIs.
  • The client app must have the PHP SDK installed through Composer

How to start using the PHP SDK?

  1. Prerequisite : Register your application with Zoho CRM.
  2. Install the PHP SDK.
  3. Knowledge Base : Token Persistence
  4. Configuration 
  5. initialization.

1. Register your application with Zoho CRM

Registering your application with Zoho CRM is a mandatory step in order to authenticate and authorize API calls using the OAuth2.0 standards.
  1. Go to https://api-console.zoho.com
  2. Click on Get Started or +ADD CLIENT.
  3. Choose the Client Type.
  4. Fill in the necessary details and click CREATE. Once you successfully register your self-client, you will receive a Client ID and Client Secret.

2. Install PHP SDK 

1. Install Composer, if not already installed. Please check the corresponding link for installation instructions.

2. Install PHP-SDK using Composer
  • Navigate to the workspace of your client app.
  • Run the following command in the workspace. Upon successful installation, the system will create a package named vendor in the workspace of your client app.   Note : This command installs SDK for API v2.1.

    composer require zohocrm/php-sdk-2.1

3. To use the SDK in your project, add the following line in your project PHP files. This loads and includes our PHP-SDK library in your project. If you skip this step, you will get a fatal error in response due to the missing libraries.

require 'vendor/autoload.php';

3. Token Persistence

Token persistence refers to storing and utilizing authentication tokens provided by Zoho, enabling the SDK to refresh the access tokens without the need for user intervention. The SDK offers three types of persistence - File, DB, and Custom - with file persistence being the default method. 
The persistence is achieved by writing an implementation of the inbuilt TokenStore interface, which has the following callback methods. 

Method
Description
getToken($user, $token)
Invoked before firing a request to fetch the saved tokens. This method returns an implementation of Token interface object for the library to process it.
saveToken($user, $token)
Invoked after fetching access and refresh tokens from Zoho. This method saves the token details.
deleteToken($token)
This method is used to delete the given token details.
getTokens()
This method is used to retrieve all the stored tokens.
deleteTokens() 
The method to delete all the stored tokens.
getTokenById($id, $token) 
This method is used to retrieve the user token details based on the unique ID.

a. Token Persistence using a Database

Database persistence is a technique that involves storing and retrieving data from a database. If you prefer using database persistence, you can use MySQL. 
Create a table in your database with the required columns. For example, if you want to persist your tokens in a table named token in database named zoho, use the following:
CREATE DATABASE zoho; // use this to create database named zoho
// use this to create a table named token, with the necessary columns
CREATE TABLE token ( 
  id varchar(255) NOT NULL,
  user_mail varchar(255) NOT NULL,
  client_id varchar(255),
  client_secret varchar(255),
  refresh_token varchar(255),
  access_token varchar(255),
  grant_token varchar(255),
  expiry_time varchar(20),
  redirect_url varchar(255),
  primary key (id)
);

In this example, your tokens will be persisted in the token table in your zoho database.

b. File Persistence

File Persistence allows storing and retrieving the authentication tokens from the given file path. The file contains id, user_mail, client_id, client_secret, refresh_token, access_token, grant_token, expiry_time and redirect_url. 

c. Custom Persistence

Custom Persistence refers to a technique where users can create their own method of storing and retrieving authentication tokens. To use this method, users need to implement the TokenStore interface and override its methods according to their own logic.

4. Configuration

Configuration is a critical step in which you set up SDK's configuration details like user authentication, token persistence, logging and API call timeout settings, and more. Listed below are the keys that you define in this step.

Key
Description
user
mandatory
Represents the mail id, which is used to identify and fetch tokens from the File or DB.
environment
mandatory
Represents the data centre details in Domain::Environment pattern.
Domains : USDataCenter, EUDataCenter, INDataCenter, CNDataCenter, AUDataCenter
Environments : PRODUCTION(), DEVELOPER(), SANDBOX()
token
mandatory
Contains user token details. Depending on the tokens, you can choose grantToken flow, refreshToken flow or accessToken flow.
logger
optional
Contains the configuration for logging exceptions and API call information. By default, the logs will be available in the workspace as sdk_logs.log.
store
optional
Contains details for the Token Persistence object. You can choose between DB Store, File Store or Custom Store, and configure accordingly.
SDKConfig
optional
Contains additional configuration details like timeout, autorefresh fields, picklistvalidation, etc
requestProxy
optional
Contains the details of the proxy, if you are using a proxy server to authenticate and make the API calls.
resourcePath
optional
The path containing the absolute directory path to store user specific files containing the module fields information.


Let us discuss how to configure each of them, in detail.
a. user : The user key will be used to store and identify the tokenstore details in the DB or File Storage for token persistence. Create an instance of UserSignature that identifies the current user with the following :
  1. $user = new UserSignature("patricia@zoho.com");
b. environment : The API environment which decides the domain and the URL to make API calls. 
  1. $environment = USDataCenter::PRODUCTION();
c. token : Create an instance of OAuthToken with the information that you get after registering your Zoho client. Depending on the tokens available with you, you can choose one of the following flows. 
Note : You need to generate the tokens (grant/access/refresh) beforehand. 
  • grantToken flow - You should use the grant Token for configuration.
    $token = (new OAuthBuilder())
      ->clientId("clientId")
      ->clientSecret("clientSecret")
      ->grantToken("grantToken")
      ->redirectURL("redirectURL")
      ->build();

  • refreshToken flow -In this flow, use the refresh token.
    $token = (new OAuthBuilder())
      ->clientId("clientId")
      ->clientSecret("clientSecret")
      ->refreshToken("refreshToken")
      ->redirectURL("redirectURL")
      ->build();

  • accessToken flow - You can use the access token to configure in this flow. Please note that the token will not be persisted in this case, and the access token will be directly used to make the API calls.

    $token = (new OAuthBuilder()
      ->accessToken("accessToken")
      ->build(); 

d. logger : Create an instance of Logger Class to log exception and API information. You can set the level you want to log (FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, ALL, OFF), and also configure the file path and file name for the log file.

$logger = (new LogBuilder())
->level(Levels::INFO)
->filePath("/Documents/php_sdk_log.log")
->build();

e. store : Configure your token persistence using this method. If this is skipped, the SDK creates the sdk_tokens.txt in the current working directory to persist the tokens by default.
  • DB Store - Configure the Database details, where you want to store your tokens.
    $tokenstore = (new DBBuilder())
    ->host("hostName")
    ->databaseName("dataBaseName")
    ->userName("userName")
    ->password("password")
    ->portNumber("portNumber")
    ->tableName("tableName")
    ->build();

  • File store - Give the absolute file path, where you want to store the tokens. 
    $tokenstore = new FileStore("absolute_file_path");

  • Custom Store - In this method, you can implement your own method for storing and retrieving the tokens. Please note that to do so, you must implement the TokenStore interface, and override its callback methods (getToken, saveToken, deleteToken, getTokens, deleteTokens, getTokenById). 
    $tokenstore = new CustomStore();

Note :  The corresponding storage will  have id, user_mail, client_id, client_secret, refresh_token, access_token, grant_token, expiry_time and redirect_url. The id is a unique system generated key.

f. SDKConfig : The additional SDK configurations are taken care of with this method. 

Configuration Key
Description
autoRefreshFields
Default Value : False
A boolean configuration key to enable or disable automatic refreshing of module fields in the background. If set to true, fields are refreshed every hour, and if set to false, fields must be manually refreshed or deleted.
pickListValidation
Default Value : True
This field enables or disables pick list validation. If enabled, user input for pick list fields is validated, and if the value does not exist in the pick list, the SDK throws an error. If disabled, the input is not validated and the API call is made.
enableSSLVerification
Default Value : True
A boolean field to enable or disable curl certificate verification. If set to true, the SDK verifies the authenticity of certificate. If set to false, the SDK skips the verification.
connectionTimeout
Default Value : 0
The maximum time (in seconds) to wait while trying to connect. Use 0 to wait indefinitely.
timeout
Default Value : 0
The maximum time (in seconds) to allow cURL functions to execute. Use 0 to wait indefinitely.
  1. $autoRefreshFields = false;
  2. $pickListValidation = false;
  3. $enableSSLVerification = true;
  4. $connectionTimeout = 2;
  5. $timeout = 2;
  6. $sdkConfig = (new SDKConfigBuilder())
  7. ->autoRefreshFields($autoRefreshFields)
  8. ->pickListValidation($pickListValidation)
  9. ->sslVerification($enableSSLVerification)
  10. ->connectionTimeout($connectionTimeout)
  11. ->timeout($timeout)
  12. ->build();
g. requestProxy : Create an instance of RequestProxy containing the proxy properties of the user. Configure this only if you're using a proxy server to make the API calls.

$requestProxy = (new ProxyBuilder())
 ->host("proxyHost")
 ->port("proxyPort")
 ->user("proxyUser")
 ->password("password")
 ->build();

h. resourcePath : Configure path containing the absolute directory path to store user specific files containing module fields information.

$resourcePath = "/Documents/phpsdk-application";

5. Initilization

Once you have completed the configuration process, you can move on to initializing the SDK and begin making API requests.

Here is a sample code to initialize the SDK, using refresh token flow and DB Persistence.

<?php
use com\zoho\api\authenticator\OAuthBuilder;
use com\zoho\api\authenticator\store\DBBuilder;
use com\zoho\api\authenticator\store\FileStore;
use com\zoho\crm\api\InitializeBuilder;
use com\zoho\crm\api\UserSignature;
use com\zoho\crm\api\dc\USDataCenter;
use com\zoho\api\logger\LogBuilder;
use com\zoho\api\logger\Levels;
use com\zoho\crm\api\SDKConfigBuilder;
use com\zoho\crm\api\ProxyBuilder;
use com\zoho\api\authenticator\store\DBBuilder;

require_once "vendor/autoload.php";

class Initialize
{
  public static function initialize()
  {
    $user = new UserSignature("patricia@zoho.com");
    $environment = USDataCenter::PRODUCTION();
    $token = (new OAuthBuilder())
    ->clientId("1000.xxxxxxxxxxxxxxxx")
    ->clientSecret("554a9776d10ff016a92c1eb01xxxxxxxxxx")
    ->refreshToken("1000.xxxxxxxxxxxxxxxxxxxx")
    ->redirectURL("www.zoho.com")
    ->build();
    $logger = (new LogBuilder())
    ->level(Levels::INFO)
    ->filePath("/Documents/php_sdk_log.log")
    ->build();
   $tokenstore = (new DBBuilder())
    ->host("insert_your_hostname_here")
    ->databaseName("insert_your_database_name_here")
    ->userName("insert_your_db_username_here")
    ->password("insert_your_db_password_here")
    ->portNumber("insert_your_portnumber_here")
    ->tableName("insert_your_table_name_here")
    ->build();
    $autoRefreshFields = false;
    $pickListValidation = false;
    $connectionTimeout = 2;
    $timeout = 2;
    $sdkConfig = (new SDKConfigBuilder())
    ->autoRefreshFields($autoRefreshFields)
    ->pickListValidation($pickListValidation)
    ->sslVerification($enableSSLVerification)
    ->connectionTimeout($connectionTimeout)
    ->timeout($timeout)
    ->build();
    $resourcePath = "/Documents/phpsdk-application";
    $requestProxy = (new ProxyBuilder())
    ->host("proxyHost")
    ->port("proxyPort")
    ->user("proxyUser")
    ->password("password")
    ->build();
    (new InitializeBuilder())
    ->user($user)
    ->environment($environment)
    ->token($token)
    ->store($tokenstore)
    ->SDKConfig($configInstance)
    ->resourcePath($resourcePath)
    ->logger($logger)
    ->requestProxy($requestProxy)
    ->initialize();
  }
}
?>


You are now all set to explore the functionalities of SDK. Here is a sample code to get the records from Leads module, with the ifmodifiedsince header.

<?php
use com\zoho\api\authenticator\OAuthBuilder;
use com\zoho\crm\api\dc\USDataCenter;
use com\zoho\crm\api\InitializeBuilder;
use com\zoho\crm\api\UserSignature;
use com\zoho\crm\api\record\RecordOperations;
use com\zoho\crm\api\record\GetRecordsHeader;
use com\zoho\crm\api\HeaderMap;
use com\zoho\crm\api\ParameterMap;
require_once "vendor/autoload.php";

class Record
{
    public static function initialize()
    {
        $user = new UserSignature('myname@mydomain.com');
        $environment = USDataCenter::PRODUCTION();
        $token = (new OAuthBuilder())
        ->clientId("1000.xxxxxxx")
        ->clientSecret("4b5baxxxxxxxxxxxxf")
        ->grantToken("1000.xxxxx")
        ->build();
        (new InitializeBuilder())
            ->user($user)
            ->environment($environment)
            ->token($token)
            ->initialize();
    }

    public static function getRecords()
    {
        $recordOperations = new RecordOperations();
        $paramInstance = new ParameterMap();
        $headerInstance = new HeaderMap();
     $ifmodifiedsince = date_create("2022-06-01T12:00:00+05:30")->setTimezone(new \DateTimeZone(date_default_timezone_get()));
        $headerInstance->add(GetRecordsHeader::IfModifiedSince(), $ifmodifiedsince);
        $response = $recordOperations->getRecords("Leads", $paramInstance, $headerInstance);
        echo($response->getStatusCode() . "\n");
        print_r($response);
    }
}
Record::initialize();
Record::getRecords();


Next week, we will dive deeper and provide more sample codes to help you further. Stay tuned!

If you have any queries, let us know the comments below, or drop an email to support@zohocrm.com. We would love to hear from you. 



    • Recent Topics

    • Reporting tags for custom modules

      Hi, it could be very useful. At field level and at sub table level. Thanks, Eduardo
    • Can't pass Dates and use date filtered Charts in Pages?

      I don't mess with pages very much, but I'm trying to build a dashboard. I have a search element and several charts that need to be filtered. I also have a stateless form for a start/end date picker I am trying to use to filter data for the charts. Here
    • ZOHO FSM Trial - Assets

      Hi I am currently using Zoho CRM and looking at adding FSM. I am trialing FSM at the moment, to potentially move away from my current programme (SimPro) but have a query on the Asset system within FSM It looks like you can only create 1 asset "type";
    • Customize User Invites with Invitation Templates

      Invitation Templates help streamline the invitation process by allowing users to create customized email formats instead of sending a one-size-fits-all email. Different invitation templates can be created for portal users and client users to align with
    • Sending Email with Attachment (PDF, Excel file)

      Hi, I'm new to Zoho CRM and I'm setting up a flow to send an Email with Attachment when user reaching a certain stage of a Deal. In detail, I've created a Blueprint which requires user to attach a PDF file when reaching a certain point of the stage and
    • Based on the Assign To time task want to trigger also reminder for the task still move form fresh lead

      If the leads is assigned To 1 am to 10.55 am task want to create 11am Then reminder want to go the person at 4pm If lead status not moved from fresh lead. From next on wards Reminder want to go 11 Am and 4pm Every day still the person moved to fresh lead
    • Emails Not Sending

      This has happened before. I contacted Zoho and it seemed to work, but now my emails are not sending or taking a long time to send and half the time attachments don't attach. It just keeps saying Sending... and I have to keep clicking it to make it send.
    • [Free Webinar] Learning Table Series - AI-Enhanced Logistics Management in Zoho Creator

      Hello Everyone! We’re excited to invite you to another edition of Learning Table Series, where we showcase how Zoho Creator empowers industries with innovative and automated solutions. About Learning Table Series Learning Table Series is a free, 45-60
    • WhatsApp pricing changes: Pay per message starting July 1, 2025

      Starting July 1, 2025, WhatsApp is shifting from conversation-based pricing to per-message billing. That means every business-initiated message you send will count. Not just the first one in a 24-hour window. Pricing updates on the WhatsApp Business Platform
    • Create a button that converts Sales Order into a Custom Module

      I am looking for a way of creating a button on Sales Orders that would automatically create a record in a custom module I have created called Contracts. The custom destination module "Contracts"  has the following fields that I would need to populate [Contracts Name] populate with SalesOrderID [Account Name] populate with related Account Name [Contract Start Date] populate with the date that the record was created Could someone help or point me in the right direction? Thanks
    • Remove all of the junk data that comes with the trial

      How would I go about removing all of the junk data that comes with the trial of zoho crm?
    • Video Interview Feature

      Please add a text option as well while sending invitations to candidates for video interviews, candidates are missing out on the email. They are more convenient in text and it really helps Hope you would understand, thanks
    • Singapore DBS Bank

      Is there any schedule corresponding to DBS of Singapore? 
    • Including Contact and Account Information in Zoho Projects.

      In Zoho Projects I have created a custom layout which already includes a 'Client Information' section. The 'Client Information' section already includes integrated fields (integrated with CRM) for various account and contact details. Here's what I want
    • Unable to Download CRM Contact Data: WorkDrive Integration Issues

      ## Problem Description We need to let users download contact information from CRM as CSV files to their local computers. Since we couldn't implement a direct download option, we're trying to use WorkDrive as a workaround - but we're encountering issues
    • App Spotlight : PagerDuty for Zoho Cliq

      App Spotlight brings you hand-picked apps to enhance the power of your Zoho apps and tools. Visit the Zoho Marketplace to explore all of our apps, integrations, and extensions. In today's fast-paced world, seizing every moment is essential for operational
    • Campaigns going to spam folder, how to build so that it goes to inbox

      Hello, New to campaigns, now have it functioning correctly. In my test group of 10 email addresses 100% of the emails went to spam/junk folder and/or were blocked/captured by spam filters. What is the process to building a message or format that does
    • Integrate QuickBooks with Bigin and streamline your sales and accounting!

      If your business relies on Bigin for customer management and QuickBooks for accounting and invoicing, this new integration is here to make your operations more efficient. By connecting these two platforms, you can now manage your CRM and financial processes
    • When a ticket is merged, the merged ticket's link should redirect to the remaining ticket.

      Zoho Desk deletes merged tickets. Which is not ideal. The issue is if you have a link bookmarked, or even in your inbox from a ticket that was merged, when you visit you receive an error because merging tickets actually deletes the ticket that was merged.
    • Pass data from a Zoho Desk ticket to a Zoho Form as pre-fill data?

      Hello, I'm trying to pre-fill a Zoho form with client data based on the Zoho Desk ticket data that would be associated. Work flow i'm trying to create: 1. Ticket created for a sales order 2. order requires a site survey 3. link inside ticket links to
    • Goods total weight in Sales Orders

      Hello everyone, We want to automatically calculate the total weight in Sales Orders based on the weight data specified in the Items. Could you please suggest the simplest way to achieve this in Zoho Inventory? I would greatly appreciate any advice and
    • Problem with pagination in Zoho Inventory API

      Hello, I'm having an issue with the  Zoho Inventory API when I try to use the pagination. When I send a request to https://inventory.zoho.com/api/v1/items?authtoken=XXXXXXXXXX&organization_id=YYYYYY&page=1&per_page=50, I get back 200 items. And when I send the same request for the second page, https://inventory.zoho.com/api/v1/items?authtoken=XXXXXXXXXX&organization_id=YYYYYY&page=2&per_page=50 I'm getting back the same 200 items I get with the first request.  So I think neither the page parameter
    • Can a user be assigned to an Account based on email domain?

      Hi ZohoDesk, If I have a customer Account already configured is there any way I can use a domain matching rule to assign a new user to the correct account when logging a ticket by email? Many thanks Rich
    • Can't track conversions using GTM

      We had to move the installation of the SalesIQ widget from GTM to directly do it in our wordpress site. The SalesIQ widget was being blocked by Adblockers which caused a lot of our visitors to not be able to see it. This issue was fixed from deleting
    • WhatsApp Message Pricing Changes (Effective July 1, 2025)

      Starting July 1, 2025, Meta will introduce a per-message pricing model on the WhatsApp Business Platform, replacing the current conversation-based billing. This update affects all WhatsApp messages sent through Zoho Marketing Automation. We’ve broken
    • Parent-Child Tickets using API or Deluge

      Hi Everyone, We are looking at the parent-child ticketing features in Zoho Desk. We want to be able to create a parent ticket at customer level and nest child tickets underneath. The issue we are facing is to be able to automate this. I'm checking the
    • Blueprint transitions on locked records

      We use the ability to automatically lock records (quotes, sales orders, etc.) based on criteria, such as stage. For instance, if a quote has been sent to a client, the quote is then locked for further edits. Our ideal quote stage process is: Draft>Sent>Won.
    • CC from mail client to Zoho CRM

      Hi,  Is it possible to have emails sent outside of CRM use a CC that sends them into the CRM and attaches to the record?  Thanks
    • Department e-mail signatures

      Hello everyone, We're just in the process of evaluating various help desk software alternatives and Zoho is looking pretty good to us at the moment. Our set up is a bit strange and I was wondering if this is possible. We have one tech who looks after
    • How can I hide "My Requests" and "Marketplace" icon from the side menu

      Hello everybody, We recently started using the new Zoho CRM for Everyone. How can I hide "My Requests" and "Marketplace" from the side menu? We don't use these features at the moment, and I couldn't find a way to disable or remove them. Best regards,
    • WhatsApp Calling Integration via Zoho Desk

      Dear Zoho Desk Team, I would like to request a feature that allows users to call WhatsApp numbers directly via Zoho Desk. This integration would enable sending and receiving calls to and from WhatsApp numbers over the internet, without the need for traditional
    • Sites Speed and Performance Grades

      I noticed that there are no recent inquiries or complaints about load speed or performance issues with Zoho Sites websites. However, I wanted to understand what Zoho has done to ensure that speed remains optimized, images are compressed and lazy loaded,
    • Include Audio in Zoho Assist Session Recordings

      Hello Zoho Assist Team, We hope you're doing well. We’d like to formally submit a feature request regarding session recordings in Zoho Assist. 🎯 Current Limitation When conducting a Zoho Assist session that includes voice and/or video chatting, the recording
    • Unable to update Created Date/Time even via upsert

      hi all --- running a demo version and "recreating" some data from hubspot. I had tried the method to automatically move data over but it missed A TON of fields and some stuff wouldn't even map correctly so i am simply creating new Deal records to test
    • Blockchain Feature?

      Since I'm not an expert in this technology, is there any reason why you would not want to add this option to your Zoho SIgn documents? Is there a downside?
    • Kaizen #196 - Zoho CRM Queries - Best Practices

      Nearing 200th Kaizen Post – We want to hear from you! Do you have any questions, suggestions, or topics you would like us to cover in future posts? Your insights and suggestions help us shape future content and make this series better for everyone. Got
    • Best way to account for shipping charges to customer

      I have been allocating all our shipping expenses to the "postage" account, but I realise that is probably incorrect, as for the most part, we pass on shipping charges to our customers. So I should probably add the shipping charges into the "shipping charges"
    • Zoho Flow s’enrichit avec les subflows et les actions Webhook

      Nous sommes ravis d’annoncer deux ajouts importantsà Zoho Flow : les subflows et les webhooks sortants. Ces nouvelles fonctionnalités ont été conçues pour vous aider à créer des workflows plus facilement et à automatiser davantage de tâches répétitives.
    • How to assign canvas view for portal user

      Hi , as a portal user, I can switch to another canvas view, however, I cannot find any field to configure a default canvas view for portal user. May I ask how to set it up in CRM? And if I can view list by sheet view as a portal user?
    • Restrict Leave Application Based on Attendance Cycle (24th to 23rd)

      Hi Zoho Team, Our organization follows a custom attendance cycle from 24th of the current month to 23rd of the next month. I would like to configure the system so that: Employees should not be able to apply backdated leave for any date after the attendance
    • Next Page