Wednesday, November 7, 2007

JTV Search API

We launched the new search engine a few days ago. Now I'm excited to announce that it has an API you can use in your own programs.

We've based the API on some very familiar open standards - basically HTTP and JSON, so using it should be a piece of cake from just about any language. To see an example in Common Lisp, scroll to the end of this post.

To use our search API, you just need to send an HTTP request to with a bunch of parameters. Here's a complete list of the parameters that are available right now:

qThe search query (required). Keywords are separated by url-encoded spaces ('+' or '%20'). Anything non-alphanumeric is ignored.
sort-byOne of 'bestmatch' (default), 'newest', 'oldest', 'mostviews'.
pagePage number in results set, default 1.
results-per-pageMaximum 100, minimum 10, default 10.
show-archivesReturn video archives. 'yes', 'true', 'on' all do the same thing.
show-live-broadcastersReturn users who are currently broadcasting. 'yes', 'true', 'on' all do the same thing.
show-offline-broadcastersReturn users who are not currently broadcasting. 'yes', 'true', 'on' all do the same thing.
If none of the above three are specified, they are all assumed to be 'true'.
broadcastersOnly return results from a list of named broadcasters, e.g. 'b1,b2,b3'.
encode-asOne of 'html-fragment' (default), 'html-page', 'json'.

So let's say we want to build a small application, using the search api, that alerts us whenever a new video clip is available that has something to do with cats. Here's a query that would be a good starting point for an application like that:


Let's pull that apart and look at what each piece does.

q=catWe're interested in search results whose metadata contain the word "cat".
sort-by=newestWe want the most recently produced results.
show-archives=trueWe do want video archives in our results. Note that show-live-broadcasters and show-offline-broadcasters will both default to 'false' because we've set show-archives to 'true'.
encode-as=jsonThe results set should be encoded using json.

Let's send that query to and see what we get back:


[{"type": "video_archive", "broadcaster": "ggjeffy", "id": 28144, "title": "Cat doing cat stuffs", "start_time": 1186542932, "duration": 180}, {"type": "video_archive", "broadcaster": "nekomimi_lisa", "id": 39175, "title": "Nekomimi Cat Doing The Cat Dance", "start_time": 1191805139, "duration": 108}, {"type": "video_archive", "broadcaster": "nekomimi_lisa2", "id": 9832, "title": "CAT FIGHT!!", "start_time": 1185954224, "duration": 180}, {"type": "video_archive", "broadcaster": "nekomimi_lisa2", "id": 9818, "title": "cat trying to hump blanket", "start_time": 1185939617, "duration": 180}, {"type": "video_archive", "broadcaster": "ashleymarie", "id": 36553, "title": "Sister Cat Fight Part 1", "start_time": 1190060150, "duration": 80}, {"type": "video_archive", "broadcaster": "ibrbigottopee", "id": 34698, "title": "I thought i saw a putty cat", "start_time": 1189149636, "duration": 66}, {"type": "video_archive", "broadcaster": "ashleymarie", "id": 36555, "title": "Sister Cat Fight Part 2", "start_time": 1190060349, "duration": 66}, {"type": "video_archive", "broadcaster": "audratv", "id": 39679, "title": "Attack of the Fuzzy Cat Part 2", "start_time": 1191985459, "duration": 180}, {"type": "video_archive", "broadcaster": "audratv", "id": 39656, "title": "Cat Attack", "start_time": 1191980666, "duration": 180}, {"type": "video_archive", "broadcaster": "xk3ll3yx", "id": 40879, "title": "Cat on Head!", "start_time": 1192431728, "duration": 71}]

Now we need to decode that blob of json. Fortunately there's a library to do that for every language under the sun (look on the json page for yours).

So let's see how we would start writing that feline-video-feed in my favorite language, Common Lisp. First we need libraries for doing the http request and the json decoding. trivial-http and cl-json are more than good enough:

(require :trivial-http)
(require :json)

Let's write a "find-cats" function, which will send the http request and return the results as a string:

(defparameter *url*

(defun find-cats ()
(let ((stream (first (last (trivial-http:http-get *url*))))
(json nil)
(line nil))
(loop while (setf line (read-line stream nil nil)) do
(push line json))
(apply #'concatenate 'string (nreverse json))))

Now we just need to call that function periodically, parse the json, and print any new cat videos:

(defun cats-alert ()
(let ((known-cat-videos (make-hash-table :test #'equalp)))
(let ((cats (json:decode-json-from-string (find-cats))))
(dolist (cat cats)
(unless (gethash cat known-cat-videos)
(setf (gethash cat known-cat-videos) t)
(format t "New cat video!~%~A~%"
(rest (assoc 'title cat))
(rest (assoc 'broadcaster cat))
(rest (assoc 'id cat)))
(sleep 600))))

That's it, we're done! Here's an example of the program's output:

CL-USER> (cats-alert)
New cat video!
Get the cat butt out of the way!

New cat video!
cat vs dog

New cat video!
scared cat!

New cat video!
Bob scares the cat! lol

New cat video!
Cat fight. Or something.

New cat video!
Cat on Head - Part II (With New Web Cam)

New cat video!
Cat fight

New cat video!
Dear cat in the middle of the road, i hate you.

New cat video!
Jasmine Playing... (& the amazing flying cat-jumps) TOO CUTE!

New cat video!
KT, the cat, running around acting strange, then craps on the floor

We can't wait to see what you do with the APIs we're developing. Email me (bill at justin dot tv) if you have something cool to show off, or if you have any questions or comments.


rog said...

Good to see some a lisp example.

Just in case someone has problems with trivial-http (it is not maintained anymore), here you can find an example with drakma, trivial-http's replacement

WiseAllec said...

Hi, I'm having troubles in using the SearchAPI, I copied the http address that was in this post ( to try it out and it doesn't work. I am unable to get the SearchAPI working for me... :S

I just keep getting a Failed to Connect error in Firefox every time.

Is there something wrong with the server? Oo

aio said...

same thing here!
error in firefox

anyone can help us??

Anonymous said...

This post is way out of date. The current search api docs are here.

Reverse Phone Lookup said...

this kind of blog always useful for blog readers, it helps people during research. your post is one of the same for blog readers.
Reverse Phone Lookup
Avatar Movie

Anonymous said...

Well I really like the ad and i think there is an immediate need of this among youngsters, It’s a fastidious and instructive. Things are ordered wellspring. acai berry
Best Acne Treatment
acai berry weight loss

Nelson Noble said...

Thanks for the nice post. I am expecting some different idea from your side. You always represent some new thought in your post.
Acai Berry Colon Cleanse
Acai Max Cleanse Review
Acai Berry
How To Get Pregnant Fast

Daniel Rusu said...

In case you dolce and gabbana light blue perfume or somebody you realize home security safe is ever charged aided by the crime of driving below home mortgage calculator the affect, the initial thing that you just auto tint must do is tiny bluetooth usb adapter dongle black consult a criminal law firm dual alarm clock radio about the circumstance. lip liners There are a lot of lcd hd tv optimistic things that wine glass racks an experienced prada laptop bag Alameda County DUIwaste compactors lawyer can deliver to a situation. gold necklace With in depth knowledge booster car seat about the law, a attorney may be casio cameras suitable there with you to help defend spouse visas your constitutional rights and freedoms. dvd editing software free

coloncleansehomekits said...

This is really nice post, I found and love this content. I will prefer this, thanks for sharing. intestinal cleanse.