This page NeedsTranslation.
GET & Authentication
To browse the public marks posted on Blogmarks.net just fetch this URL :
By default, the last 30 public marks posted on blogmarks.net are sent.
Corresponding to the following parameters :
- last : 30
- order_type : DESC
- order_by : created
And so the following URL :
http://api.blogmarks.net/marks?last=30&order_type=DESC&order_by=created
So you can grab the 10 most popular marks of all time, by fetching this URL :
Let's write our first HTTP query and fetch the last mark :
GET /marks?last=1 HTTP/1.0 Host: api.blogmarks.net Accept: application/atom+xml
The server response :
HTTP/1.1 200 OK Date: Mon, 07 Mar 2005 19:32:10 GMT Server: Apache/1.3.26 (Unix) Debian GNU/Linux PHP/4.3.9-1.dotdeb.3 X-Powered-By: PHP/4.3.9-1.dotdeb.3 Content-length: 1293 Connection: close Content-Type: text/xml; charset=utf-8 <?xml version="1.0" encoding="UTF-8"?> <feed version="draft-ietf-atompub-format-05:do not deploy" xmlns="http://purl.org/atom/ns#draft-ietf-atompub-format-05" xmlns:bm="http://api.blogmarks.net/ns#"> <head> <title>Last public marks</title> <link rel="alternate" type="application/xhtml+xml" href="?last=1"/> <link rel="next" type="application/atom+xml" href="http://api.blogmarks.net/marks?last=1&offset=1&order_type=DESC&order_by=created"/> <updated>2005-03-07T20:23:04Z</updated> </head> <entry> <id>tag:blogmarks.net,2005:marks,31171</id> <title type="TEXT">Kevin Kelly -- Cool Tools:Wall Full of Whiteboard</title> <link rel="related" href="http://www.kk.org/cooltools/archives/000679.php" type="text/html"/> <link rel="alternate" href="http://blogmarks.net/user/delicious.popular/archives/2005/03/#mark31171" type="application/xhtml+xml" title="Kevin Kelly -- Cool Tools:Wall Full of Whiteboard"/> <link rel="image" href="http://www.blogmarks.net/screenshots/2005/03/07/2d3eb782512a6aff2540f74a0a32bd3d.png" type="image/png"/> <updated>2005-03-07T20:23:04Z</updated> <published>2005-03-07T20:23:04Z</published> <author><name>delicious.popular</name></author> <edit>http://api.blogmarks.net/atom/marks/31171</edit> <bm:created>2005-03-07T20:23:04Z</bm:created> </entry> </feed>
If you want to write this in a script, we recommand you to use an HTTP library like Pear HTTP:Request (in case you're using PHP) :
<?php
require_once "HTTP/Request.php";
$req =& new HTTP_Request("http://api.blogmarks.net/marks?last=1");
$req->addHeader("Accept", 'application/atom+xml');
$response = $req->sendRequest();
if (PEAR::isError($response)) {
echo $response->getMessage();
} else {
$code = $req->getResponseCode();
switch ( $code ) {
case 200:
$xml = $req->getResponseBody();
// Handle the resulting Atom response here
echo $xml;
break;
default:
echo $code . " Error\n";
break;
}
}
?>
For your curiosity, in vanilla PHP, you can write this (very basic, no error handling) :
<?php
$request = 'GET /marks?last=1 HTTP/1.0' . "\n";
$request .= 'Host: api.blogmarks.net' . "\n";
$request .= 'Accept: application/atom+xml' . "\n";
$request .= "\n";
$fp = fsockopen('api.blogmarks.net', 80, $errno, $errstr, 30);
fputs($fp,$request);
$response = '';
while ( !feof ( $fp ) ) {
$line = fgets ($fp, 128);
$response .= $line;
}
fclose($fp);
echo $response;
?>
Now, imagine you want to fetch your private marks and private tags. This feature require authentication. As advised in the Atom authentication tutorial by Mark Pilgrim, we'll use WSSE Username Token authentication. For detailed explanation about WSSE authentication, the tutorial is a must read.
We start with 4 variables :
- $Username : znarf
- $Password : foo
- $Nonce (a cryptographically random string ) : 15253654
- $CreationTimestamp (the current time in W3CDTF format) : 2004-03-08T17:11:42Z
In our implementation we use the md5 hash of the password. If you have the original password hash it, else just use the hashed one.
So eventually :
- $PasswordHash = md5( $Password );
We create the password digest :
- $PasswordDigest = Base64 ( SHA1 ( $Nonce + $CreationTimestamp + $PasswordHash ) )
Basically we add 2 lines in the HTTP header and we are authenticated. Note we've set the private parameter to TRUE to request the private marks and private tags.
GET /marks?last=30&private=true HTTP/1.0 Host: api.blogmarks.net Accept: application/atom+xml Authorization: WSSE profile="UsernameToken" X-WSSE: UsernameToken Username="$Username", PasswordDigest="$PasswordDigest", Nonce="$Nonce", Created="$CreationTimestamp"
The corresponding PHP code is :
<?php
$Username = 'znarf';
$Password = 'foo';
$Nonce = rand( 1 , 100000000000000 );
$CreationTimestamp = date('Y-m-d\Th:i:s\Z');
$PasswordHash = md5( $Password );
$PasswordDigest = base64_encode( sha1( $Nonce . $CreationTimestamp . $PasswordHash ) );
require_once "HTTP/Request.php";
$req =& new HTTP_Request("http://api.blogmarks.net/marks?last=1");
$req->addHeader("Accept", 'application/atom+xml');
$req->addHeader('Authorization', 'WSSE profile="UsernameToken"');
$req->addHeader('X-WSSE', 'UsernameToken Username="' . $Username . '",
PasswordDigest="' . $PasswordDigest . '", Nonce="' . $Nonce . '", Created="' . $CreationTimestamp . '"');
$response = $req->sendRequest();
if (PEAR::isError($response)) {
echo $response->getMessage();
} else {
$code = $req->getResponseCode();
switch ( $code ) {
case 200:
$xml = $req->getResponseBody();
// Handle the resulting Atom response here
echo $xml;
break;
default:
echo $code . " Error\n";
break;
}
}
?>
Note that we've handled directly the authentication but the best is to use core components of your framework of choice.
POST
You add a new mark on blogmarks.net by posting an Atom entry on a postURI. The postURI is http://api.blogmarks.net/marks.
In the Atom entry, you must specify at least a related link and a title.
First example
We'll se how to create the most simple allowed blogmark.
Authentication is explained in AtomApiTutorial/Get
The client send
POST /marks HTTP/1.0 Host: api.blogmarks.net Accept: application/atom+xml Content-Type: text/xml; charset=utf-8 Content-length: 267 Authorization: WSSE profile="UsernameToken" X-WSSE: UsernameToken Username="$Username", PasswordDigest="$PasswordDigest", Nonce="$Nonce", Created="$CreationTimestamp" <entry version="draft-ietf-atompub-format-05:do not deploy" xmlns="http://purl.org/atom/ns#draft-ietf-atompub-format-05" xmlns:bm="http://api.blogmarks.net/ns#"> <title>Znarf Blog</title> <link rel="related" href="http://upian.net/znarf/blog/" /> </entry>
The server response :
HTTP/1.1 201 Created Date: Wed, 09 Mar 2005 11:21:03 GMT Content-length: 811 Connection: close Content-Type: application/atom+xml; charset=utf-8 <?xml version="1.0" encoding="UTF-8"?> <entry xmlns="http://purl.org/atom/ns#draft-ietf-atompub-format-05" xmlns:bm="http://api.blogmarks.net/ns#> <id>tag:blogmarks.net,2005:marks,31523</id> <title type="TEXT">Znarf Blog</title> <link rel="related" href="http://upian.net/znarf/blog/" type="text/html"/> <link rel="alternate" href="http://blogmarks.net/user/znarf/archives/2005/03/#mark31523" type="application/xhtml+xml" title="Znarf Blog Test"/> <link rel="image" href="http://blogmarks.net/screenshots/2005/03/09/dbc0c60c8794c0ca4f2e99f10a5f2408.png" type="image/png"/> <updated>2005-03-09T12:21:03Z</updated> <author><name>znarf</name></author> <edit>http://api.blogmarks.net/marks/31523</edit> <bm:created>2005-03-09T12:21:03Z</bm:created> </entry>
Second example
We'll create a more advanced blogmark.
- In the Atom mapping, tags are called category
- By specifing published=0000-00-00, we say that the blogmarks is private (not published)
- bm:created is the main blogmark date. This is the one which is used to sort blogmarks chronologically
POST /marks HTTP/1.0 Host: api.blogmarks.net Accept: application/atom+xml Content-Type: text/xml; charset=utf-8 Content-length: 535 Authorization: WSSE profile="UsernameToken" X-WSSE: UsernameToken Username="$Username", PasswordDigest="$PasswordDigest", Nonce="$Nonce", Created="$CreationTimestamp" <?xml version="1.0" encoding="UTF-8"?> <entry version="draft-ietf-atompub-format-05:do not deploy" xmlns="http://purl.org/atom/ns#draft-ietf-atompub-format-05" xmlns:bm="http://api.blogmarks.net/ns#"> <title>Znarf Blog</title> <link rel="related" href="http://upian.net/znarf/blog/" /> <link rel="via" href="http://blogmarks.net/" /> <summary>This blog really rox</summary> <category label="blog" /> <category label="dotclear" /> <published>0000-00-00</published> <bm:created>2005-03-09</bm:created> </entry>
Same code in PHP / Pear HTTP Request
<?php
$Username = 'znarf';
$Password = '';
$Nonce = rand( 1 , 100000000000000 );
$CreationTimestamp = date('Y-m-d\Th:i:s\Z');
$PasswordHash = md5( $Password );
$PasswordDigest = base64_encode( sha1( $Nonce . $CreationTimestamp . $PasswordHash ) );
require_once "HTTP/Request.php";
$req =& new HTTP_Request('http://api.blogmarks.net/marks');
$req->setMethod(HTTP_REQUEST_METHOD_POST);
$req->addHeader('X-WSSE', 'UsernameToken Username="' . $Username . '", PasswordDigest="' . $PasswordDigest . '", Nonce="' . $Nonce . '", Created="' . $CreationTimestamp . '"');
$xml =
'<?xml version="1.0" encoding="UTF-8"?>
<entry
version="draft-ietf-atompub-format-05:do not deploy"
xmlns="http://purl.org/atom/ns#draft-ietf-atompub-format-05"
xmlns:bm="http://api.blogmarks.net/ns#">
<title>Znarf Blog</title>
<link rel="related" href="http://upian.net/znarf/blog/" />
<link rel="via" href="http://blogmarks.net/" />
<summary>This blog rox</summary>
<category term="http://api.blogmarks.net/tags/" sheme="blog" />
<category term="http://api.blogmarks.net/tags/" sheme="dotclear" />
<published>0000-00-00</published>
<bm:created>2005-03-09</bm:created>
</entry>';
$req->addRawPostData($xml);
$response = $req->sendRequest();
if (PEAR::isError($response)) {
echo $response->getMessage();
} else {
$code = $req->getResponseCode();
switch ($code) {
case 201:
echo "OK\n";
echo $req->getResponseBody();
break;
default:
echo $code . " Error\n";
break;
}
}
?>
Good practices
- Don't flood : Flooding is posting a lot of blogmarks (say more than 5) and by the way filling the Last Public Marks list. Others users really don't like that. The recommended practice is to specify a bm:created in the past. You may have one if you import marks for example. If you don't have one, we recommand to put the current date without specifying the hour. <bm:created>2005-03-08Z</bm:created>
Put
To update a blogmark, just PUT an Atom entry on the mark editURI.
The editURI can be found in Atom entries and is basically http://api.blogmarks.net/marks/$MarkID
Authentication is explained in AtomApiTutorial/Get
The client send :
PUT /marks/31523 HTTP/1.0 Host: api.blogmarks.net Accept: application/atom+xml Content-Type: text/xml; charset=utf-8 Content-length: 433 Authorization: WSSE profile="UsernameToken" X-WSSE: UsernameToken Username="$Username", PasswordDigest="$PasswordDigest", Nonce="$Nonce", Created="$CreationTimestamp" <entry version="draft-ietf-atompub-format-05:do not deploy" xmlns="http://purl.org/atom/ns#draft-ietf-atompub-format-05" xmlns:bm="http://api.blogmarks.net/ns#"> <title>Znarf Blog</title> <link rel="related" href="http://upian.net/znarf/blog/" /> <summary>This blog *really* rox</summary> <category term="http://api.blogmarks.net/tags/" sheme="blog" /> <category term="http://api.blogmarks.net/tags/" sheme="dotclear" /> <category term="http://api.blogmarks.net/tags/" sheme="daily" /> <category term="http://api.blogmarks.net/tags/" sheme="topsite" /> </entry>
The server response :
HTTP/1.1 200 OK Date: Wed, 09 Mar 2005 11:21:03 GMT Content-length: 811 Connection: close Content-Type: application/atom+xml; charset=utf-8 <?xml version="1.0" encoding="UTF-8"?> <entry xmlns="http://purl.org/atom/ns#draft-ietf-atompub-format-05" xmlns:bm="http://api.blogmarks.net/ns#> <id>tag:blogmarks.net,2005:marks,31523</id> <title type="TEXT">Znarf Blog</title> <link rel="related" href="http://upian.net/znarf/blog/" type="text/html"/> <link rel="alternate" href="http://blogmarks.net/user/znarf/archives/2005/03/#mark31523" type="application/xhtml+xml" title="Znarf Blog"/> <link rel="image" href="http://blogmarks.net/screenshots/2005/03/09/dbc0c60c8794c0ca4f2e99f10a5f2408.png" type="image/png"/> <summary>This blog *really* rox</summary> <updated>2005-03-09T11:21:03Z</updated> <author><name>znarf</name></author> <edit>http://api.blogmarks.net/marks/31523</edit> <category term="http://api.blogmarks.net/tags/" sheme="blog" label="blog"/> <category term="http://api.blogmarks.net/tags/" sheme="dotclear" label="dotclear"/> <category term="http://api.blogmarks.net/tags/" sheme="daily" label="daily"/> <category term="http://api.blogmarks.net/tags/" sheme="topsite" label="topsite"/> <bm:created>2005-03-09T12:21:03Z</bm:created> </entry>
Delete
To delete a blogmark, just send an HTTP Delete on the mark editURI.
The editURI can be found in Atom feeds and is basically http://api.blogmarks.net/marks/MARK_ID
Authentication is explained in AtomApiTutorial/Get
The client send :
DELETE /marks/1025 HTTP/1.0 Host: api.blogmarks.net Authorization: WSSE profile="UsernameToken" X-WSSE: UsernameToken Username="$Username", PasswordDigest="$PasswordDigest", Nonce="$Nonce", Created="$CreationTimestamp"
The server response :
HTTP/1.1 200 OK Date: Thu, 10 Mar 2005 12:10:26 GMT Connection: close
With PHP / Pear HTTP:Request you write
<?php
$Username = 'znarf';
$Password = '';
$Nonce = rand( 1 , 100000000000000 );
$CreationTimestamp = date('Y-m-d\Th:i:s\Z');
$PasswordHash = md5( $Password );
$PasswordDigest = base64_encode( sha1( $Nonce . $CreationTimestamp . $PasswordHash ) );
require_once "HTTP/Request.php";
$req =& new HTTP_Request('http://api.blogmarks.net/marks/1025');
$req->setMethod(HTTP_REQUEST_METHOD_DELETE);
$req->addHeader('X-WSSE', 'UsernameToken Username="' . $Username . '", PasswordDigest="' . $PasswordDigest . '", Nonce="' . $Nonce . '", Created="' . $CreationTimestamp . '"');
$response = $req->sendRequest();
if (PEAR::isError($response)) {
echo $response->getMessage();
} else {
$code = $req->getResponseCode();
switch ($code) {
case 200:
echo "OK\n";
break;
default:
echo $code . " Error\n";
echo $req->getResponseBody();
break;
}
}
?>
See also : DeveloperDocs
