Permalink
Browse files

Initial commit of Nutshell API JSON-RPC wrapper + examples

0 parents commit 25f76e159f2db14dba0382f1244d7e5a313c9fb9 Chris Dzombak committed Mar 2, 2011
Showing with 398 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +195 −0 NutshellApi.php
  3. +105 −0 examples/create.php
  4. +61 −0 examples/edit.php
  5. +36 −0 examples/retrieve.php
@@ -0,0 +1 @@
+temp/
@@ -0,0 +1,195 @@
+<?php
+
+/**
+ * @class NutshellApi
+ * @brief Easy access to the Nutshell JSON-RPC API
+ *
+ * This class is instantiated with a username and API key. Once it has been
+ * instantiated, the call() method is used to make calls to the Nutshell API.
+ *
+ * Rather than using call(), you can also call any Nutshell API methods on
+ * this class. For example, rather than calling
+ * @code
+ * $api->call('getContact', $params);
+ * @endcode
+ * you can call
+ * @code
+ * $api->getContact($params);
+ * @endcode
+ *
+ * Calls made using this class are synchronous - the method blocks until the
+ * request is completed.
+ *
+ * Requires PHP 5.0+ and the CURL and JSON modules.
+ * CURL: http://php.net/manual/en/book.curl.php
+ * JSON Module: http://pecl.php.net/package/json
+ *
+ * @version 0.1
+ * @date March 2, 2011
+ */
+
+class NutshellApi {
+ const ENDPOINT_DISCOVER_URL = 'http://api.nutshell.com/v1/json';
+ protected $curl = NULL;
+
+ /**
+ * Initializes the API access class. Takes care of endpoint discovery.
+ *
+ * @param string $username
+ * @param string $apiKey
+ * @throws NutshellApiException if either parameter is invalid
+ */
+ function __construct($username, $apiKey) {
+ if (!is_string($username) || !is_string($apiKey)) {
+ throw new NutshellApiException('You must specify a username and API key.');
+ }
+ if (strpos($username, '@') === FALSE) {
+ throw new NutshellApiException('Username is not a valid email address.');
+ }
+ if (strlen($apiKey) <= 12) {
+ throw new NutshellApiException('API key is not long enough to be a valid key.');
+ }
+
+ $endpoint = $this->_getApiEndpointForUser($username);
+ $authHeader = base64_encode($username . ':' . $apiKey);
+
+ $this->curl = curl_init($endpoint);
+ curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Authorization: Basic '.$authHeader));
+ curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->curl, CURLOPT_POST, true);
+ curl_setopt($this->curl, CURLOPT_HEADER, false);
+ }
+
+ function __destruct() {
+ if ($this->curl) {
+ curl_close($this->curl);
+ }
+ }
+
+ /**
+ * Calls a Nutshell API method
+ *
+ * See call() for detailed specs.
+ *
+ * @return array
+ * @throws NutshellApiException
+ */
+ public function __call($name, $args) {
+ return $this->call($name, isset($args[0]) ? $args[0] : NULL);
+ }
+
+ /**
+ * Calls a Nutshell API method.
+ *
+ * Returns the result from that call or, if there was an error on the server,
+ * throws an exception.
+ *
+ * @param string $method
+ * @param array|null $params
+ * @return array
+ * @throws NutshellApiException
+ */
+ public function call($method, array $params = NULL) {
+ if ($this->curl === NULL) {
+ throw new NutshellApiException('Nutshell API uninitialized; perhaps the constructor failed?');
+ }
+ if ($params === NULL) {
+ $params = array();
+ }
+ if (!is_string($method)) {
+ throw new NutshellApiException("Invalid method '$method'");
+ } else if (!is_array($params)) {
+ throw new NutshellApiException('$params must be an array');
+ }
+
+ $payload = array(
+ 'method' => $method,
+ 'params' => $params,
+ 'id' => $this->_generateRequestId(),
+ );
+
+ curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->json_encode($payload));
+ $fullResult = curl_exec($this->curl);
+ if (curl_errno($this->curl)) {
+ throw new NutshellApiException('Curl error #' . curl_errno($this->curl) . ' during API call: '. curl_error($this->curl));
+ }
+ $fullResult = $this->json_decode($fullResult);
+
+ if ($fullResult->error !== NULL) {
+ throw new NutshellApiException('API Error: ' . $fullResult->error->message, $fullResult->error->code, $fullResult->error->data);
+ }
+
+ return $fullResult->result;
+ }
+
+ /**
+ * Finds the appropriate API endpoint for the given user.
+ *
+ * Info on endpoint discovery: http://nutshell.com/api/endpoint-discovery.html
+ *
+ * @param string $username
+ * @return string API endpoint
+ * @throws NutshellApiException
+ */
+ protected function _getApiEndpointForUser($username) {
+ $payload = array(
+ 'method' => 'getApiForUsername',
+ 'params' => array('username' => $username),
+ 'id' => $this->_generateRequestId(),
+ );
+
+ $curl = curl_init(self::ENDPOINT_DISCOVER_URL);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $this->json_encode($payload));
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ $result = curl_exec($curl);
+ if (curl_errno($curl)) {
+ throw new NutshellApiException('Curl error #' . curl_errno($curl) . ' while finding endpoint: '. curl_error($curl));
+ }
+ curl_close($curl);
+
+ $decoded = $this->json_decode($result);
+ return 'https://' . $decoded->result->api . '/api/v1/json';
+ }
+
+ /**
+ * Generates a random JSON request ID
+ *
+ * @return string
+ */
+ protected function _generateRequestId() {
+ return substr(md5(rand()), 0, 8);
+ }
+
+ /**
+ * Encodes object in JSON
+ *
+ * Can be overridden to support PHP installations without built-in JSON support.
+ */
+ protected function json_encode($x) {
+ return json_encode($x);
+ }
+
+ /**
+ * Decodes object from JSON
+ *
+ * Can be overridden to support PHP installations without built-in JSON support.
+ */
+ protected function json_decode($x) {
+ return json_decode($x);
+ }
+}
+
+class NutshellApiException extends Exception {
+ protected $data;
+
+ public function __construct($message, $code = 0, $data = NULL) {
+ parent::__construct($message, $code);
+ $this->data = $data;
+ }
+
+ public function getData() {
+ return $this->data;
+ }
+}
@@ -0,0 +1,105 @@
+#!/usr/bin/env php
+<?php
+
+// Configuration:
+$apiKey = 'YOUR API KEY HERE';
+$username = 'user@example.com';
+// End of configuration
+
+require_once('../NutshellApi.php');
+$api = new NutshellApi($username, $apiKey);
+
+/**
+ * Example: creating an account, contact, and lead
+ *
+ * We will create a new contact, then add a new account associated with that contact,
+ * then finally create a new lead involving that account/contact.
+ *
+ * Relevant documentation:
+ * http://www.nutshell.com/api/detail/class_nut___api___core.html
+ */
+
+// Create a new contact and save its ID to $newContactId
+$params = array(
+ 'contact' => array(
+ 'name' => 'Joan Smith',
+ 'phone' => array(
+ '734-555-9090',
+ 'cell' => '734-555-6711',
+ ),
+ 'email' => array(
+ 'jsmith@example.com',
+ 'blackberry' => 'jsmith@att.blackberry.com',
+ ),
+ ),
+);
+$newContact = $api->call('newContact', $params);
+$newContactId = $newContact->id;
+
+// Create a new account that includes the contact we just added
+$params = array(
+ 'account' => array(
+ 'name' => 'Arbor Medical LLC',
+ 'industryId' => 1,
+ 'url' => array(
+ 'http://example.com',
+ 'http://suppliers.example.com',
+ ),
+ 'phone' => array(
+ '734-234-9990',
+ ),
+ 'contacts' => array(
+ array(
+ 'id' => $newContactId,
+ 'relationship' => 'Purchasing Manager'
+ ),
+ ),
+ 'address' => array(
+ 'office' => array(
+ 'address_1' => '220 Depot St',
+ 'city' => 'Ann Arbor',
+ 'state' => 'MI',
+ 'postalCode' => '48104',
+ ),
+ ),
+ ),
+);
+$newAccount = $api->newAccount($params);
+$newAccountId = $newAccount->id;
+
+// Finally, create a lead that includes the account we just added
+$params = array(
+ 'lead' => array(
+ 'primaryAccount' => array('id' => $newAccountId),
+ 'confidence' => 70,
+ 'market' => array('id' => 1),
+ 'contacts' => array(
+ array(
+ 'relationship' => 'First Contact',
+ 'id' => $newContactId,
+ ),
+ ),
+ 'products' => array(
+ array(
+ 'relationship' => '',
+ 'quantity' => 15,
+ 'price' => array(
+ 'currency_shortname' => 'USD',
+ 'amount' => 1000,
+ ),
+ 'id' => 4,
+ ),
+ ),
+ 'sources' => array(
+ array('id' => 2),
+ ),
+ 'assignee' => array(
+ 'entityType' => 'Teams',
+ 'id' => 1000,
+ ),
+ ),
+);
+$result = $api->newLead($params);
+var_dump($result);
+
+echo "\n";
@@ -0,0 +1,61 @@
+#!/usr/bin/env php
+<?php
+
+// Configuration:
+$apiKey = 'YOUR API KEY HERE';
+$username = 'user@example.com';
+// End of configuration
+
+require_once('../NutshellApi.php');
+$api = new NutshellApi($username, $apiKey);
+
+/**
+ * Example: editing a lead
+ *
+ * We will add a contact and change the confidence for a lead.
+ * To keep the existing contacts, we need to include them in our request.
+ *
+ * Relevant documentation:
+ * http://nutshell.com/api/retrieving-editing.html
+ * http://www.nutshell.com/api/revs-etags.html
+ */
+
+// Get the lead so we have an up-to-date rev and the current contacts array
+$leadId = 1600;
+$params = array( 'leadId' => $leadId );
+$oldLead = $api->call('getLead', $params);
+$rev = $oldLead->rev;
+$oldContacts = $oldLead->contacts;
+
+// Build new contacts array containing the old contacts plus the one we want to add
+$contacts = array();
+foreach ($oldContacts as $contact) {
+ $contacts[] = array(
+ 'id' => $contact-> id,
+ 'relationship' => $contact->relationship,
+ 'entityType' => 'Contacts',
+ // entityType is required for updating multivalue keys when editing a lead.
+ // this requirement will be removed in a future API release.
+ );
+}
+$contacts[] = array(
+ 'relationship' =>'additional contact',
+ 'id' => 17,
+ 'entityType' => 'Contacts',
+ // entityType is required for updating multivalue keys when editing a lead.
+ // this requirement will be removed in a future API release.
+);
+
+// edit the lead
+$params = array(
+ 'leadId' => $leadId,
+ 'rev' => $rev,
+ 'lead' => array(
+ 'confidence' => 75,
+ 'contacts' => $contacts,
+ ),
+);
+$result = $api->editLead($params);
+var_dump($result);
+
+echo "\n";
Oops, something went wrong.

0 comments on commit 25f76e1

Please sign in to comment.