Accessing Your Crevado Portfolio via the Crevado API

What’s this about an API?

Every Crevado portfolio has a built in minimal REST style API which allows reading of pages and media on your portfolio using JSON.

How do I access the API?

It’s pretty easy! First obtain your API Key at your API information page.

Once you have your API key, you can access your JSON REST API via https://crevado.com/api/pages.json. When accessing the Crevado API resources you must pass your API key and Crevado domain via custom HTTP headers. Your API Key should be passed as the header X-APIKey and your Crevado domain name as X-APIDomain - see the code samples below for more information. If either of these credentials are not supplied or incorrect the endpoint will return with a HTTP 403 (Forbidden).

Sample JSON Output

Typical output from api/pages.json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[{
  "images_count":13,
    "link_title":"Awesome Photography Gallery",
    "page_type_id":5,
    "updated_at":"2013-02-21T11:37:10Z",
    "api_url":"pages/76327-photos"
}, {
  "images_count":0,
  "link_title":"About",
  "page_type_id":1,
  "updated_at":"2013-02-21T11:36:30Z",
  "api_url":"pages/76324-about-me"
}
...etc.etc...
]

Accessing the above mentioned page “Awesome Photography Gallery” can be done via /api/pages/76324-photos.json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
  "page": {
      "page_title":"Awesome Photography Gallery",
      "link_title":"Awesome Photography Gallery"
  },
  "media":[
    {
      "id":282857,
      "title":"Elephant in the field",
      "urls":{
        "enlarged":"http://i.crevado.com/91282857_enlarged-1.jpg",
        "thumb":"http://i.crevado.com/91282857_thumb-1.jpg"
      }
    },
    {
      "id":282856,
      "title":"Where'd he go?",
      "urls":{
        "enlarged":"http://i.crevado.com/91282857_enlarged-1.jpg",
        "thumb":"http://i.crevado.com/91282857_thumb-1.jpg"
      }
    },
    ... etc. etc...
  ]
}

PHP Code Sample

The following is a PHP code sample which demonstrates how you can interact with the API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<?
/*
 *  CREVADO.COM API Integration with PHP
 *
 *  Author ✰  Crevado Portfolios
 *
 *  DateCreated ✰ Thu, 14/Mar/2013
 *
 */

class CrevadoPortfolio {

  const PAGE_TYPE_CONTENT   = 0;
  const PAGE_TYPE_ABOUT     = 1;
  const PAGE_TYPE_GALLERIES = 2;
  const PAGE_TYPE_LINK      = 3;
  const PAGE_TYPE_EMAIL     = 4;
  const PAGE_TYPE_GALLERY   = 5;

  private $arrConfig = array();
  private $_errors   = array();
  // cache ttl in seconds
  private $_ttl      = 180;
  // cache dir (built in __construct)
  private $_cachedir = null;

  // Constructor - pass hostname as yourname.crevado.com or www.yourname.com
  // along with your API key:
  //
  // $obj = new CrevadoPortfolio("myname.crevado.com","my-secret-api-key");
  // or
  // $obj = new CrevadoPortfolio("myname.com","my-secret-api-key");
  public function __construct($sCrevadoHostName, $sAPIKey) {
    // keys are always 32 chars long
    if (strlen(trim($sAPIKey)) != 32)
      throw new Exception("Invalid API key! {$sAPIKey}");
    $this->arrConfig = array(
      'domain'  =>  strtolower(trim($sCrevadoHostName)),
      'api_key' =>  trim($sAPIKey),
    );
    // init cache dir..
    $this->_cachedir = join(DIRECTORY_SEPARATOR, array(sys_get_temp_dir(), ".crevado-cache-".$this->arrConfig['domain']));
    if (!is_dir($this->_cachedir))
      mkdir($this->_cachedir, 0700);
  }

  // Error Handling
  protected function resetErrors() {
    $this->_errors = array();
  }

  public function errors() {
    return $this->_errors;
  }

  private function addError($sMessage) {
    $this->_errors[] = $sMessage;
  }

  // The main meat of all this...
  protected function get($sAPIUrl) {
    if ($cache = $this->isCached($sAPIUrl))
      return $cache;
    $this->resetErrors();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://crevado.com/api/".$sAPIUrl.".json");
    curl_setopt($ch, CURLOPT_USERAGENT, "Crevado/PHP/v1.0");
    // NOTE: API key is passed to the server via the X-ApiKey header
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
      "X-ApiKey: "   .$this->arrConfig['api_key'],
      "X-ApiDomain: ".$this->arrConfig['domain'],
    ));
    curl_setopt($ch, CURLOPT_VERBOSE, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);

    $response = curl_exec($ch);
    // Check for a cURL connection error
    if (curl_error($ch)) {
      // We hit a failure!
      $this->addError("Curl Error: ".curl_error($ch));
    } else {
      $info = curl_getinfo($ch);
      if ($info['http_code'] != 200)
        $this->addError("HTTP ERROR {$info['http_code']} - http://en.wikipedia.org/wiki/HTTP_{$info['http_code']}");
    }
    curl_close($ch);
    if (!empty($response) && !count($this->_errors)) {
      $this->saveCache($sAPIUrl, $response);
      return json_decode($response);
    }
    return null;
  }

  // API Wrapping
  public function page($page) {
    $url = null;
    if (is_object($page)) {
      if (empty($page->api_url))
        throw new Exception("Invalid Page! (missing url?)");
      else
        $url = $page->api_url;
    } elseif (is_array($page)) {
      if (empty($page['api_url']))
        throw new Exception("Invalid Page! (missing url?)");
      else
        $url = $page['api_url'];
    } else {
      $url = $page;
    }
    return $this->get($url);
  }

  public function pages() {
    return $this->get("pages");
  }

  private function getCachePath($sAPIUrl) {
    return join(DIRECTORY_SEPARATOR, array($this->_cachedir, md5($sAPIUrl)));
  }

  private function saveCache($sAPIUrl, $sContents) {
    $sCachePath = $this->getCachePath($sAPIUrl);
    if ($fp = fopen($sCachePath, "w")) {
      fwrite($fp, $sContents);
      fclose($fp);
    }
  }

  private function isCached($sAPIUrl) {
    $sCachePath = $this->getCachePath($sAPIUrl);
    // if file exists and its less than our TTL
    if (file_exists($sCachePath) && (filemtime($sCachePath) > (time()-$this->_ttl)))
      return json_decode(file_get_contents($sCachePath));
    return false;
  }
}

//----------------------------------------------------------------------
//    _______  __    _    __  __ ____  _     _____
//   | ____\ \/ /   / \  |  \/  |  _ \| |   | ____|
//   |  _|  \  /   / _ \ | |\/| | |_) | |   |  _|  
//   | |___ /  \  / ___ \| |  | |  __/| |___| |___
//   |_____/_/\_\/_/   \_\_|  |_|_|   |_____|_____|
//
//       S A M P L E   U S A G E
//
//                  your crevado domain:          and your API key:
$objFolio = new CrevadoPortfolio("mysite.crevado.com", "dd152981...............87d3da552");

if ($pages = $objFolio->pages()) {
  //print_r($pages); <- take a peek!
  $objGalleryPage = null;
  foreach ($pages as $objPage) {
    // output some useful attributes for kicks..
    echo "{$objPage->link_title} => {$objPage->page_type_id} ({$objPage->api_url})\n";
    // if we don't have a gallery page already and this is one record it for a page() call demo
    if (!$objGalleryPage && $objPage->page_type_id == CrevadoPortfolio::PAGE_TYPE_GALLERY)
      $objGalleryPage = $objPage;
  }

  // given we've swiped the first available gallery above get the contents of the page
  $objMyGalleryPage = $objFolio->page($objGalleryPage);
  // you can also pass the api_url directly:
  //$objMyGalleryPage = $objFolio->page("pages/76324-photos");
  // images ...
  print_r($objMyGalleryPage->media);

} else {
  echo "<h2>Something bad happened:</h2>";
  print_r($objFolio->errors());
}
//----------------------------------------------------------------------