<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[RingCentral Developers - Medium]]></title>
        <description><![CDATA[Revolutionize Communications with one solution for your out of the box and programmatic voice, SMS, messaging, meeting, video, fax, and data needs. - Medium]]></description>
        <link>https://medium.com/ringcentral-developers?source=rss----8ea22f7ec634---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>RingCentral Developers - Medium</title>
            <link>https://medium.com/ringcentral-developers?source=rss----8ea22f7ec634---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 23 Jun 2026 12:44:22 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/ringcentral-developers" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Automating SMS in ServiceNow]]></title>
            <link>https://medium.com/ringcentral-developers/automating-sms-in-servicenow-5ad784f34c72?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/5ad784f34c72</guid>
            <dc:creator><![CDATA[Mike Stowe]]></dc:creator>
            <pubDate>Tue, 09 Jun 2026 02:52:28 GMT</pubDate>
            <atom:updated>2026-06-09T02:55:41.971Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QODmyUyVdrvKmzLi3H1MSg.jpeg" /></figure><p>The platform known as ServiceNow is a major component to an organization’s overall IT Service Management (ITSM) and workflow automation strategy. ServiceNow, according to its website, is “the intelligent platform for business transformation” — delivering end-to-end workflow automation across IT, HR, customer service, and operations. This really means that the product is the key incident management and process automation component to an organization’s broader digital operations offering. The platform can trigger notifications, escalate tickets, send approval requests, and route communications across channels while tracking their effectiveness through real-time dashboards and reporting.</p><p>This tutorial will focus on how ServiceNow can be leveraged to send out SMS messages with the assistance of RingCentral.</p><p><strong>Before you get started, please ensure the numbers you plan to send SMS from are registered under the appropriate TCR Campaign in the RingCentral Admin Portal. To send automated or marketing messages, these numbers must be assigned to an “Automated” campaign type. You cannot use a conversational campaign to send automated or marketing messages.</strong></p><h3>Step 1: Set up JWT token</h3><p>In the RingCentral Developer platform you can create your JWT Key for use with the RingCentral Labs Marketo SMS App. Through the Marketo SMS App you will be able to use Marketo webhooks to connect to the RingCentral SMS APIs. <strong>Please note, this app is in beta and is not officially supported by RingCentral.</strong></p><p>Once you have signed in to the platform, follow these steps:</p><ol><li>Click on your profile name to access the pull-down menu. Click on “Credentials” as shown in figure 1.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/473/0*pmX2MwkilLT-R_Z7" /><figcaption>Figure 1: Access JWT Credentials</figcaption></figure><p>2. Click “Create JWT” which will bring up the following screen:</p><p>Press enter or click to view image in full size</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/921/0*O-7JhFKNBRavm3h6" /><figcaption>Figure 2: Creating the JWT key</figcaption></figure><p>3. Create a name or label for this JWT that will help you recognize what this token is for in the future, and enter it in the Label field.</p><p>4. Under environment, ensure Production is selected</p><p>5. For what apps are permitted to use this credential, check “Only specific apps of my choice.” You will then be prompted for a Client ID.</p><p>Press enter or click to view image in full size</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xZCZxFdaEub1w_Nx" /><figcaption>Figure 3: Specifying a Client ID for the JWT Key</figcaption></figure><p>6. Enter “<strong>fKZNy9WuNShd7aQcu6Z2sj</strong>” as the client ID and click Add App. You should now see “Marketo SMS App” listed as an authorized app for this client ID.</p><p>7. Choose an expiration date or leave blank. If you enter an expiration date, your token will stop working after this time, and you will need to create a new token before the expiration or you will not be able to send SMS through the Marketo SMS App API.</p><p>8. Click create JWT. You should now see your credentials screen.</p><p>9. Click the copy icon next to your JWT to get the full JWT code.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HOZ3SYRjCm-9wRXL" /><figcaption>Figure 4: Generated JWT Key ready for use.</figcaption></figure><h3>Setting up ServiceNow</h3><p>ServiceNow uses a concept called <strong>REST Messages</strong> to integrate with outside applications like RingCentral. In ServiceNow, find the link called “REST Message” under the <strong>Outbound</strong> section, which is found within the <strong>System Web Services</strong> module in the left-hand navigation menu. Create a new REST Message and name it appropriately.</p><p>Now open the created record, and in the HTTP Methods related list, click <strong>New</strong> and select the HTTP method as <strong>POST</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W8JQbUWJARRaWVKGLmlcJA.png" /></figure><p><strong>Enter the following information:</strong></p><p><strong>Endpoint: </strong><a href="https://marketo.apps.gamechanging.dev/api/sms">https://marketo.apps.gamechanging.dev/api/sms</a></p><p><strong>Content: </strong>jwt=JWT_TOKEN&amp;fromNumber=${from}&amp;toNumber=${to}&amp;type=standard&amp;text=${text}</p><p><strong>Content-type:</strong> application/json</p><blockquote>Important: Replace <strong>JWT_TOKEN</strong> with the JWT Token you generated in Step 1. You may also save it as a variable in ServiceNow. Ensure that ${from} is a SMS registered RingCentral phone number tied to your extension.</blockquote><p>You should now be able to utilize RingCentral within ServiceNow to send SMS messages using ServiceNow REST Messages.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5ad784f34c72" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/automating-sms-in-servicenow-5ad784f34c72">Automating SMS in ServiceNow</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Automating Video Call Follow Ups Using the RingCentral AI Integration API]]></title>
            <link>https://medium.com/ringcentral-developers/automating-video-call-follow-ups-using-the-ringcentral-ai-integration-api-acc459944f3c?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/acc459944f3c</guid>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[ringcentral-developer]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[integration]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Tue, 02 Jun 2026 06:01:01 GMT</pubDate>
            <atom:updated>2026-06-02T06:01:01.015Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BlqYiBUrHMQKhL_znLXXSA.png" /></figure><p>Video meetings are full of decisions, action items, deadlines, and customer commitments. The problem is that most teams still rely on manual note taking and human memory to create follow ups after the meeting ends.</p><p>That creates delays, inconsistent communication, and often missed tasks.</p><p>With RingCentral’s communication platform APIs and its set of AI-specific APIs, developers can automate much of this workflow using real meeting recordings, AI-generated summaries, and messaging integrations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/610/1*dtp2GbnZcN0JOrs3eEuzRA.png" /></figure><p>Instead of manually reviewing the recording of a lengthy meeting, your application can automatically:</p><ul><li>retrieve meeting or call insights</li><li>extract action items</li><li>generate customer follow up emails</li><li>send internal team notifications</li><li>create CRM tasks</li><li>archive meeting intelligence</li></ul><p>This article walks through a practical PHP implementation using currently documented RingCentral APIs and SDK syntax.</p><p>The workflow we will build could look like this:</p><ol><li>A RingCentral video meeting</li><li>RingCentral generates recordings and AI insights</li><li>Your application retrieves the insights</li><li>PHP code processes the summaries and action items</li><li>Automated follow ups are generated and delivered</li></ol><h3>The APIs Used</h3><p>This workflow will make use of a few different RingCentral platform capabilities:</p><ul><li>Call Log API — Detect completed video calls and recordings</li><li>Webhooks — Receive real-time event notifications</li><li>Call Recording API — Access video recording metadata and media</li><li>RingSense / AI Conversation Expert API — Retrieve summaries, transcripts, highlights, and action items</li></ul><h3>Required Application Scopes</h3><p>Your RingCentral application must request the proper OAuth scopes depending on which endpoints are used.</p><ul><li>ReadCallLog — Read call and meeting records</li><li>ReadCallRecording — Access recordings metadata and content</li><li>WebhookSubscriptions — Create Webhook subscriptions</li><li>SMS — if you intend to disseminate video call summaries by text</li><li>Team Messaging — if you intend to disseminate video call summaries by Team Messaging means</li><li>Fax — if you intend to disseminate video call summaries by fax</li></ul><h3>Understanding What the AI Integration Provides</h3><p>RingCentral AI capabilities are exposed through features like voice recordings, transcripts, and summaries generated from recorded call meetings. These artifacts become available soon after a conference call ends and can be accessed through the platform’s insights API endpoint.</p><p>In practice, this means your workflow will combine:</p><ul><li>meeting lifecycle events via the Notifications API</li><li>call recording and meeting data via the REST API</li><li>your own logic to distribute follow ups</li></ul><p>Let’s look at the steps involved in a concrete use case. After a video meeting is recorded, with transcription and notes turned on, your system should get a notification that a video call event has occurred. From there, your application can retrieve the call’s recording and metadata, extract the call’s available transcript or summary data, and send follow up communication to participants.</p><p>Instead of polling for completed video calls, you can subscribe to an RCV (RingCentral Video) event and react in real time. Before this notification functionality is active however you need to have a few things in place.</p><ol><li>Your RingCentral account (phone number) should have the “AI Conversation Expert” licence active on it (there is an additional fee for this service). See the following image showing how this is established within the Service Web interface.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zpZ9DnFn2jX2p2avsnXxKQ.png" /></figure><p>2. You need to have a RingCentral developer app (REST JWT) with the following scopes attached to it:</p><p>Call Control<br>Read Call Log<br>Read Call Recording<br>RingSense<br>SMS<br>Webhook Subscriptions</p><p>You will need even more app scopes active if you plan to send call follow-up information messages by fax or Team Messaging, for example.</p><h3>Setting Up Event Subscriptions</h3><p>To detect when a video call’s transcription information is available you can subscribe to /rcv/insights events. You do this by creating a webhook that “listens” for these events. The RingCentral API platform will watch for an event that indicates when the video call or session transcription information is available.</p><p>Here is how to create a subscription using the RingCentral PHP SDK. After you connect to the SDK ($platform) you create the subscription with the post method passing it the needed credentials.</p><pre>try {<br> $api_call = $platform-&gt;post(&#39;/subscription&#39;,<br> array(<br> &quot;eventFilters&quot; =&gt; array(&#39;/ai/ringsense/v1/public/accounts/~/domains/rcv/insights&#39;,),<br> &quot;expiresIn&quot; =&gt; &quot;315360000&quot;,<br> &quot;deliveryMode&quot; =&gt; array(<br> &quot;transportType&quot; =&gt; &quot;WebHook&quot;,<br> // need full URL for this to work as well<br> &quot;address&quot; =&gt; $subscription_url,<br> )<br> )<br> );<br> $webhook_id = $api_call-&gt;json()-&gt;id;<br> echo_spaces(&quot;Webhook ID&quot;, $webhook_id);<br>} catch (\RingCentral\SDK\Http\ApiException $e) {<br> echo_spaces(&quot;create_webhook API Exception&quot;, $e-&gt;getMessage(), 2);<br> exit();<br>}</pre><p>This registers your application to receive updates about session state changes and in our sample code we display the newly created webhook (subscription) id.</p><h3>When the Webhook is Triggered</h3><p>Once established, the webhook will react when a suitable event occurs. In this case, as mentioned, when the video call’s transcription information is ready for use. When the event is triggered the payload of that event is sent to the URL address that you provided when it was created, “address” =&gt; $subscription_url,. After it passes some necessary validation we get the event information payload and optionally save it to the server (received_Video_EVENT_payload.log) for later debugging, if needed.</p><pre>$hvt = isset($_SERVER[&#39;HTTP_VALIDATION_TOKEN&#39;]) ? $_SERVER[&#39;HTTP_VALIDATION_TOKEN&#39;] : &#39;&#39;;<br>if (strlen($hvt) &gt; 0) {<br>header(&quot;Validation-Token: {$hvt}&quot;);<br>}<br>$incoming = file_get_contents(&quot;php://input&quot;);<br>// if desired, also save the incoming event information to<br>// a local file for human viewing<br>file_put_contents(&quot;received_Video_EVENT_payload.log&quot;, $incoming);<br>if (empty($incoming)) {<br>http_response_code(200);<br>// echo json_encode(array(&#39;responseType&#39; =&gt; &#39;error&#39;, &#39;responseDescription&#39; =&gt; &#39;No data provided Check Event payload.&#39;));<br>echo_spaces(&quot;No video data payload received Check Event payload.&quot;);<br>exit();<br>}<br>$incoming_event_data = json_decode($incoming, true);<br>if (!$incoming_event_data) {<br>http_response_code(200);<br> echo_spaces(&quot;Media type not supported. Please use JSON.&quot;, &quot;&quot;, 2);<br> exit();<br>}</pre><p>The event payload would be one continuous string that could look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/987/1*PFtWLX8zayquioh8RVSqvQ.png" /></figure><p>After this step, our code then extracts the information that we need to get the details from the API. The remaining code follows. After we break down the incoming data object to its respective event information we connect to the SDK and test each event to see if the call has a “Disconnected” status, this means that the call is completed and the AI insights should be available. It can actually take some time to assemble the insights information depending on how long the call was and how busy the servers are at the time. You may want to wait a few minutes after the event is triggered before you collect the call transcript and other information to ensure it is all there. Assuming all the event insights are ready for us we then collect the call log information with a get method call to the call-log endpoint based on the sessionId and from that response object we can get the call details.</p><pre>$controller = ringcentral_sdk();<br>$platform = $controller[&#39;platform&#39;];<br>//echo_spaces(&quot;incoming EVENTS&quot;, $incoming_event_data, 2);<br>echo_spaces(&quot;Call Title&quot;, $incoming_event_data[&#39;body&#39;][&#39;title&#39;], 1);<br>foreach ($incoming_event_data[&#39;body&#39;][&#39;speakerInfo&#39;] as $speaker) {<br> echo_spaces(&quot;Speaker Name&quot;, $speaker[&#39;name&#39;]);<br>}<br>echo_spaces(&quot;&quot;, &quot;&quot;, 1);<br>foreach ($incoming_event_data[&#39;body&#39;][&#39;insights&#39;][&#39;Transcript&#39;] as $segment) {<br> echo_spaces(&quot;Transcript segment&quot;, $segment[&#39;text&#39;]);<br>}<br>echo_spaces(&quot;&quot;, &quot;&quot;, 1);<br>echo_spaces(&quot;Call Summary&quot;, $incoming_event_data[&#39;body&#39;][&#39;insights&#39;][&#39;Summary&#39;][0][&#39;value&#39;], 1);</pre><p>If you want to see the whole call log object structure ($incoming_event_data), you can output it in a similar way to the code that is commented out on the third line in the above section of code.</p><p>I am sending some of the event payload information to the output stream so that I can see what is going on with my code, but typically the processing of webhook events is non-visual. I can see the output when I run my code through a service like postman (postman.com). Following is an image showing what the output looks like.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xxGAELTJ36TJJKkIC5XSwQ.png" /></figure><p>You can then use any or all of the transcribed information available to you to send out call summary SMS messages, Team Messaging group notes, and even Faxes if you so wish.</p><h3>Closing Thoughts</h3><p>Automating video call follow ups is a natural extension of event-driven architecture. RingCentral provides the building blocks through its Notifications API, call log endpoints, and recording resources. AI-generated transcripts and insights add an additional layer of value to the communications process.</p><p>By combining these powerful API pieces, you can build a workflow that ensures every call meeting is followed up by timely, consistent communication without needing time consuming manual processes.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=acc459944f3c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/automating-video-call-follow-ups-using-the-ringcentral-ai-integration-api-acc459944f3c">Automating Video Call Follow Ups Using the RingCentral AI Integration API</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Automating Conference Call Follow Ups Using the RingCentral AI Integration API]]></title>
            <link>https://medium.com/ringcentral-developers/automating-conference-call-follow-ups-using-the-ringcentral-ai-integration-api-54580d81f9d8?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/54580d81f9d8</guid>
            <category><![CDATA[ringcentral-developer]]></category>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[integration]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Mon, 11 May 2026 23:01:01 GMT</pubDate>
            <atom:updated>2026-05-11T23:01:01.376Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jlF_WFpL4yt7NL3h6myRHg.png" /></figure><p>Conference call meeting follow ups are one of those tasks that everyone agrees are important, but because it is often very manual “busy work”, follow ups are often delayed or skipped entirely. Call notes get buried, action items are forgotten, and momentum fades quickly after a call ends.</p><p>With RingCentral’s AI-powered meeting insights and the existing platform APIs, you can automate much of this workflow. The goal is not to replace human judgment, but to ensure that summaries, recordings, and key outputs are delivered consistently and promptly after a meeting.</p><p>This article walks through how to build a practical follow up system using RingCentral APIs, webhook notifications, and the PHP SDK.</p><h3>Understanding What the AI Integration Provides</h3><p>RingCentral AI capabilities are exposed through features like voice recordings, transcripts, and summaries generated from recorded call meetings. These artifacts become available after a conference call ends and can be accessed through the platform’s insights API endpoint.</p><p>In practice, this means your workflow will combine:</p><ul><li>meeting lifecycle events via the Notifications API</li><li>call recording and meeting data via the REST API</li><li>your own logic to distribute follow ups</li></ul><p>Let’s look at the steps involved in a concrete use case.</p><p>After a voice call meeting is recorded with transcription and notes turned on, your system should:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/619/1*NBG3CS7dg_sfXDrsIIyjIw.png" /></figure><ul><li>detect that the call has ended</li><li>retrieve the recording and metadata</li><li>extract available transcript or summary data</li><li>send a follow up communication message to participants</li></ul><p>Instead of polling for completed calls, you can subscribe to telephony events and react in real time. Before this is active however you need to have a few things in place.</p><ol><li>Your RingCentral account (phone number) should have the “AI Conversation Expert” licence active on it (there is an additional fee for this service). See the following image showing how this is established within the Service Web interface.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zpZ9DnFn2jX2p2avsnXxKQ.png" /></figure><p>2. You need to have a RingCentral developer app (REST JWT) with the following scopes attached to it.<br>a) Call Control<br>b) Read Call Log<br>c) Read Call Recording<br>d) RingSense<br>e) SMS<br>f) Webhook Subscriptions</p><p>You will need more app scopes active if you plan to send call followup information messages by fax or Team Messaging, for example.</p><h3>Setting Up Event Subscriptions</h3><p>To detect when a call session ends, you can subscribe to telephony session events. You do this by creating a webhook that “listens” for these events. We watch for an event that indicates when a call or session changes state.</p><p>Here is how to create a subscription using the RingCentral PHP SDK. After you connect to the SDK ($platform) you create the subscription with the post method passing it the needed credentials.</p><pre>try {<br>$api_call = $platform-&gt;post(&#39;/subscription&#39;,<br>array(<br>&quot;eventFilters&quot; =&gt; array(<br>&#39;/restapi/v1.0/account/~/telephony/sessions&#39;,<br>),<br>&quot;expiresIn&quot; =&gt; &quot;315360000&quot;,<br>&quot;deliveryMode&quot; =&gt; array(<br>&quot;transportType&quot; =&gt; &quot;WebHook&quot;,<br>// need full URL for this to work as well<br>&quot;address&quot; =&gt; $subscription_url,<br>)<br>)<br>);<br>$webhook_id = $api_call-&gt;json()-&gt;id;<br>echo_spaces(&quot;Webhook ID&quot;, $webhook_id);<br>} catch (\RingCentral\SDK\Http\ApiException $e) {<br>echo_spaces(&quot;create_webhook API Exception&quot;, $e-&gt;getMessage());<br>exit();<br>}</pre><p>This registers your application to receive updates about session state changes and in our sample code we display the newly created webhook (subscription) id.</p><h3>When the Webhook is Triggered</h3><p>Once established, the webhook will react when a suitable event occurs. In this case when a telephony event happens. When the event is triggered the payload of that event is sent to the URL address that you provided when it was created, “address” =&gt; $subscription_url. After it passes some necessary validation we get the event information payload and optionally save it to the server (received_EVENT_payload.log) for later debugging, if needed.</p><pre>$hvt = isset($_SERVER[&#39;HTTP_VALIDATION_TOKEN&#39;]) ? $_SERVER[&#39;HTTP_VALIDATION_TOKEN&#39;] : &#39;&#39;;<br>if (strlen($hvt) &gt; 0) {<br>header(&quot;Validation-Token: {$hvt}&quot;);<br>}<br>$incoming = file_get_contents(&quot;php://input&quot;);<br>// if desired, also save the incoming event information to<br>// a local file for human viewing<br>file_put_contents(&quot;received_EVENT_payload.log&quot;, $incoming);<br>if (empty($incoming)) {<br>http_response_code(200);<br>echo json_encode(array(&#39;responseType&#39; =&gt; &#39;error&#39;, &#39;responseDescription&#39; =&gt; &#39;No data provided Check Event payload.&#39;));<br>exit();<br>}<br>$incoming_event_data = json_decode($incoming, true);<br>if (!$incoming_event_data) {<br>http_response_code(200);<br>echo json_encode(array(&#39;responseType&#39; =&gt; &#39;error&#39;, &#39;responseDescription&#39; =&gt; &#39;Media type not supported. Please use JSON.&#39;));<br>exit();<br>}</pre><p>The event payload would be one continuous string that could look like this:</p><pre>{&quot;uuid&quot;:&quot;6975102786429086013&quot;,&quot;event&quot;:&quot;/restapi/v1.0/account/3058829020/<br>telephony/sessions&quot;,&quot;timestamp&quot;:&quot;2026–04–27T18:45:22.168Z&quot;,&quot;subscriptionId&quot;<br>:&quot;2ff48c00–6c78–4ef5–8eb4–1a269ff1e616&quot;,&quot;ownerId&quot;:&quot;2412476021&quot;,&quot;body&quot;:<br>{&quot;sequence&quot;:11,&quot;sessionId&quot;:&quot;6326XXX6020&quot;,&quot;telephonySessionId&quot;:<br>&quot;s-a0d16e911f939z19dd04137ffz2432460000&quot;,&quot;serverId&quot;:&quot;10.13.22.233.TAM&quot;,<br>&quot;eventTime&quot;:&quot;2026–04–27T18:45:22.070Z&quot;,&quot;parties&quot;:[{&quot;accountId&quot;:&quot;30588XXX20&quot;,<br>&quot;id&quot;:&quot;p-a0d16e911f939zXXXfz2432460000–1&quot;,&quot;direction&quot;:&quot;Outbound&quot;,&quot;to&quot;:<br>{&quot;phoneNumber&quot;:&quot;+190XXX774&quot;,&quot;name&quot;:&quot;Peter Beck MacIntyre&quot;,&quot;extensionId&quot;<br>:&quot;241XXX21&quot;}, &quot;from&quot;:{&quot;phoneNumber&quot;:&quot;+190XXX5827&quot;,&quot;name&quot;:&quot;CHARLOTTETOW PE&quot;},<br>&quot;status&quot;:{&quot;code&quot;:&quot;Disconnected&quot;, &quot;rcc&quot;:false},&quot;park&quot;:{},&quot;missedCall&quot;:false,<br>&quot;standAlone&quot;:false,&quot;muted&quot;:false}],&quot;origin&quot;:{&quot;type&quot;:&quot;Call&quot;}}}</pre><p>I have added “XXX” to some of the listed information above for security reasons. After this step, our code then extracts the information that we need to get the details from the API. The remaining code follows. After we break down the incoming data object to its respective event information we connect to the SDK and test each event to see if the call has a “Disconnected” status, this means that the call is completed and the AI insights should be available. It can actually take some time to assemble the insights information depending on how long the call was and how busy the servers are at the time. You may want to wait a few minutes after the event is triggered before you collect the call transcript and other information to ensure it is all there. Assuming all the event insights are ready for us we then collect the call log information with a get method call to the call-log endpoint based on the sessionId and from that response object we can get the call details.</p><pre>$controller = ringcentral_sdk();<br>$platform = $controller[&#39;platform&#39;];<br>if (isset($incoming_event_data[&#39;body&#39;][&#39;parties&#39;])) {<br>foreach ($incoming_event_data[&#39;body&#39;][&#39;parties&#39;] as $party) {<br>if ($party[&#39;status&#39;][&#39;code&#39;] == &quot;Disconnected&quot;) {<br>echo_spaces(&quot;Session ID&quot;, $incoming_event_data[&#39;body&#39;][&#39;sessionId&#39;]);<br>echo_spaces(&quot;Call status&quot;, $party[&#39;status&#39;][&#39;code&#39;]);<br>$apiResponse = $platform-&gt;get(&#39;/restapi/v1.0/account/~/call-log&#39;, [<br>&#39;sessionId&#39; =&gt; $incoming_event_data[&#39;body&#39;][&#39;sessionId&#39;]<br>]);<br>$callLog = $apiResponse-&gt;json();<br>echo_spaces(&quot;Recording ID&quot;, $callLog-&gt;records[0]-&gt;recording-&gt;id, 1);<br>echo_spaces(&quot;Recording ContentURI&quot;, $callLog-&gt;records[0]-&gt;recording-&gt;uri, 1);<br>$recordingId = $callLog-&gt;records[0]-&gt;recording-&gt;id;<br>// echo_spaces(&quot;call log deets&quot;, $callLog);</pre><p>If you want to see the whole call log object structure you can output it in a similar way to the code line above.</p><p>The next section of code takes the recording id and accesses the transcription information from the “ai… insights” end point.</p><pre>try {<br>$endpoint = &#39;/ai/ringsense/v1/public/accounts/~/domains/pbx/records/&#39; . $recordingId . &#39;/insights&#39;;<br>$resp = $platform-&gt;get($endpoint);<br>$insightsObj = $resp-&gt;json();<br>//echo_spaces(&quot;Recording insights&quot;, $insightsObj, 1);<br>$attendeeCount = 1;<br>// cycle through the list of call attendees adding a counter to the output<br>foreach ($insightsObj-&gt;speakerInfo as $attendees) {<br>echo_spaces(&quot;Call attendee $attendeeCount&quot;, $attendees-&gt;name);<br>$attendeeCount++;<br>}<br>echo_spaces(&quot;&quot;, &quot;&quot;, 1);<br>echo_spaces(&quot;Call Summary&quot;, $insightsObj-&gt;insights-&gt;Summary[0]-&gt;value, 1);<br>echo_spaces(&quot;Call Notes and recap&quot;, $insightsObj-&gt;insights-&gt;CallNotes[0]-&gt;value, 1);<br>} catch (ApiException $e) {<br>print &#39;Expected HTTP Error: &#39; . $e-&gt;getMessage() . PHP_EOL;<br>}<br>}<br>}<br>}</pre><p>I occasionally send some information to the output stream so that I can see what is going on with my code, but typically the processing of webhook events is non-visual. I can see the output when I run my code through a service like postman (<a href="http://postman.com">postman.com</a>). Following is an image showing what the output looks like.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kj8mJzqFKFoBhla2UpRYCg.png" /></figure><p>If you want to see the whole insights AI object content, then use a similar line of code to this one: echo_spaces(“Recording insights”, $insightsObj, 1);</p><p>This will list the object structure similar to the following and you can use that to extract any of the AI generated content relating to a particular call. Here is what a partial listing could look like as generated from within postman.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/686/1*fwI6u4MF9wgtvCnV1E6exA.png" /></figure><p>You can then use any or all of the transcribed information available to you to send out call summary SMS messages, Team Messaging group notes, and even Faxes if you so wish.</p><h3>Closing Thoughts</h3><p>Automating conference call follow ups is a natural extension of event-driven architecture. RingCentral provides the building blocks through its Notifications API, call log endpoints, and recording resources. AI-generated transcripts and insights add an additional layer of value to the communications process. In a future article I will show you how to get similar information from video meetings so stay tuned.</p><p>By combining these powerful API pieces, you can build a workflow that ensures every call meeting is followed up by timely, consistent communication without needing time consuming manual processes.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=54580d81f9d8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/automating-conference-call-follow-ups-using-the-ringcentral-ai-integration-api-54580d81f9d8">Automating Conference Call Follow Ups Using the RingCentral AI Integration API</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Automating Billing Notifications Using the RingCentral Notifications API]]></title>
            <link>https://medium.com/ringcentral-developers/automating-billing-notifications-using-the-ringcentral-notifications-api-271451c1ea39?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/271451c1ea39</guid>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[ringcentral-developer]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[workflow]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Tue, 05 May 2026 15:08:25 GMT</pubDate>
            <atom:updated>2026-05-05T15:08:23.507Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NLU73t_wM2M3RVtAnvneGQ.png" /></figure><p>Billing workflows are rarely real time by default. Most systems rely on scheduled jobs or periodic polling to detect events like new invoices, failed payments, or overdue balances. That approach works, but it introduces latency and unnecessary API calls.</p><p>RingCentral’s Notifications API provides a cleaner pattern. Instead of polling, your application can subscribe to events and react as they happen. In this article, we will walk through how to use webhook-based subscriptions with the RingCentral PHP SDK to build a simple but realistic billing notification system. We will focus on a practical flow that you can adapt to your own system.</p><h3>Understanding the Notifications API</h3><p>At its core, the RingCentral Notifications API is built around subscriptions. A subscription defines:</p><ul><li>which events you care about</li><li>how those events should be delivered</li></ul><p>Delivery can happen via WebHooks or WebSockets. For billing-related workflows, WebHooks are usually the better choice because they tend to integrate more naturally with backend systems so we will focus this article on that aspect of the process.</p><p>To create a subscription, you send a POST request to the <strong><em>/restapi/v1.0/subscription</em></strong> endpoint with a list of event filters and a delivery mode.</p><p>In the PHP SDK, that looks like this:</p><pre>try {<br>$api_call = $platform-&gt;post(&#39;/subscription&#39;,<br>array(<br>&quot;eventFilters&quot; =&gt; array(<br>&quot;/restapi/v1.0/account/~/extension/~/message-store&quot;,<br>),<br>&quot;expiresIn&quot; =&gt; &quot;315360000&quot;,<br>&quot;deliveryMode&quot; =&gt; array(<br>&quot;transportType&quot; =&gt; &quot;WebHook&quot;,<br>// need full URL for this to work as well<br>&quot;address&quot; =&gt; $subscription_url,<br>)<br>)<br>);<br>$webhook_id = $api_call-&gt;json()-&gt;id;<br>echo_spaces(&quot;Webhook ID&quot;, $webhook_id);<br>} catch (\RingCentral\SDK\Http\ApiException $e) {<br>echo_spaces(&quot;create_webhook API Exception&quot;, $e-&gt;getMessage());<br>exit();<br>}</pre><p>This tells RingCentral to push events to your webhook URL address located at <strong><em>$subscription_url</em></strong> whenever relevant activity occurs. We even echo the webhook identifier out to the screen to show that a webhook indeed was created. You may want to add in some controlling code here as well to ensure that you only create one webhook for this purpose for efficiency’s sake.</p><p>Note that subscriptions are not permanent <strong><em>“expiresIn” =&gt; “315360000”</em></strong>. Granted this is set to expire in approximately 10 years (315360000 seconds), but they do eventually expire and must be renewed periodically, or recreated if they lapse.</p><p>While there is no dedicated “billing event” endpoint, billing notifications are typically triggered indirectly through messaging or system-generated alerts. For example:</p><ul><li>SMS alerts for payment failures</li><li>system notifications sent to an extension mailbox</li><li>integrations that convert external billing events into messages</li></ul><p>That makes the message store event filter a practical starting point. You will have to look for specific strings in the messaging in order to react appropriately. We will point this out later in our sample code when we process the incoming event information.</p><h3>A Realistic Billing Notification Flow</h3><p>Let’s ground this in a real life situation. Imagine you run a magazine subscription service that does the following:</p><ul><li>charges customers monthly</li><li>sends SMS reminders for failed payments</li><li>wants to notify internal staff immediately when a billing issue occurs</li></ul><p>Instead of polling for new messages, you can subscribe to message-store events and process them as they occur.</p><p>The flow could look like this:</p><ol><li>Customer payment fails in your billing system</li><li>Your system sends an SMS via RingCentral</li><li>RingCentral logs that message in the message store</li><li>Your webhook receives an event notification</li><li>Your app parses the message and reacts accordingly</li></ol><p>This approach makes your system reactive rather than passive. It can manage events as they occur rather than doing a nightly or weekly process that would have built in latency.</p><h3>Setting Up the Webhook Endpoint</h3><p>Before creating a subscription, you need a webhook endpoint that can receive events. You will also need a <a href="https://medium.com/ringcentral-developers/a-beginners-guide-to-the-ringcentral-rest-api-part-2-007a503aea12">RingCentral app</a> that is created under your developer account that has the follow scope as a minimum:</p><ul><li>SMS</li><li>Webhook Subscriptions</li><li>Read Messages (not needed if you also have SMS in scope)</li></ul><p>You should add in Faxes or Team Messaging if you also plan to send event response notifications to those destinations.</p><p>RingCentral requires your webhook to handle a validation handshake. When the subscription is created, RingCentral sends a request with a <strong><em>Validation-Token</em></strong> header. Your server must return that same header to confirm the endpoint.</p><p>A minimal PHP webhook processing code example looks like this:</p><pre>$hvt = isset($_SERVER[&#39;HTTP_VALIDATION_TOKEN&#39;]) ? $_SERVER[&#39;HTTP_VALIDATION_TOKEN&#39;] : &#39;&#39;;<br>if (strlen($hvt) &gt; 0) {<br>header(&quot;Validation-Token: {$hvt}&quot;);<br>}<br>$incoming = file_get_contents(&quot;php://input&quot;);<br>// if desired, also save the incoming event information to <br>// a local file for human viewing<br>file_put_contents(&quot;received_EVENT_payload.log&quot;, $incoming);<br>if (empty($incoming)) {<br>http_response_code(200);<br>echo json_encode(array(&#39;responseType&#39; =&gt; &#39;error&#39;, &#39;responseDescription&#39; =&gt; &#39;No data provided Check Event payload.&#39;));<br>exit();<br>}<br>$incoming_data = json_decode($incoming);<br>if (!$incoming_data) {<br>http_response_code(200);<br>echo json_encode(array(&#39;responseType&#39; =&gt; &#39;error&#39;, &#39;responseDescription&#39; =&gt; &#39;Media type not supported. Please use JSON.&#39;));<br>exit();<br>}</pre><p>Once validated, and the content verified we can start processing the event information. The rest of the code could look like this.</p><pre>// pickup the message id from the event and then get the <br>// full message information from the message-store<br>$messageId = $incoming_data-&gt;body-&gt;changes[&#39;0&#39;]-&gt;newMessageIds[&#39;0&#39;] ;<br>$controller = ringcentral_sdk();<br>$platform = $controller[&#39;platform&#39;];<br>try {<br>$apiResponse = $platform-&gt;get(&quot;/restapi/v1.0/account/~/extension/~/message-store/$messageId&quot;);<br>$messageDetails = $apiResponse-&gt;json();<br>echo_spaces(&quot;Event Message Subject&quot;, $messageDetails-&gt;subject);<br> echo_spaces(&quot;Event direction&quot;, $messageDetails-&gt;direction);<br> // you can display the whole object structure this way to see<br> // all the other information that you may want to access<br> // echo_spaces(&quot;Event Message&quot;, $event_message);<br>// Example: detect billing-related SMS<br>if (strpos($messageDetails-&gt;subject, &#39;Payment failed&#39;) !== false) {<br>// Trigger internal alert(s) as needed.<br> // send to TM, SMS, create a fax, etc.<br>echo_spaces(&quot;Event Message&quot;, $messageDetails-&gt;subject, 1);<br>}<br>} catch (\RingCentral\SDK\Http\ApiException $e) {<br>echo_spaces(&quot;Event ERROR Message&quot;, $e-&gt;getMessage(), 1);<br>}</pre><p>In this example all we are doing is sending the message text <strong><em>$messageDetails-&gt;subject</em></strong> to the screen for demo purposes. Within that <strong><em>if</em></strong> code segment you can react to the event in any way you wish.</p><p>For testing purposes be sure to examine the event payload itself that is saved to the <strong><em>received_EVENT_payload.log</em></strong> file if that line of code is active. Once you open that file it should look something like this structure:</p><pre>{&quot;uuid&quot;:&quot;7653382350236984160&quot;,&quot;event&quot;:&quot;/restapi/v1.0/account/xxxxxx/extension<br>/xxxxxx/message-store&quot;,&quot;timestamp&quot;:&quot;2026–04–21T18:20:48.180Z&quot;,&quot;subscriptionId&quot;<br>:&quot;26a87daa-5066–45b9-b8c4-fcaea228f7f0&quot;,&quot;ownerId&quot;:&quot;62199486016&quot;,<br>&quot;body&quot;:{&quot;accountId&quot;:xxxxxx,&quot;extensionId&quot;:xxxxxx,&quot;lastUpdated&quot;:<br>&quot;2026–04–21T18:20:38.674Z&quot;,&quot;changes&quot;:[{&quot;type&quot;:&quot;SMS&quot;,&quot;newCount&quot;:1,<br>&quot;updatedCount&quot;:0,&quot;newMessageIds&quot;:[33982xxxx017]}]}}</pre><p>You can then use that for testing on a site like <a href="http://postman.com">postman.com</a> and you can echo out data that would normally not show as the processing of the webhook if a non-visual code element. A sample postman screen could look like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dg9e-l6FSUfJGeoqEc1MLQ.png" /></figure><h3>Processing Billing Notifications</h3><p>Once events start flowing in, your webhook becomes the decision engine. You can build in other <strong><em>if</em></strong> conditions for the event within the <strong><em>try </em></strong>block and react to other situations like “Credit card expired”, “shipping address not given”, or anything that may be contained within the SMS message.</p><h3>Closing Thoughts</h3><p>Automating billing notifications is less about the actual billing itself and more about reacting to events reliably.</p><p>RingCentral’s Notifications API gives you a clean, event-driven foundation. By combining webhook subscriptions with message-store events, you can build systems that respond instantly to billing issues without relying on polling or scheduled jobs.</p><p>The result is simpler architecture, faster response times, and a better experience for both your team and your customers.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=271451c1ea39" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/automating-billing-notifications-using-the-ringcentral-notifications-api-271451c1ea39">Automating Billing Notifications Using the RingCentral Notifications API</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Guide to Authentication and Authorization with RingCentral APIs]]></title>
            <link>https://medium.com/ringcentral-developers/a-guide-to-authentication-and-authorization-with-ringcentral-apis-49c059a9c9b8?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/49c059a9c9b8</guid>
            <category><![CDATA[ringcentral-developer]]></category>
            <category><![CDATA[authorization]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[authentication]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Mon, 13 Apr 2026 16:01:01 GMT</pubDate>
            <atom:updated>2026-04-13T16:01:01.641Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PWT3rgIww3hGSmkUkwWpWA.png" /></figure><p>Spanning the full range of simple automated workflows to large scale integration with agentic AI, APIs are becoming critical to power modern business communications. When you build an app that needs to interact with RingCentral for voice calls, messaging, fax, or SMS (just to name a few of this API’s functions) you must first securely authenticate and authorize it. This guide shows you how to establish authentication and then demonstrates how authorization works with RingCentral’s API. This demonstration will be done with the help of PHP code samples.</p><p>With the RingCentral API you could be building a CRM integration that sends SMS updates to customers, an automated voice attendant that places calls based on business rules, or a team messaging dashboard that posts notifications to all members of a chat group. To connect with and use the RingCentral API efficiently, you’ll need a solid understanding of RingCentral’s OAuth 2.0 implementation.</p><h3>What are authentication and authorization?</h3><p>While it might seem that these two terms are synonymous, there is a marked difference when it comes to API usage. Authentication means that you verify who (or what) your app is. This means gaining initial access to the API platform by proving that you have legitimate permission to connect to it. Authorization defines what your app is allowed to do on behalf of a user or system after you have authenticated your global access. This defines the scope of what the app is allowed to perform within that platform. This will become more clear as we work through the examples.</p><p>It’s important to note that RingCentral uses OAuth 2.0, the industry standard for delegated authorization. This means your app doesn’t store user passwords; it authenticates by exchanging tokens instead.</p><h3>Prerequisites</h3><p>Before you begin, make sure you have:</p><ul><li>A RingCentral developer account, obtained here: <a href="https://developers.ringcentral.com/">https://developers.ringcentral.com</a></li><li>An app registered in the RingCentral Developer Portal</li><li>Your Client ID and Client Secret provided by the app</li></ul><h3>Use an SDK to connect to the API</h3><p>The first thing that you need to do is make an authorized connection to the API. This is typically done with the help of an SDK (Software Development Kit) which is a library of code that we install and use to connect to the API. Our code uses the authentication keys that were provided when we <a href="https://medium.com/ringcentral-developers/developers-website-overview-part-2-7530d5ed8a20">created an app</a> on the RingCentral Developer’s site. They are called the Client Id and the Client Secret key. These keys are best stored in an environment file usually called .env. Here is a sample of what we place in that file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/1*GRbuUGGcPGFLXlKGYMRvAQ.png" /></figure><p>After we install the SDK, the SDK is for PHP in our case, we create a reusable function that will access the .env values to authenticate your code with the API. Remember these codes / keys are directly connected to an app that you create on the RingCentral developers platform and are unique to that app. If you had another app on the platform you would be given different key values. Also, note that in our case when we originally set up the app we chose a JWT style of authentication, which involves another, much longer key that is also generated on the RingCentral developer’s platform. Read <a href="https://medium.com/ringcentral-developers/how-to-create-a-jwt-token-5eee1a7a7357">this</a> article for details on JWT key creation.</p><p>Here is the code that creates a connection to the API. The first three lines give you access to the content of the .env file, then we create the connection to the API through the SDK syntax providing the client id, client secret, and URL path to the API. Since this is a re-usable function we do a quick test to see if we are already logged into the API and if not, we call the login method passing it the JWT value. If all goes well we then return the $controller array which contains a handle to the API</p><pre>function ringcentral_sdk() {<br>// Include Libraries<br>require(&#39;includes/vendor/autoload.php&#39;);<br>$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);<br>$dotenv-&gt;load();<br>$jwt_key = $_ENV[&#39;RC_JWT_KEY&#39;];<br>$sdk = new RingCentral\SDK\SDK(<br>$_ENV[&#39;RC_APP_CLIENT_ID&#39;],<br>$_ENV[&#39;RC_APP_CLIENT_SECRET&#39;],<br>$_ENV[&#39;RC_SERVER_URL&#39;]);<br>$platform = $sdk-&gt;platform();<br>// Login via API<br>if (!$sdk-&gt;platform()-&gt;loggedIn()) {<br>try {<br>$platform-&gt;login([&quot;jwt&quot; =&gt; $jwt_key]);<br>} catch (\RingCentral\SDK\Http\ApiException $e) {<br>$sdk = 0;<br>// exit(&quot;&lt;br/&gt;&lt;br/&gt;Unable to authenticate to platform. Check your RingCentral credentials. &lt;br/&gt;&lt;br/&gt;&quot;) ;<br>}<br>}<br>$controller = array(&#39;SDK&#39; =&gt; $sdk, &#39;platform&#39; =&gt; $platform);<br>return $controller;<br>}</pre><p>Now that we have authenticated access to the API for a specific app on the RingCentral platform we can perform tasks from within that app. This is where the authorization aspect comes into play. When the app is created you designate what part or parts of the API you want to use. You could be creating an app that sends out both SMS and Fax messages, or you could create an app that only sends content to Team Messenger. These authorizations are also called “Application Scopes”. The good news is that these scopes can be adjusted if you want to change the authorization of the app.</p><p>In our sample app here we will just be sending out an SMS message so the scope of the app is quite narrow. The scope in the app then must coincide with what is known as the API endpoint. This means that your code has to direct its request at a specific section of the API. In other words the scope and the endpoint have to match, and this is another aspect to the authorization process. If, as in our example, your app’s scope is for sending SMS messages and we provide an endpoint for sending a fax message then the authorization would fail.</p><p>Let’s look at the PHP code for sending an SMS message.</p><pre>function send_sms($to_mobile, $message) {<br>$controller = ringcentral_sdk();<br>$platform = $controller[&#39;platform&#39;];<br>$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);<br>$dotenv-&gt;load();<br>$from_mobile = $_ENV[&#39;RC_MOBILE_SENDING_NUMBER&#39;];<br>$message .= &quot; Reply STOP to opt out of future communication from this mobile number.&quot;;<br>$api_endpoint = &#39;/restapi/v1.0/account/~/extension/~/sms&#39;;<br>try {<br>$apiResponse = $platform-&gt;post($api_endpoint,<br>array(&#39;from&#39; =&gt; array(&#39;phoneNumber&#39; =&gt; $from_mobile),<br>&#39;to&#39; =&gt; array(array(&#39;phoneNumber&#39; =&gt; $to_mobile)),<br>&#39;text&#39; =&gt; $message,)<br>);<br>} catch (\RingCentral\SDK\Http\ApiException $e) {<br>// craft a friendly message here.<br>echo $e-&gt;getMessage();<br>}<br>}</pre><p>As you can see, the function starts with calling the SDK connecting function and then connects again to the .env file to pick up the SMS sending phone number. The $to_mobile value is passed into the function along with the text of the outgoing message. We add some boiler plate STOP information to the end of the message text and then set the value of the endpoint where we call the SMS portion of the API. Lastly, we call the post method on the API sending it the parameters that it needs.</p><p>To call the sms function you would simply have to use these few lines of code:</p><pre>$to_number = &quot;+19025551234&quot;;<br>$sms_message = &quot;This is a simple SMS message for you. &quot;;<br>send_sms($to_number, $sms_message);</pre><p>We put the post method call within a try/catch structure in case there are issues with the attempt to send the SMS message. For example, we could be using the wrong sending phone number, or the phone number we used does not have permission to send out SMS messages, or the app does not have the scope of sending SMS messages, or in the very rare case, that the RingCentral API is off-line. There could be many issues like this that we need to allow for and we can handle those more gracefully if we want to. See my article on <a href="https://medium.com/ringcentral-developers/handling-errors-and-timeouts-when-using-ringcentral-apis-78deede40ab7">error handling </a>for more details.</p><h3>Final Thoughts</h3><p>Authentication and authorization are the foundation of any secure API integration, and RingCentral’s platform is built with that in mind. RingCentral’s APIs use industry-standard authentication protocols and fine-grained authorization controls to ensure that every request is properly verified and scoped. Access tokens, permissions, and secure transport all work together to protect user data and system resources, so developers can build integrations with confidence that security is enforced at every layer of the API stack.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=49c059a9c9b8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/a-guide-to-authentication-and-authorization-with-ringcentral-apis-49c059a9c9b8">A Guide to Authentication and Authorization with RingCentral APIs</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Simple Guide to using the RingCentral API in Python Applications]]></title>
            <link>https://medium.com/ringcentral-developers/a-simple-guide-to-using-the-ringcentral-api-in-python-applications-5b9b750e501f?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/5b9b750e501f</guid>
            <category><![CDATA[sms]]></category>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[ringcentral-developer]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Tue, 07 Apr 2026 15:01:03 GMT</pubDate>
            <atom:updated>2026-04-07T15:01:03.630Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qdQGfxnz5C0zRgydl9spCQ.png" /></figure><p>Imagine you’re building an internal IT helpdesk tool in Python. When a high-priority ticket is created, you want to automatically send an SMS alert to an on-call engineer. Or maybe you’re developing a logistics dashboard that sends delivery status updates to customers.</p><p>In both cases, your Python application needs to communicate with the outside world; reliably and in real time. That’s where the RingCentral API comes in.</p><p>RingCentral’s platform allows Python applications to send SMS messages, make calls, access call logs, and more. In this guide, we’ll walk through how to integrate RingCentral APIs into a Python application, using the official Python SDK and practical examples. We will be sending out a simple SMS message, but the basic steps can all be expanded on for more complex scenarios once the foundation is properly laid.</p><h3>What You’ll Need Before You Start</h3><p>Before writing code, make sure you have:</p><ul><li>A RingCentral developer account, obtained here: <a href="https://developers.ringcentral.com/">https://developers.ringcentral.com</a></li><li>An app created in the RingCentral Developer Portal</li><li>Your Client ID, Client Secret, and Server URL</li><li>A RingCentral phone number enabled for SMS</li></ul><p>Once you have those, you’re ready to connect your Python app to RingCentral.</p><h3>Step 1: Install the RingCentral Python SDK</h3><p>The RingCentral SDK handles authentication, HTTP requests, and error handling so you don’t have to build everything from scratch.</p><p>Install it using pip:</p><pre>pip install ringcentral python-dotenv</pre><p>This adds the SDK to your Python environment so your app can communicate with RingCentral’s REST API. We are also installing the environment settings package that allows us to store our app credentials in a secure location. You can create a separate file called .env and load it with the following information:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/1*GRbuUGGcPGFLXlKGYMRvAQ.png" /></figure><p>We will pick up these values later in our code sample. In a production environment you would “hide” this file in a sub-folder and place it in .gitignore to protect these keys from unauthorized use.</p><p><strong>Step 2: Authenticate Your Application</strong></p><p>RingCentral uses OAuth 2.0 for authentication. Your app must log in before making API calls so we use the dotenv approach to manage that information. Create a python code file called rc_app.py and start it with the following code:</p><pre>import os, sys, time<br>from dotenv import load_dotenv<br>from ringcentral import SDK<br>load_dotenv()<br>CLIENTID = os.environ.get(&#39;RC_APP_CLIENT_ID&#39;)<br>CLIENTSECRET = os.environ.get(&#39;RC_APP_CLIENT_SECRET&#39;)<br>SERVERURL = os.environ.get(&#39;RC_SERVER_URL&#39;)<br>JWTKEY = os.environ.get(&#39;RC_JWT_KEY&#39;)<br>FROMNUMBER = os.environ.get(&#39;RC_MOBILE_SENDING_NUMBER&#39;)<br>ENDPOINT = os.environ.get(&#39;RC_ENDPOINT&#39;)</pre><p>This loads the values that are stored in the .env file into our code and stores them in appropriately named variables. Next we want to create a connection to the RingCentral SDK using our credentials. Then we set up our specific parameters for the SMS message that we want to send and load that into the bodyParams array variable.</p><pre>rcsdk = SDK(CLIENTID, CLIENTSECRET, SERVERURL)<br>platform = rcsdk.platform()<br>platform.login( jwt=JWTKEY)<br># Set Params<br>bodyParams = {<br> &#39;from&#39;: {&#39;phoneNumber&#39;: FROMNUMBER },<br> &#39;to&#39;: [ {&#39;phoneNumber&#39;: &#39;+19025551234&#39; } ],<br> &#39;text&#39;: &#39;My first RingCentral Python SMS&#39;,<br>}</pre><p>Lastly, all we have to do is send the end point value and the parameter array to the API with the post method. Optionally, we can send a little note to the display that the SMS was sent out successfully.</p><pre>platform.post(ENDPOINT, bodyParams)<br>print(&quot;SMS sent successfully&quot;)</pre><p>Our SMS message should look like the following.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/337/1*luqDu73QWEgPaLJSWm0LxQ.png" /></figure><p>Our on screen display should look like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/625/1*RKGTJ7xP4n9RLch7R95C-w.png" /></figure><p>For more robust coding you can put the post call within a try block and trap any errors that may be returned by the API. You can also store the response object from a successful post and display any of that supporting information as needed. The try block could look like this.</p><pre>try:<br> response = platform.post(ENDPOINT, bodyParams)<br> jsonObj = response.json()<br> print (&quot;SMS sent successfully. The Message id is : &quot; + str(jsonObj.id))<br>except Exception as e:<br> print (e.message)</pre><p>And the output on success would be</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/628/1*wxivcpw51BJ_um9mPj2ZjA.png" /></figure><p>The output for an error would be a lot more involved and hopefully be helpful; pointing you to the cause of the error. It would look something like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AI5-YgLzg5T43EZKaWI1EQ.png" /></figure><p>You could clean this up substantially by storing the error code and message from the object into variables and sending those to the display. The code would look like the following and the displayed output follows that.</p><pre>except Exception as e:<br># RingCentral API errors land here<br> error_data = e.api_response().json_dict()<br>error_code = error_data.get(&quot;errorCode&quot;, &quot;Unknown&quot;)<br> error_message = error_data.get(&quot;message&quot;, &quot;No message returned&quot;)<br>print(&quot;An error occurred trying to send an SMS. &quot;)<br> print(f&quot;Error Code: {error_code} Message: {error_message}&quot;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/626/1*28sUeS2Ph97vMZDxFkzEXA.png" /></figure><h3>Final Thoughts</h3><p>Integrating RingCentral APIs into Python applications opens the door to powerful communication workflows; from SMS alerts and voice calls to reporting and automation. By using the official Python SDK and planning for authentication you can build systems that are not just functional, but production-ready.</p><p>Whether you’re sending customer notifications, internal alerts, or building analytics dashboards, these foundations will help your Python app communicate with confidence.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5b9b750e501f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/a-simple-guide-to-using-the-ringcentral-api-in-python-applications-5b9b750e501f">A Simple Guide to using the RingCentral API in Python Applications</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Use RingCentral APIs to Log Call Analytics in Your CRM]]></title>
            <link>https://medium.com/ringcentral-developers/how-to-use-ringcentral-apis-to-log-call-analytics-in-your-crm-045231fb41ac?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/045231fb41ac</guid>
            <category><![CDATA[crm]]></category>
            <category><![CDATA[ringcentral-developer]]></category>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[analytics]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Tue, 31 Mar 2026 15:01:02 GMT</pubDate>
            <atom:updated>2026-03-31T15:01:02.525Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CCT3NUCsStV_WdjokBFKYQ.png" /></figure><p>If your team uses RingCentral for voice calls and a CRM (like Salesforce, HubSpot or Zoho) to manage customer records, capturing detailed call information in your CRM can be a real game-changer. Call analytics help you understand agent performance, track engagement, and automate workflows like follow-up calls or calculating billing.</p><p>There are two main ways to work with RingCentral’s call data.</p><p>Firstly, the Call Log section of the API gives you the raw call detail records with timestamps, direction (in bound or out bound), duration, result, and even recordings (if available). It’s ideal if you want to pull every completed call into your CRM’s activities.<br> <br>Secondly, the Business Analytics portion of the API provides aggregated metrics, like daily call volumes or average handle time; useful for dashboards and performance reporting.</p><p>In this guide we will walk through:</p><ul><li>Authenticating with RingCentral in PHP</li><li>Fetching call logs with the API</li><li>Inserting those logs into your CRM</li><li>Pulling analytics summaries for reporting</li></ul><p>Everything is demonstrated with the official RingCentral PHP SDK.</p><h3>Fetching Call Logs and Logging to CRM</h3><h3>What the Call Log API Provides</h3><p>RingCentral’s call log endpoint returns completed calls with useful metadata like caller and callee phone numbers, call start / end timestamps, call duration and result (answered, voicemail, missed, etc.), and recording URLs if available.</p><p>The basic REST endpoint is:</p><pre>$endpoint = &quot;/restapi/v1.0/account/~/extension/~/call-log&quot;;</pre><p>Here is a PHP snippet that pulls call logs for the past 15 days and then shows how you might iterate over them to send to a CRM. Depending on your call volume you may want to limit the time frame to each day (-1 day).</p><pre>$endpoint = &quot;/restapi/v1.0/account/~/extension/~/call-log&quot;;<br>$params = [<br>&#39;dateFrom&#39; =&gt; date(&#39;c&#39;, strtotime(&#39;-15 day&#39;)),<br>&#39;dateTo&#39; =&gt; date(&#39;c&#39;),<br>];<br>$response = $platform-&gt;get($endpoint, $params);<br>$data = $response-&gt;json();<br>$records = count($data-&gt;records);<br>echo_spaces(&quot;call records count&quot;, $records, 2);<br>foreach ($data-&gt;records as $call) {<br> echo_spaces(&quot;call session ID&quot;, $call-&gt;sessionId);<br> echo_spaces(&quot;call direction&quot;, $call-&gt;direction);<br> echo_spaces(&quot;call from&quot;, $call-&gt;from-&gt;name);<br> echo_spaces(&quot;call from #&quot;, $call-&gt;from-&gt;phoneNumber);<br> if (!empty($call-&gt;to-&gt;name)) {<br> echo_spaces(&quot;call to&quot;, $call-&gt;to-&gt;name);<br> } else {<br> echo_spaces(&quot;no call to name&quot;);<br> }<br> echo_spaces(&quot;call to #&quot;, $call-&gt;to-&gt;phoneNumber);<br> echo_spaces(&quot;call type&quot;, $call-&gt;type);<br> echo_spaces(&quot;call Start time&quot;, $call-&gt;startTime);<br> echo_spaces(&quot;call length&quot;, $call-&gt;duration);<br> if (!empty($call-&gt;recording-&gt;contentUri)) {<br> echo_spaces(&quot;call recording&quot;, $call-&gt;recording-&gt;contentUri);<br> } else {<br> echo_spaces(&quot;no recording&quot;);<br> }<br> echo_spaces(&quot;call result&quot;, $call-&gt;result, 1);<br> //echo_spaces(&quot;call object&quot;, $call, 1);<br>}</pre><p>This foreach loop extracts fields from each call log and displays them on the browser. This is for demonstration purposes, you might not do this if you were moving the data directly into your CRM. The above code would produce output like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/754/1*zIb8mCMS5V0wZ1s21zX5Bw.png" /></figure><p>You could then take those call values and connect to your CRM API, inserting them into that platform. The last line of the above code that is commented out would show you the whole call object if you wanted to collect some other information that I have not highlighted here. You can take that additional information into your CRM as well, if there is space for it. The full object structure looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/905/1*ie3ygPPOL1_yxYKnFrQ9bw.png" /></figure><h3>Recording URLs</h3><p>If a call has a recording (the call was recorded during the call as opposed to a voicemail), RingCentral’s call log includes a recording object so you can test to see if a recording of a particular call was made:</p><pre>if (!empty($call-&gt;recording-&gt;contentUri)) {<br> echo_spaces(&quot;call recording&quot;, $call-&gt;recording-&gt;contentUri);<br>} else {<br> echo_spaces(&quot;the call was not recorded&quot;);<br>}</pre><p>Your CRM records can then be linked to the audio file for playback by storing the URL.</p><h3>Pulling Analytics with RingCentral Business Analytics API</h3><p>If you want <strong>aggregated insights</strong>, not just individual call records, the Business Analytics API is the portion to use. This API gives you counts and durations broken down by timeframes like daily, weekly, or monthly. Typical analytics use cases include cumulative counts for daily inbound vs outbound calls, average handle time per user, and peak call hours.</p><p>Note: your RingCentral app that your code uses to authenticate will have to have “Analytics” as part of its scope. The Analytics endpoints use a POST body to specify the time range and grouping. Here is an example:</p><pre>$endpoint = &quot;/analytics/calls/v1/accounts/~/aggregation/fetch&quot;;<br>$analyticsBody = [<br>&#39;grouping&#39; =&gt; [<br>&#39;groupBy&#39; =&gt; &#39;Users&#39;,<br>],<br>&#39;timeSettings&#39; =&gt; [<br>&#39;timeZone&#39; =&gt; &#39;America/Los_Angeles&#39;,<br>&#39;timeRange&#39; =&gt; [<br>&#39;timeFrom&#39; =&gt; &#39;2025–09–01T06:07:00.000Z&#39;,<br>&#39;timeTo&#39; =&gt; &#39;2026–02–02T08:20:00.000Z&#39;,<br>],<br>],<br>&#39;responseOptions&#39; =&gt; [<br>&#39;counters&#39; =&gt; [<br>&#39;allCalls&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Average&#39;,<br>&#39;aggregationInterval&#39; =&gt; &#39;Month&#39;,<br>],<br>&#39;callsByDirection&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Max&#39;,<br>&#39;aggregationInterval&#39; =&gt; &#39;Week&#39;,<br>],<br>&#39;callsByOrigin&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Sum&#39;,<br>],<br>&#39;callsByResponse&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Min&#39;,<br>&#39;aggregationInterval&#39; =&gt; &#39;Day&#39;,<br>],<br>&#39;callsSegments&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Average&#39;,<br>&#39;aggregationInterval&#39; =&gt; &#39;Hour&#39;,<br>],<br>&#39;callsByResult&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Min&#39;,<br>&#39;aggregationInterval&#39; =&gt; &#39;Month&#39;,<br>],<br>&#39;callsByCompanyHours&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Min&#39;,<br>&#39;aggregationInterval&#39; =&gt; &#39;Hour&#39;,<br>],<br>&#39;callsByActions&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Min&#39;,<br>&#39;aggregationInterval&#39; =&gt; &#39;Hour&#39;,<br>],<br>&#39;callsByType&#39; =&gt; [<br>&#39;aggregationType&#39; =&gt; &#39;Min&#39;,<br>&#39;aggregationInterval&#39; =&gt; &#39;Hour&#39;,<br>],<br>],<br>]<br>];<br>try {<br>$response = $platform-&gt;post($endpoint, $analyticsBody);<br>$analyticsData = $response-&gt;json();<br>$records = count($analyticsData-&gt;data-&gt;records);<br>echo_spaces(&quot;call records count&quot;, $records, 1);<br>foreach ($analyticsData-&gt;data-&gt;records as $record) {<br>// echo_spaces(&quot;Record name&quot;, $record-&gt;info-&gt;name);<br>if ($record-&gt;info-&gt;name == &quot;Peter MacIntyre&quot;) {<br>echo_spaces(&quot;Record details for &quot;, $record-&gt;info-&gt;name, 1);<br>// echo_spaces(&quot;Record object for Peter MacIntyre&quot;, $record);<br>echo_spaces(&quot;Extension Number&quot;, $record-&gt;info-&gt;extensionNumber);<br>echo_spaces(&quot;Number of inbound calls&quot;, $record-&gt;counters-&gt;callsByDirection-&gt;values-&gt;inbound);<br>echo_spaces(&quot;Number of outbound calls&quot;, $record-&gt;counters-&gt;callsByDirection-&gt;values-&gt;outbound);<br>}<br>}<br>} catch (\RingCentral\SDK\Http\ApiException $e) {<br>echo_spaces(&quot;Error code&quot;, $e-&gt;getCode());<br>echo_spaces(&quot;Error message&quot;, $e-&gt;getMessage());<br>// echo_spaces(&quot;Error Object&quot;, $e);<br>throw $e;<br>}</pre><p>This code produces the following object output, ahead of the objects, I send out a total count to the browser of all the records so that I can gauge my overall volume.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/444/1*f_utmSEAq_KnuCuU3NneTQ.png" /></figure><p>You can then fine tune the provided information and select the specific information that you are interested in. Here I am sending out specific data of the count of the inbound calls and the outbound calls for a selected caller, me.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/248/1*89dWADuI9R7FAOD5Ud6Low.png" /></figure><p>You can also manipulate the resulting summary data by adjusting the responseOptions values. To see all the combinations available, check out the documentation <a href="https://developers.ringcentral.com/api-reference/Business-Analytics/analyticsCallsAggregationFetch">here</a> and <a href="https://developers.ringcentral.com/guide/analytics/aggregate">here</a>. This can all provide a dataset of aggregated metrics you can present in dashboards or store in CRM custom. objects.</p><h3>Closing Thoughts</h3><p>Integrating RingCentral’s call data into your CRM unlocks better visibility into your team’s communication activities. The Call Log API gives you detailed records you can map directly to CRM activities, while the Business Analytics API helps you generate custom dashboards and insight reports automatically.</p><p>Once you have authenticated your PHP backend with the RingCentral SDK, you can retrieve, transform, and push call events into your CRM’s activity history with relatively few lines of code, making your CRM the single source for customer interactions and performance analytics.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=045231fb41ac" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/how-to-use-ringcentral-apis-to-log-call-analytics-in-your-crm-045231fb41ac">How to Use RingCentral APIs to Log Call Analytics in Your CRM</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Test and Debug workflows in Workflow Builder]]></title>
            <link>https://medium.com/ringcentral-developers/test-and-debug-workflows-in-workflow-builder-12a85c6944e0?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/12a85c6944e0</guid>
            <category><![CDATA[ringcentral]]></category>
            <category><![CDATA[workflow]]></category>
            <category><![CDATA[ringcentral-developer]]></category>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[workflow-builder]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Tue, 03 Mar 2026 18:01:02 GMT</pubDate>
            <atom:updated>2026-03-03T18:01:01.915Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*smZqL4uebVQtYyWTmBvqpg.png" /></figure><p>RingCentral’s Workflow Builder is nearing GA (General Availability). This is exciting news as it will imbue RingCentral voice, SMS, video, and team messaging with automated processes that you can create without any programming knowledge.</p><p>In this tutorial, I’ll show you how you can test and debug your workflows.</p><p>To get started, after you log into the RingCentral desktop application, or its equivalent website interface, you should see “Workflows” on the left panel. If it is not there, look under “More” also on the left panel. You can drag and drop the icon to the main left panel if you would rather not have to access it under the “More” option.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/84/1*awFXNyu4MfiWK8LY6CT5_A.png" /></figure><p>When clicked you will be taken to the dashboard area that lists all your existing workflows, if any.</p><p>It should look similar to the following image.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/941/1*nmYWewtFHCOVMJIQG4TiaQ.png" /></figure><p>In our example [1], we are wanting to test the “SMS Product Support Request” workflow. This workflow was built to respond to a received SMS message if it contained the text of “support request” and then if it contained the text of “SMS granted”. It is shown in the figure below. In the first condition <strong>[1]</strong>, if the incoming SMS text contains the words “support request” or “help”, we want to post a note to a Team Messenger chat group <strong>[2]</strong> with the full text of the received SMS.</p><p>Hopefully, the incoming text will be descriptive and concise enough that the support team can lend assistance. In our workflow the group receiving the note about a new support request is called “Messenger Tests”, but this can be updated to any individual or group chat that the account has access to. The next condition <strong>[3]</strong> is another query on the incoming text to see if the string “SMS granted” is also contained within it. If the case is true <strong>[4],</strong> then we send a courteous SMS message back to the sender telling them that the message was received and that it would be worked on as soon as possible. We take no action on the false conditions of either case.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/232/1*HNGMtfQjXrNb16SrqmTCfg.png" /></figure><h3>Testing a workflow</h3><p>Once you have your workflow designed to a point where you want to test it, you can save it and then test it by clicking the “Simulate” button at the top right of the design area. The “Simulate” pop-up screen will display and you can enter in any sample information that the workflow needs. In our case we need to provide a sender’s mobile number [1], the sender’s name [2], and the body of the text message [3] that we want to send. We can change the sender’s name if we like, but “John Doe” is fine for testing purposes. The test screen should look like the following.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/539/1*o7sEBxRULXNWO3TEOniGKw.png" /></figure><p>If you look at the logical flow of the workflow you will see that based on the content of the message text. This should do nothing and fall down through the initial “false” side of the process. Here is the result screen of the test:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/555/1*LPYl9p7cnW_TgDr2ODa5Xg.png" /></figure><p>The areas of the workflow that were tested are listed with what they were testing for (our search conditions) and what they were testing against (the incoming SMS message). Then the results of each of the tests are shown (pass: true/false). We can click “Simulate again” to perform more tests on different scenarios. As we perform other tests on different text message content, we can see the simulated results each time.</p><p>Following are the results of another test SMS that contains only the text “Help SMS granted”. This is the content that we are testing for in each branch so both conditions should prove to be true and we should get a message sent to the chat group as well as a response message to the sender.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/544/1*DzoW-7GeTJ-_CcthGz4jGA.png" /></figure><p>If any of the process steps fail, for example a bad phone number was used, then the error will be identified as accurately as possible by the simulation environment.</p><p>All of the above tests have been performed on the workflow while it was being built or edited in the workflow design area. After you complete your workflow and “Enable” it, there is another way to see the results of its activities. <strong>RingCentral Workflow Builder</strong> keeps a results log of your workflow when it runs. You can view your logs on the dashboard screen by clicking on the history link. The following image shows this for you.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/442/1*Fi2aIbu24XroK1vAtz7MLg.png" /></figure><p>You should then see a log of activity that your workflows have generated so far. Here is a screen shot of that history page. If there were errors, you should see them listed in the status column.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/941/1*nmYWewtFHCOVMJIQG4TiaQ.png" /></figure><p>If you click on the status word of “Successful” or “Failed” you will see the details of the workflow when it last ran. An example of the “failed” log look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/631/1*-rav93GpzlFlVvL52Pu85g.png" /></figure><p>RingCentral Workflow Builder is a great time saver when your workflows perform as desired. Workflows can grow to be quite complex and sometimes hard to follow so it is a good idea to test your workflows thoroughly before they are enabled. Be sure to also occasionally check the log page to ensure that your workflow is running at its best.</p><p>To learn more about RingCentral Workflow Builder, and see samples of other workflows you can build, visit our <a href="https://developers.ringcentral.com/automator">Workflow Builder Developer page</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=12a85c6944e0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/test-and-debug-workflows-in-workflow-builder-12a85c6944e0">Test and Debug workflows in Workflow Builder</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Real-time Event Notifications with RingCentral’s API]]></title>
            <link>https://medium.com/ringcentral-developers/real-time-event-notifications-with-ringcentrals-api-b11cf34eae6d?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/b11cf34eae6d</guid>
            <category><![CDATA[events]]></category>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[sdk]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[ringcentral-developer]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Tue, 24 Feb 2026 17:56:01 GMT</pubDate>
            <atom:updated>2026-02-24T17:56:01.445Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*08YuVxwJSxDqnGQJJiMQEA.png" /></figure><p>There are often times when you are using the RingCentral API within your applications that you would like to know when an event has occurred, such as receiving a voicemail, SMS, FAX, or page. As these events never occur on a set schedule, the RingCentral platform has to make your applications aware of the event so you can act on it. The event notifications aspect of the API is where you want to start. In this article, I will show you how to make use of this API endpoint and how you can leverage it to provide the information that you want from these types of events. This can help with keeping track of response times in the case of customer support, for example.</p><p>I have created a small app that you can use as a starting point and the code is located <a href="https://github.com/pbmacintyre/Real-time-Event-Notifications">here</a>. In this app, I created webhooks that listen for these types of events and can be programmed to react in a desired fashion like sending out a Team Messaging notification or an SMS message. Let’s get started by looking at what a webhook is and why we need them in this case.</p><h3>Webhooks</h3><p>A webhook, also known as a subscription, is a notification request event that you can place on the RingCentral API server requesting that it notify you when specified events occur. For example, when someone sends you a fax message you can tell the RingCentral API server to watch for these incoming types of communication and let you know about it. There are a few rules about how you can create a webhook in terms of what it needs to be able to send you the event notifications and they are:</p><ol><li>You need to have a code file on your own server that it can communicate with.</li><li>Your code file cannot be behind a firewall.</li><li>The web server that your own code sits on must support TLS 1.2 or higher.</li><li>Your own web server must be able to respond within 3000 milliseconds.</li><li>The web server must respond with an HTTP 200 OK code.</li><li>The web server must respond with a valid validation token header.</li><li>The web server must not respond with anything larger than 1024 bytes.</li></ol><p>When you send a request to the API to create a webhook the target file has to exist as a minimum, then all the other items on the above list will need to be in place before the webhook can start to send you any notifications. Let’s look at the code to get a better idea of how this is all accomplished.</p><pre>$api_call = $controller[&#39;platform&#39;]-&gt;post(&#39;/subscription&#39;,<br> array(<br> &quot;eventFilters&quot; =&gt; $event_filters,<br> &quot;expiresIn&quot; =&gt; &quot;315360000&quot;,<br> &quot;deliveryMode&quot; =&gt; array(<br> &quot;transportType&quot; =&gt; &quot;WebHook&quot;,<br> // need full URL for this to work as well<br> &quot;address&quot; =&gt; $subscription_url, )<br> )<br> );</pre><p>Here is the basic creation statement that we send to the RingCentral API with a post method call. The endpoint is “/subscription” and the parameters are sent within an array structure.</p><p>The “eventFilters” are the items that you want to be notified about. More on that later. The “expiresIn” option can be left as a default of seven days but can be set as high as the number shown above which equates to almost 10 years. The number is in seconds.</p><p>The “deliveryMode” is also in an array structure and we send over the type of subscription we are creating, “WebHook”, and the “address” which is the URL of our code file that the webhook will be running if and when an event occurs. I am using a few variables here and we will explore those next.</p><h3>eventFilters</h3><p>The “eventFilters” value that is being sent to the subscription post method is an array of all the events that you want this webhook to react to. In our code, we test to see if a webhook of the requested type already exists and we therefore don’t create one if the case is true. If we do need to create a webhook for the designated event type then we have to add that request to the $event_filters array. The code for creation of an incoming SMS notice will look like this and naturally precedes the code above.</p><pre>$event_filters[] = &quot;/restapi/v1.0/account/~/extension/~/message-store?type=SMS&amp;direction=Inbound&quot;;</pre><p>So we have to set the type and the direction of the filter as query string options on the message-store endpoint. There are a total of 8 endpoints of this nature that you can be notified about. They are SMS, Voicemail, Fax, and Pager; each has an inbound and outbound value. In our app we only want to be notified of incoming (inbound) events.</p><h3>Subscription URL</h3><p>The other variable that I am using is the code file that I want the webhook to call when an event actually occurs. I set this value in my .env environment file and call it into existence earlier in the code. The url value in my case is:</p><pre>RC_WEBHOOK_URL_SUFFIX = &#39;/real_time_events/process_webhooks.php&#39;</pre><p>And I concatenate this with the full url path to my application host with this line of code:</p><pre>$subscription_url = &quot;https://&quot; . $_SERVER[&#39;HTTP_HOST&#39;] . $_ENV[&#39;RC_WEBHOOK_URL_SUFFIX&#39;];</pre><p>So my file called process_webhooks.php has to exist on my server, in the folder specified, not behind a firewall, etc. in order to have the webhook created when I call this API endpoint.</p><h3>The application interface</h3><p>Our application’s home page looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/733/1*lvbSDUggkHCfstL1MnR_KA.png" /></figure><p>Here we can request the creation of the webhook notification events with the checkboxes and also list any existing webhooks should we forget which ones we already have active. If I ask for the creation of a Voicemail and SMS webhook and one already exists for Voicemail, I will see this on the screen.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/728/1*I_ArPUFGAuVqgdOsWjE4uw.png" /></figure><p>This is all done within the create_webhook.php code file after I place the values of the checkboxes into the $_SESSION, so be sure to explore that for full coverage of the creation of a webhook.</p><h3>Show Existing Webhooks</h3><p>The other link I have on my home screen is a call to list_kill_webhooks.php. This is a code file that checks to see if there are any existing webhooks and then displays them to the browser. I also have a few lines of code in this file that by all rights should be in its own code but I have it there for convenience. It is code that will delete an existing webhook by providing the subscription Id.</p><p>The bulk of the code file is as follows:</p><pre>$controller = ringcentral_sdk();<br>// list subscriptions then optionally delete the one we don&#39;t want.<br>try {<br> $response = $controller[&#39;platform&#39;]-&gt;get(&quot;/subscription&quot;);<br> $subscriptions = $response-&gt;json()-&gt;records;<br>} catch (Exception $e) {<br> echo_spaces(&quot;catch error&quot;, $e-&gt;getMessage());<br>}<br>foreach ($subscriptions as $subscription) {<br>// echo_spaces(&quot;Subscription Info&quot;, $subscription, 2);<br>echo_spaces(&quot;Subscription ID&quot;, $subscription-&gt;id);<br> echo_spaces(&quot;Creation Time&quot;, $subscription-&gt;creationTime);<br> echo_spaces(&quot;Expires&quot;, $subscription-&gt;expirationTime);<br> echo_spaces(&quot;Webhook URI&quot;, $subscription-&gt;deliveryMode-&gt;address);<br> echo_spaces(&quot;Webhook transport type&quot;,<br> $subscription-&gt;deliveryMode-&gt;transportType);<br> foreach ($subscription-&gt;eventFilters as $event_url) {<br> $query = parse_url($event_url, PHP_URL_QUERY);<br> parse_str($query, $params);<br> echo_spaces(&quot;Event Type&quot;, $params[&#39;type&#39;]);<br> }<br> echo_spaces(&quot;Event Filter(s) URI&quot;, $subscription-&gt;eventFilters);<br>if ($subscription-&gt;id == &quot;f7a15b17–3339-xxxxxxx-b2e8e96d28a3&quot;) {<br> $response = $controller[&#39;platform&#39;]-&gt;delete<br> (&quot;/restapi/v1.0/subscription/$subscription-&gt;id&quot;);<br> echo_spaces(&quot;Subscription ID Deleted&quot;, $subscription-&gt;id, 1);<br> }<br>}</pre><p>First we connect to the SDK receiving a $controller handle. Then with the SDK connection we call the get method to the subscription endpoint to be given all the currently active subscriptions. This information is stored in the records array and we place it in our local variable called $subscriptions. Then we traverse that array listing the information that is available for each existing webhook. We show the id, creationTime, expirationTime, and so on. The commented line above will list all the elements of the array if you ever want to see all the information that is available in that array and maybe want to display additional webhook information.</p><p>Within that array is another array of the eventFilters (individual events) that are part of the individual webhook. So for example, we could have one webhook that is watching for both Voicemail and SMS inbound events. I tease out the event type from the provided URL of the event then show the full event URL for confirmation.</p><p>Lastly, I check on an individual subscription id to see if it is provided to my code and then I delete it. This is a manual process that I need to update my code file each time and then re-run it in order for the delete process to actually be accomplished. I only provide it here as an example of how a subscription can be removed.</p><p>The output of the above code, without a deletion request would look like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/729/1*O5gsDB-rN2RWwId5usMPVg.png" /></figure><h3>Processing the event(s)</h3><p>The last piece of this puzzle is what you want your code to do when the created webhook(s) actually record an event and notify you. We have the code file already designated when we created the webhook. In our case it is called process_webhooks.php.</p><p>Let’s look at the code in sections. The first significant step is this.</p><pre>$hvt = isset($_SERVER[&#39;HTTP_VALIDATION_TOKEN&#39;]) ? $_SERVER[&#39;HTTP_VALIDATION_TOKEN&#39;] : &#39;&#39;;<br>if (strlen($hvt) &gt; 0) {<br> header(&quot;Validation-Token: {$hvt}&quot;);<br>}<br>$incoming = file_get_contents(&quot;php://input&quot;);<br>// use following to send incoming event data to a file for visual review<br>file_put_contents(&quot;received_EVENT_payload.log&quot;, $incoming);</pre><p>Here we prepare the validation token to be matched with the token that is coming from the event notification that RingCentral is providing. Once matched we can continue with the code. We take the incoming data and store it into a variable called $incoming and then optionally we store it on our server with the file name of received_EVENT_payload.log. A sample of the incoming data would look like this.</p><pre>{&quot;uuid&quot;:&quot;5710691562723757251&quot;,&quot;event&quot;:&quot;/restapi/v1.0/account/5499917/extension<br>/62177786016/message-store&quot;,&quot;timestamp&quot;:&quot;2025–08–28T18:20:28.565Z&quot;,<br>&quot;subscriptionId&quot;:&quot;2b95d0da-xxx-4fb6–82c3–38d26fa5c498&quot;,&quot;ownerId&quot;:<br>&quot;621555486016&quot;,&quot;body&quot;:{&quot;accountId&quot;:5414445017,&quot;extensionId&quot;:621555486016,<br>&quot;lastUpdated&quot;:&quot;2025–08–28T18:20:18.543Z&quot;,&quot;changes&quot;:[{&quot;type&quot;:&quot;SMS&quot;,<br>&quot;newCount&quot;:1,&quot;updatedCount&quot;:0,&quot;newMessageIds&quot;:[3099897302017]}]}}</pre><p>The important part of this data is what comes after the “changes” designation. Here we see that the event is an SMS message and we are provided with the message id as well if we want to do anything further with it.</p><p>Back to the code, after a few data integrity checks we see this.</p><pre>// get the type of event<br>$incoming_event_type = <br> htmlentities($incoming_data-&gt;body-&gt;changes[0]-&gt;type);<br>// handle the type of the event with notifications or SMS or whatever you want.<br>echo_spaces(&quot;Event Type&quot;, $incoming_event_type, 1);<br>echo_spaces(&quot;Event Info&quot;, $incoming_data-&gt;body-&gt;changes, 1);</pre><p>I draw out the type of the event from the changes[0]-&gt;type section and then simply show the information on the browser.</p><p>I use the <a href="https://www.postman.com/">postman</a> site to test this code. It’s a great way to play with the outcome of your notification code that is usually non-visual. The echo statements can be seen in the postman “preview” area when you send the “Body” to the specified URL. It essentially mimics a notification call that the webhook would be doing. Here you can see the output of a new fax notification showing the event type and the event info as displayed by the echo statements.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/723/1*kZvzHns94L3MTwJCiHlsSQ.png" /></figure><p>To make it truly a notification you could use the API to send yourself an SMS when a new fax or voicemail came in, or send some information to a Team Messenger group. There are a lot of options to consider here, but the point is that you can react to almost any event that you want with this API. You can even take some notifications from the audit trail system and handle them in a similar way. All you have to do is specify the event type when creating a webhook and have access permission to the audit trail system (which is usually at least admin level access).</p><h3>Developer App Setup</h3><p>The only thing left to make note of is how to set up the developer app so that you would have the correct access to the message-store and subscription endpoints. The app scope for the message store is called “Read Messages” and the scope for webhooks is “Webhook Subscriptions”.</p><p>Additionally, if you wanted to send out SMS, or Team Messaging notifications when events occur you would have to add “SMS” and “Team Messaging” to the scope of your application. Don’t forget to add the client id, client secret, and JWT codes to your .env file when you have those created as part of your application development environment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/718/1*a4g-f8hz4JbjQhv8U-vTyQ.png" /></figure><p>That is all there is to getting event notifications and handling them when they occur. I hope you can make use of these code examples and maybe leverage it to make your own applications more robust when interacting with the RingCentral API.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b11cf34eae6d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/real-time-event-notifications-with-ringcentrals-api-b11cf34eae6d">Real-time Event Notifications with RingCentral’s API</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Accessing Contact Information with RingCentral’s API]]></title>
            <link>https://medium.com/ringcentral-developers/accessing-contact-information-with-ringcentrals-api-a6fc58988376?source=rss----8ea22f7ec634---4</link>
            <guid isPermaLink="false">https://medium.com/p/a6fc58988376</guid>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[ringcentral-developer]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[ringcentral]]></category>
            <dc:creator><![CDATA[Pbmacintyre]]></dc:creator>
            <pubDate>Wed, 11 Feb 2026 16:52:41 GMT</pubDate>
            <atom:updated>2026-02-11T16:52:39.965Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5_ZJ1pDubjwVy23jFPgRkA.png" /></figure><p>As you might be aware every RingCentral account includes multiple contact lists, but did you know that they can all be accessed within an API? Through the API, contact lists can be shared with other applications or downloaded for processing. Although there are several categories of contacts that you can see on the Contacts tab within the RingCentral app, we will focus on the two most used categories: <strong>Company </strong>and <strong>Personal.</strong></p><p>The first group of contacts that we will be looking at is a collection of Company contacts or internal contacts. These are contacts that are input from your company’s LDAP or directory server. The API provides read-only company contacts and cannot add new contacts to it. The second group of contacts that you have access to are personal contacts. This is a list of contacts that you can control. This is a little different than a list of personal contacts that is accessed through your Google or Apple accounts. These are contacts that you enter yourself into the RingCentral platform.</p><p>If you are using Team Messenger you should be able to see these contact lists in the Contacts section.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/427/1*ydhgNZr3nbp3kWeeZGnBzg.png" /></figure><p>In this article, I will show you how to access these lists and some of the things that you can do with the returned information. I have created a small app in PHP that I will use for these demonstrations. Be sure to add “ReadAccounts” and “ReadContacts” as app scopes to your RingCentral Developers app if you are following along with the code. The “ReadAccounts” scope will be used for retrieving the Company contact information and “ReadContacts” will be used to access the personal contact information. The code base can be found on GitHub <a href="https://github.com/pbmacintyre/Contacts-API-Blog-app">here</a>.</p><h3>Company Contacts API</h3><p>We will start with the company contacts listing. As mentioned above, we can only retrieve the information through the API and not add any new records. Our landing page then only offers a submit button to bring out that data. The home page looks like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/909/1*DyGVTx1Qcim8qVSj7cm7ZQ.png" /></figure><p>Here, we only want to click the “Retrieve Company Contacts” button, the other form parts are for the Guest Contacts, so ignore those for now.</p><p>I wrote the code for bringing in the Company contacts and encased it within a function that is called when the button is clicked. It looks like the following.</p><pre>function get_company_contacts() {<br> $controller = ringcentral_sdk();<br> $platform = $controller[&#39;platform&#39;];<br>$endpoint = &quot;/restapi/v1.0/account/~/directory/entries&quot;;<br>try {<br> $resp = $platform-&gt;get($endpoint);<br> $records = $resp-&gt;json()-&gt;records; // array of objects<br>if (count($records) &gt;= 1) {<br>// usort($records, function ($a, $b) {<br>// $lastA = $a-&gt;lastName ?? &#39;&#39;;<br>// $lastB = $b-&gt;lastName ?? &#39;&#39;;<br>// return strcmp($lastA, $lastB);<br>// });<br> foreach ($records as $record) {<br> // echo_spaces(&quot;Response record&quot;, $record);<br> if ($record-&gt;status == &#39;Enabled&#39;) {<br> echo_spaces(&quot;Contact ID&quot;, $record-&gt;id);<br> echo_spaces(&quot;Contact Status&quot;, $record-&gt;status);<br> echo_spaces(&quot;Contact name&quot;, $record-&gt;firstName . &#39; &#39; .<br> $record-&gt;lastName);<br> if (!$record-&gt;jobTitle) {<br> echo_spaces(&quot;No Job Title listed&quot;);<br> } else {<br> echo_spaces(&quot;Contact Job Title&quot;,$record-&gt;jobTitle);<br> }<br> echo_spaces(&quot;Contact account id&quot;,$record-&gt;account-&gt;id);<br> echo_spaces(&quot;Contact extension #&quot;,<br> $record-&gt;extensionNumber);<br> if ($record-&gt;profileImage) {<br> $img_account = $record-&gt;account-&gt;id;<br> $img_extension = $record-&gt;id;<br> $img_endpoint =<br>&quot;/restapi/v1.0/account/$img_account/extension/$img_extension/profile-image/90x90&quot;;<br>// $img_endpoint = &quot;/restapi/v1.0/account/$img_account/extension/$img_extension/profile-image/195x195&quot;;<br> $img_resp = $platform-&gt;get($img_endpoint);<br> $contentType = <br> $img_resp-&gt;response()-&gt;<br> getHeaderLine(&quot;Content-Type&quot;);<br> $binary = $img_resp-&gt;raw();<br> $base64 = base64_encode($binary);<br> $imageSrc = &quot;data:$contentType;base64,$base64&quot;; ?&gt;<br>&lt;img src=&quot;&lt;?php echo $imageSrc; ?&gt;&quot; alt=&quot;Profile&quot;&gt;<br> &lt;br/&gt;<br> &lt;?php } else {<br> echo_spaces(&quot;Contact profile image not found.&quot;, &quot;&quot;, 2);<br> }<br> }<br> }<br> } else {<br> echo_spaces(&quot;No contact records found for provided<br> parameters.&quot;);<br> }<br> } catch (\RingCentral\SDK\Http\ApiException $e) {<br> // craft a friendly error message here.<br> echo_spaces(&quot;There was an error retrieving the contacts list,<br> Please try again later&quot;, $e-&gt;getMessage());<br> }<br>}</pre><p>The endpoint for this API call is: /restapi/v1.0/account/~/directory/entries</p><p>After we get our connection to the API with the sdk() call, we call the get method on the platform object passing in this endpoint. We are then given the response object with all the company contact information that is related to the specified account.</p><p>After checking that there is at least one record returned, there is a block of code that is commented out that can help to sort the object elements by “lastName”. You can uncomment this out and adjust it if you need to sort the retrieved information. Next we step through all the records and see if they are “enabled” before we do anything with them. If they are enabled, then we start to send out the information to the browser in a human-readable format.</p><p>Each company contact also has the potential to have a profile image associated with it. So we are using another aspect of the API to bring back a profile image if one exists. You will see a variable called $img_endpoint that calls another get method with the provided account and extension numbers added and the dimension of the image at the end — 90x90. There is also a 195x195 dimension option that I have added as a comment if you want to see what the larger images may look like. After the new endpoint is called we process the image information and craft an HTML image output line within the overall loop, so that we can see an image for each company contact. When we run this code we should see output like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/319/1*zNsFNaQCD46iGtEs2QkntQ.png" /></figure><h3>Personal Contacts API</h3><p>The API endpoint for the personal contacts is different from the Company one. This is partially due to the fact that you can control the content of these contacts. The endpoint for personal data is: /restapi/v1.0/account/~/extension/~/address-book/contact</p><p>Here we see that the main difference is /address-book/contact</p><p>The criterion for the endpoint also allows for a few parameters. The first one is “startsWith”; this allows you to filter the returned records with only data that has a firstname or lastname that starts with a provided string. The second parameter is “sortBy” and this allows you to have the returned information sorted by first name, last name, or company data elements. We will see this in action shortly when we look at the code. The request form that I built is the same one from before but this time we have the option of passing in one or both of these optional parameters. Here, again, is the screen.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/909/1*DyGVTx1Qcim8qVSj7cm7ZQ.png" /></figure><p>If we leave the “starts with” option blank and request that we sort the returned data by lastname the output will look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/380/1*xPgfqOc7mkS0a6rYQfUeNg.png" /></figure><p>The code for this is collected within a function called “get_guest_contacts” and we pass over the 2 parameters for the endpoint as options within the structure of the function. Here is the code for the function:</p><pre>function get_guest_contacts($startsWith = &quot;&quot;, $sortBy = &quot;&quot;) {<br>$controller = ringcentral_sdk();<br>$platform = $controller[&#39;platform&#39;];<br>$queryParams = array(<br>&#39;startsWith&#39; =&gt; $startsWith,<br>&#39;sortBy&#39; =&gt; $sortBy,<br>);<br>$endpoint = &quot;/restapi/v1.0/account/~/extension/~/address-book/contact&quot;;<br>try {<br>$resp = $platform-&gt;get($endpoint, $queryParams);<br>$records = $resp-&gt;json()-&gt;records; // array of objects<br>if (count($records) &gt;= 1) {<br>foreach ($records as $record) {<br>echo_spaces(&quot;Contact ID&quot;, $record-&gt;id);<br>echo_spaces(&quot;Company&quot;, $record-&gt;company);<br>echo_spaces(&quot;Contact Last name&quot;, $record-&gt;lastName);<br>echo_spaces(&quot;Contact Full name&quot;, $record-&gt;firstName . &#39; &#39; . $record-&gt;lastName);<br>echo_spaces(&quot;Contact Home Phone #&quot;, $record-&gt;homePhone);<br>if (!$record-&gt;birthday) {<br>echo_spaces(&quot;No birthday listed&quot;);<br>} else {<br>echo_spaces(&quot;Contact Birthday&quot;, $record-&gt;birthday);<br>}<br>if (!$record-&gt;jobTitle) {<br>echo_spaces(&quot;No Job Title listed&quot;);<br>} else {<br>echo_spaces(&quot;Contact Job Title&quot;, $record-&gt;jobTitle);<br>}<br>if (!$record-&gt;notes) {<br>echo_spaces(&quot;No notes recorded&quot;, &quot;&quot;, 2);<br>} else {<br>echo_spaces(&quot;Contact notes&quot;, $record-&gt;notes, 2);<br>}<br>}<br>} else {<br>echo_spaces(&quot;No contact records found for provided parameters.&quot;);<br>}<br>} catch (\RingCentral\SDK\Http\ApiException $e) {<br>// craft a friendly error message here.<br>echo_spaces(&quot;There was an error retrieving the contacts list, Please try again later&quot;, $e-&gt;getMessage());<br>// echo_spaces(&quot;details&quot;, $e);<br>}<br>}</pre><p>The structure of this function is very close to the one that we used for company data. One of the main differences is that there is no associated image available for these contacts, so that has been removed from this code. Also, the ability to sort the information on a few criteria is available here and not with the company information.</p><p>One other thing that you can do with this endpoint, using the post method instead, is to create personal contacts. There are more queryParameters that are available when adding in a new contact, as one would expect and they can be found <a href="https://developers.ringcentral.com/api-reference/External-Contacts/createContact">here</a>. If you are considering using this process, you will have to add the “Contacts” scope to your developer app.</p><h3>Further Reference</h3><p>With this collection of information available to you via the API, there are quite a few things you can do with it. You can export the data to external systems, archive the data, or use individual record information to place personalized calls, SMS messages, or electronic fax transmissions. For more complete information on these API actions check out these links.</p><ol><li>Address book developer guide: <a href="https://developers.ringcentral.com/guide/address-book">https://developers.ringcentral.com/guide/address-book</a></li><li>Address book API Reference — List User Contacts: <a href="https://developers.ringcentral.com/api-reference/External-Contacts/listContacts">https://developers.ringcentral.com/api-reference/External-Contacts/listContacts</a></li><li>Address book API Reference — Create User Contacts:<br><a href="https://developers.ringcentral.com/api-reference/External-Contacts/createContact">https://developers.ringcentral.com/api-reference/External-Contacts/createContact</a></li><li>Address book API Reference — Get Company Directory Entries:<br><a href="https://developers.ringcentral.com/api-reference/Internal-Contacts/listDirectoryEntries">https://developers.ringcentral.com/api-reference/Internal-Contacts/listDirectoryEntries</a></li></ol><p>I hope you found this article useful and that you can see the potential of what can be done with this portion of the RingCentral API beyond what was demonstrated here.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a6fc58988376" width="1" height="1" alt=""><hr><p><a href="https://medium.com/ringcentral-developers/accessing-contact-information-with-ringcentrals-api-a6fc58988376">Accessing Contact Information with RingCentral’s API</a> was originally published in <a href="https://medium.com/ringcentral-developers">RingCentral Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>