+<p>On failure, all API calls return either a standard HTTP error
+response, like 404 Not Found if a record or user doesn't exist, or a 200
+response with a 'JSON failure', which will look like this:
+
+<pre>{"status": "failure"}</pre>
+
+<p>Blërg doesn't currently explain <i>why</i> there is a failure, and
+I'm not sure it ever will.
+
+<p>On success, you'll either get some JSON relating to your request (for
+/get, /tag, or /info), or a 'JSON success' response (for /create, /put,
+/login, or /logout), which looks like this:
+
+<pre>{"status": "success"}</pre>
+
+<p>For the CGI backend, you may get a 500 error if something goes wrong.
+For the HTTP backend, you'll get nothing (since it will have crashed),
+or maybe a 502 Bad Gateway if you have it behind another web server.
+
+<p>All usernames must be 32 characters or less. Usernames must contain
+only the ASCII characters 0-9, A-Z, a-z, underscore (_), and hyphen (-).
+Passwords can be at most 64 bytes, and have no limits on characters (but
+beware: if you have a null in the middle, it will stop checking there
+because I use <code>strncmp(3)</code> to compare).
+
+<p>Tags must be 64 characters or less, and can contain only the ASCII
+characters 0-9, A-Z, a-z, underscore (_), and hyphen (-).
+
+<h3><a name="api_authorization">Authorization</a></h3>
+
+<p>As the result of a successful <a href="#api_login">login</a>, the server
+will send back a cookie named <code>auth</code>. This cookie authorizes
+restricted requests, and must be sent for any API endpoint marked <span
+class="feature">authorization</span>, or else you will get a 403 Forbidden
+response. The cookie format looks like:
+
+auth=username/abcdef0123456789abcdef0123456789
+
+That is a username, a forward slash, and 32 hexadecimal digits which denote the
+"token" identifying the session. On logout, the server will invalidate the
+token and expire the cookie.
+
+<h3><a name="api_create">/create</a> - create a new user</a></h3>
+
+<p>To create a user, POST to /create with <code>username</code> and
+<code>password</code> parameters for the new user. The server will
+respond with JSON failure if the user exists, or if the user can't be
+created for some other reason. The server will respond with JSON
+success if the user is created.
+
+<h3><a name="api_login">/login</a> - log in</a></h3>
+
+<p>POST to /login with the <code>username</code> and
+<code>password</code> parameters for an existing user. The server will
+respond with JSON failure if the user does not exist or if the password
+is incorrect. On success, the server will respond with JSON success,
+and will set a cookie named 'auth' that must be sent by the client when
+accessing restricted API functions (See <a
+href="#api_authorization">Authorization</a> above).
+
+<h3><a name="api_logout">/logout</a> - log out</a></h3>
+<div class="feature">authorization</div>
+
+<p>POST to /logout. The server will respond with JSON failure if the
+user does not exist or if the request is unauthorized. The server will
+respond with JSON success after the user is successfully logged out.
+
+<h3><a name="api_put">/put</a> - add a new record</a></h3>
+<div class="feature">authorization</div>
+
+<p>POST to /put with a <code>data</code> parameter. The server will
+respond with JSON failure if the request is unauthorized, if the user
+doesn't exist, or if <code>data</code> contains more than 65535 bytes
+<i>after</i> URL decoding. The server will respond with JSON success
+after the record is successfully added.
+
+<h3><a name="api_get">/get/(user), /get/(user)/(start record)-(end record)</a> - get records for a user</a></h3>
+
+<p>A GET request to /get/(user), where (user) is the user desired, will
+return the last 50 records for that user in a list of objects. The
+record objects look like this:
+
+<pre>
+{
+ "record":"0",
+ "timestamp":1294309438,
+ "data":"eatin a taco on fifth street"
+}
+</pre>
+
+<p><code>record</code> is the record number, <code>timestamp</code> is
+the UNIX epoch timestamp (i.e., the number of seconds since Jan 1 1970
+00:00:00 GMT), and <code>data</code> is the content of the record. The
+record number is sent as a string because while Blërg supports record
+numbers up to 2<sup>64</sup> - 1, Javascript uses floating point for all
+its numbers, and can only support integers without truncation up to
+2<sup>53</sup>. This difference is largely academic, but I didn't want
+this problem to sneak up on anyone who is more insane than I am. :]
+
+<p>The second form, /get/(user)/(start record)-(end record), retrieves a
+specific range of records, from (start record) to (end record)
+inclusive. You can retrieve at most 100 records this way. If (end
+record) - (start record) specifies more than 100 records, or if the
+range specifies invalid records, or if the end record is before the
+start record, the server will respond with JSON failure.
+
+<h3><a name="api_info">/info/(user)</a> - Get information about a user</a></h3>
+
+<p>A GET request to /info/(user) will return a JSON object with
+information about the user (currently only the number of records). The
+info object looks like this:
+
+<pre>
+{
+ "record_count": "544"
+}
+</pre>
+
+<p>Again, the record count is sent as a string for 64-bit safety.
+
+<h3><a name="api_tag">/tag/(#|H|@)(tagname)</a> - Retrieve records containing tags</a></h3>
+
+<p>A GET request to this endpoint will return the last 50 records
+associated with the given tag. The first character is either # or H for
+hashtags, or @ for mentions (I call them ref tags). You should URL
+encode the # or @, lest some servers complain at you. The H alias for #
+was created because Apache helpfully strips the fragment of a URL
+(everything from the # to the end) before handing it off to the CGI,
+even if the hash is URL encoded. The record objects also contain an
+extra <code>author</code> field, like so:
+
+<pre>
+{
+ "author":"Jon",
+ "record":"57",
+ "timestamp":1294555793,
+ "data":"I'm taking #garfield to the vet."
+}
+</pre>
+
+<p>There is currently no support for getting more than 50 tags, but /tag
+will probably mutate to work like /get.
+
+<h3><a name="api_subscribe">/subscribe/(user)</a> - Subscribe to a
+user's updates</a></h3>
+<div class="feature">authorization</div>
+
+<p>POST to /subscribe/(user) with a <code>subscribed</code> parameter
+that is either "true" or "false", indicating whether (user) should be
+subscribed to or not. The server will respond with JSON failure if the
+request is unauthorized or if the user doesn't exist. The server will
+respond with JSON success after the subscription request is successfully
+registered.
+
+<h3><a name="api_feed">/feed</a> - Get updates for subscribed users</h3>
+<div class="feature">authorization</div>
+
+<p>POST to /feed, with a <code>username</code> parameter and an auth
+cookie. The server will respond with a JSON list of the last 50 updates
+from all subscribed users, in reverse chronological order. Fetching
+/feed does not reset the new message count returned from /status. To do
+that, look at <a href="#api_status">POST /status</a>.
+
+<p>NOTE: subscription notifications are only stored while subscriptions
+are active. Any records inserted before or after a subscription is
+active will not show up in /feed.
+
+<h3><a name="api_status">/status, /status/(user)</a> - Get or clear
+general and user-specific status</a></h3>
+<div class="feature">authorization</div>
+
+<p>GET to /status to get information about your account. It tells you
+the number of new subscription records since the last time the
+subscription counter was reset, and a flag for whether the account was
+mentioned since the last time the mention flag was cleared. The server
+will respond with a JSON object:
+
+<pre>
+{
+ "feed_new": 3,
+ "mentioned": false
+}
+</pre>
+
+<p>POST to /status with a <code>clear</code> parameter that is either
+"feed" or "mentioned" to reset either the subscription counter or the
+mention flag, respectively. There is not currently a way to clear both
+with a single request. The server will respond with JSON success.
+
+<p>GET to /status/(user) to get subscription information for a
+particular user. The server will respond with a simple JSON object:
+
+<pre>
+{"subscribed":true}
+</pre>
+
+<p>The value of "subscribed" will be either true or false depending on
+the subscription status.
+
+<h3><a name="api_passwd">/passwd</a> - Change a user's password</a></h3>
+<div class="feature">authorization</div>
+
+<p>POST to /passwd with <code>password</code> and
+<code>new_password</code> parameters to change the user's password. For
+extra protection, changing a password requires sending the user's
+current password in the <code>password</code> parameter. If
+authentication is successful and the password matches, the user's
+password is set to <code>new_password</code> and the server responds
+with JSON success.
+
+If the password doesn't match, or one of <code>password</code> or
+<code>new_password</code> are missing, the server returns JSON failure.
+
+<h2><a name="libraries">Libraries</a></h2>
+
+<h3><a name="lib_c">C</a></h3>
+
+<p>Most of Blërg's core functionality is packaged in a static library
+called <code>blerg.a</code>. It's not designed to be public or
+installed with `make install-environment`, but it should be relatively
+straightforward to use it in C programs. Look at the headers under the
+<code>database</code> directory.
+
+<p>A secondary library called <code>blerg_auth.a</code> handles the
+authentication layer of Blërg. To use it, look at
+<code>common/auth.h</code>.
+
+<h3><a name="lib_perl">Perl</a></h3>
+
+<p>As of 1.9.0, Blërg includes a perl library called
+<code>Blerg::Database</code>. It wraps the core and authentication
+functionality in a perlish interface. The module has its own POD
+documentation, which you can read with your favorite POD reader, from
+the manual installed in an environment directory, or in HTML <a
+href="perl/Blerg-Database.html">here</a>.
+
+<h2><a name="design">Design</a></h2>