Flavio Poletti bio photo

Flavio Poletti

Irreducible Perler.

Email Comics Twitter LinkedIn MetaCPAN Github Stackoverflow Pinterest

Get the most out of your APIs… from the shell!

I sometimes need to read values from a configuration file or a response to an API call from the shell. Most of the times they come either in JSON or YAML format… which is when teepee comes handy.

Why the name, in the first place? It heavily relies upon the Perl distribution/module Template::Perlish, whose initials are Ti Pi. Hence… teepee.1

Table of Contents

Quick! Show Me Something!

# something about me
curl "$metacpan/author/POLETTIX" \
  | teepee -nT "Hi! I'm [% name %] <[% email.0 %]>."
# Hi! I'm Flavio Poletti <polet...pan.org>.

# for extracting multiple data, let's cache in a variable
me=$(curl "$metacpan/author/POLETTIX")
teepee -I "$me" -nT 'See my big face at [% gravatar_url %]?s=200'
# See my big face at http://www.gravatar.com/av...b57.png?s=200

# my favourite band
pjq=$(curl "$mbrz/artist?fmt=json&limit=1&query=Pearl%20Jam")
name=$(teepee -I "$pjq" -v artists.0.name)
country=$(teepee -I "$pjq" -v artists.0.country)
echo "$name rock from the $country"'!'
# Pearl Jam rock from the US!

# let's just isolate data about Pearl Jam from the query response
pj=$(teepee -I "$pjq" -F'YAML(V "artists.0")')
year=$(teepee -I "$pj" -v "'life-span'.begin")
city=$(teepee -I "$pj" -v "'begin-area'.name")
echo "they started from $city in $year"
# they started from Seattle in 1990

# we can also pretty-print, especially handy with compact JSON
curl "$ap/coefficients?date=1972-11-9&bodies=mars"
# {"date": 2441630.5, "type": "chebyshev", "results": {"mars": ...
curl "$ap/coefficients?date=1972-11-9&bodies=mars" \
    | teepee -FYAML
# ---
# date: 2441630.5
# results:
#   mars:
#     coefficients:
#       -
#         - -221246363.667206
#         - 26761105.8067001
#         ...
#     end: 2441680.5
#     start: 2441616.5
# type: chebyshev
# unit: km

# or do the pretty-printing of a sub-section only
teepee -I "$pj" -F'YAML(V "aliases")'
# ---
# -
#   begin-date: ~
#   end-date: ~
#   locale: ~
#   name: 'Mookie Blaylock'
#   primary: ~
#   sort-name: 'Mookie Blaylock' type: ~

No, I didn’t know Pearl Jam had an alias as Mookie Blaylock!

Setting Up

To get up to speed in the examples, you need teepee and curl.

teepee is easy to install, especially in the bundled version:

$ curl -LO \
$ chmod +x teepee

We will assume the directory where you place teepee is in the PATH, otherwise you can move it in some directory that is. (e.g. usr/local/bin). You shouldn’t need anything more than Perl 5.8 to be able to run it (please report any issues!).

In case you don’t have curl, you can try to see if you have GNU Wget instead. In this case, a quick and dirty replacement for the examples below can be the following alias:

alias curl='wget -O -'

Last, but not least, we will use bash as our shell of election in the following examples. You are smart enough to figure out what to change in case you want to use something different!

Getting A Value

The basic use case is probably just getting a value from a JSON or YAML structured file. You will need:

  • some input structured data
  • the path of the variable in the data

To make things clearer, let’s start playing with the following sample input data:

name: Flavio
surname: Poletti
    id: POLETTIX
    metacpan: https://metacpan.org/author/POLETTIX
        - Data::Crumbr
        - Template::Perlish
        - Graphics::Potrace
        - Log::Log4perl::Tiny
        Dancer: YANICK
        Moo: HAARG

We’ll assume the above text is in file input.yaml, so we have our input.

What’s a path then? It’s how you can reach the value you’re interested into starting from the root of the data structure, all the way down, with components separated by dots. For example, who’s the current maintainer of Moo?

$ teepee -i input.yaml -v cpan.favorites.Moo
HAARG$ # OK but next prompt is on the same line and it's UGLY...

The first two options we just saw are:

is for inputs. They can be JSON or YAML, and teepee will try to auto-detect. You can be explicit and use -j and -y, you can guess what for what;
is for variable’s path. As anticipated, the different keys/indexes, separated by dots (more on this later!).

Well, we managed to get the value we were after, but it would be nice to have a newline when printing out to the terminal. No worries, there’s option -n to the rescue:

$ teepee -i input.yaml -nv cpan.favorites.Dancer
$ # now the next prompt is on its own new line!

This option is useful only for printing things to the terminal, otherwise you can ignore it, e.g. when just filling up some variables:

$ metacpan_uri=$(teepee -i input.yaml -v cpan.metacpan)
$ echo "$metacpan_uri"

So far so good, but probably not that impressive as we could have obtained the same with some grep and sed magic. In this case probably yes, but what if data were shaped like this instead:

name: Flavio
surname: Poletti
    id: POLETTIX
    metacpan: https://metacpan.org/author/POLETTIX
        - Data::Crumbr
        - Template::Perlish
        - Graphics::Potrace
        - Log::Log4perl::Tiny
            id: 'https://metacpan.org/release/JSON'
            id: YANICK
            id: MAKAMAKA
            id: HAARG

Note that I added a using hash that has itself a JSON element inside, and changed how ids are associated to the distributions. To make things funnier, the shape of using and of favorites is the same, but with different data. Well, now it’s a bit more difficult to get the right id for the JSON inside favorites, isn’t it? It’s a trivial change in calling teepee though:

# --------------------------------------------vvv
$ teepee -i input2.yaml -nv cpan.favorites.JSON.id

I hope you appreciate the simplification.

In case you’re wondering, accessing arrays just means using the right index in the right place:

$ teepee -i input.yaml -nv cpan.latest.1

The assumption (at least so far) is that you know exactly how your data are shaped, including the position of elements inside arrays. We will see later in section Iterating Over an Array that there are functions that allow us to iterate over data structures, so that we can partially2 remove this assumption.

Using Available Inputs

If you’re consuming an API, chances are you’re actually doing remote calls (e.g. with curl) and getting responses back.

You are polite enough to understand that if you need three values from the same response… you don’t have to make three different calls, right? One alternative (apart using temporary files, of course) is to save the response in a shell variable, which works for local files a well of course:

# cache query result in a variable, for using over and over
$ mcpan_input=$(curl "http://api.metacpan.org/v0/author/POLETTIX")

# read file contents in a convenience variable
$ local_input=$(< input.yaml)

In this case, you can use the immediate parameters, that are the uppercase counterparts of the file-base input parameters:

# auto-detect
$ PAUSE_ID=$(teepee -I "$local_input" -v cpan.id)

# force interpreting as YAML
$ name=$(teepee -Y "$local_input" -v name)

# force interpreting as JSON
$ fullname=$(teepee -J "$mcpan_input" -v name)

Remember to put double quotes around the variable with the data, or the shell will make a mess!

Expanding Templates

Getting variables is handy, but what if you want to generate something a bit more evolved? You can use Template::Perlish for this, e.g. with a template passed directly on the command line as text with option -T:

$ teepee -i input.yaml -nT 'Hello, I am [% name%] [% surname %]'
Hello, I am Flavio Poletti

Templates can live in files, of course. Again, what’s immediate on the command line as an uppercase option -T becomes a lowercase option -t when taken from a file:

$ cat story.txt
Hello, my name is [% name %] [% surname %].
Lorem ipsum...

$ teepee -i input.yaml -t story.txt
Hello, my name is Flavio Poletti.
Lorem ipsum...

This can come quite handy when you’re doing API consumption where you have to send JSON text back and forth. For example, one way to see one’s favorite distributions on meta::cpan is to POST the following query:

    "fields": [ "distribution" ],
    "filter" : { "term" : { "user" : "[% user %]" } },
    "size": 100

We will store the above template in favorites-for.json.

We need the user identifier, which is easy to retrieve from the author’s profile:

$ me=$(curl "http://api.metacpan.org/v0/author/POLETTIX")
$ teepee -I "$me" -nv user
$ query=$(teepee -I "$me" -t favorites-for.json)
$ echo "$query"
    "fields": [ "distribution" ],
    "filter" : { "term" : { "user" : "NwdPuW9vRBGuIdSr4Gw26g" } },
    "size": 100
$ favs=$(curl -XPOST "http://api.metacpan.org/v0/favorite/_search" \
              -d "$query")
$ teepee -I "$favs" -nT 'I have [% hits.total %] favorites'
I have 13 favorites

As you are correctly thinking now, this requires that the template is shaped to accept exactly the data structure coming from the response, which is a bit stiff. We’ll see later how to use even more general inputs.

Iterating Over an Array

Our last query result contained as much as 13 favorites, in an array shaped like this:

    "hits" : {
        "hits" : [
                "fields" : {
                    "distribution" : "Template-Toolkit"
                "_score" : 1,
                "_type" : "favorite",
                "_id" : "vx77xt7X5e_a1pr66pq_QJvhbJs",
                "_index" : "cpan_v1"
                "_index" : "cpan_v1",
                "_id" : "DD1K8tb8s2oNX8RN1UZEL6wijUQ",
                "fields" : {
                    "distribution" : "Pod-Markdown"
                "_type" : "favorite",
                "_score" : 1

How to get a list of distribution names? We might grep, of course, or use a bit of Perl with Template::Perlish:

$ teepee -I "$favs" -T 'My favorites:
[% for my $hit (A "hits.hits") {
   %]- [%= $hit->{fields}{distribution} %]
[% } %]'
My favorites:
- Template-Toolkit
- Pod-Markdown
- GraphViz
- Pinto
- Parse-RecDescent
- Path-Class
- Dancer
- WWW-Mechanize
- Dist-Zilla
- WWW-Mechanize-Shell
- libwww-perl
- Moo

We already saw that option -T allows us to set a generic template. What’s good is that the template can also contain Perl code.

The really handy thing here is the A function, that works on a path (string "hits.hits" in this case) and, assuming it leads to an array reference, expands the reference to a list of items. In our case, each item is a hash where the interesting part is inside fields, then inside distribution.

Handy Shortcuts

We saw in Iterating Over an Array that it’s possible to use a function A in the templates, that takes a template path and expands it into a list. There are a few of additional functions:

  • V expands to a single value. It might be a leaf scalar or an intermediate data structure, you should know what you have though;
  • H expands a hash reference to the list intermixing keys and values;
  • HK expands a hash reference into the list if its keys;
  • HV expands a hash reference into the list of its values.

They all take a path, either as a string or as a reference to an array containing the different crumbs in the sequence.

The functions also accept an optional second parameter, assumed to be a reference to a data structure. When present, it is visited instead of the top-level data structure. Hence, the last example in the previous section can be rewritten as follows:

$ teepee -I "$favs" -T 'My favorites:
    for my $hit (A "hits.hits") { %]- [%=
        V("fields.distribution", $hit) %]
[% } %]'
My favorites:
- Template-Toolkit

Yet Another Input Channel

There is an interesting meta::cpan query get the latest version numbers of your favorite modules that can be expressed in the following template:

    "query" : { "terms" :
        { "release.distribution" : [% list_array %] } },
    "filter" : { "term" : { "release.status" : "latest" } },
    "fields" : [ "distribution", "version" ],
    "size"   : [% size %]

We’ll save the above template in lastv-favs.json.

Now, of course, the issue is to get list_array and size for your favorites. In the previous section we already saw mine, so we can generate something suitable for list_array as follows:

$ list_array=$(teepee -I "$favs" -T '[ [%=
    join ", ", map { qq["$_->{fields}{distribution}"]}
        A "hits.hits";
%] ]')
$ size=$(teepee -I "$favs" -v hits.total)

Now we have our expansion values inside shell variables… how do we pass them to teepee for expanding the template above? This is where option -d comes handy, because it allows you to define variable valued directly on the command line:

$ query=$(teepee -t "lastv-favs.json" \
    -d list_array="$list_array" \
    -d size="$size")

But wait! Why does it seem to be stuck at this point? The fact is that by default teepee expects to read some input, and it goes to standard input by default. If you don’t want it to get any regular input (as in this case, in which you define variables directly) you can use option -N:

$ query=$(teepee -Nt "lastv-favs.json" \
    -d list_array="$list_array" \
    -d size="$size")
$ echo "$query"
    "query" : { "terms" :
        { "release.distribution" : [ "Template-Toolkit", ... ] } },
    "filter" : { "term" : { "release.status" : "latest" } },
    "fields" : [ "distribution", "version" ],
    "size"   : 13

We’re now ready to run our query:

$ lfv=$(curl -XPOST "http://api.metacpan.org/v0/release/_search" \
             -d "$query")
$ teepee -I "$lfv" -T 'My favorites with latest version:
    for my $hit (A "hits.hits") {
        my $f = $hit->{fields};
        print "- $f->{distribution} ($f->{version})\n";
My favorites with latest version:
- Path-Class (0.35)
- Pod-Markdown (3.003)
- GraphViz (2.19)
- WWW-Mechanize-Shell (0.55)
- Parse-RecDescent (1.967013)
- Moo (2.000002)
- WWW-Mechanize (1.75)
- JSON (2.90)
- libwww-perl (6.15)
- Template-Toolkit (2.26)
- Pinto (0.11)
- Dist-Zilla (5.042)
- Dancer (1.3202)


In our last example, we extracted information from the first query into two variables, then used them to build up a new template for our next query. This surely works, but might become cumbersome (and intensive in terms of process-calling) if you want to take more than a handful of values.

If you’re going to use teepee on the data, like in our example, an efficient alternative is to build up a new JSON/YAML data structure out of your input data:

$ reshaped=$(teepee -I "$favs" -NT '---
size: [% hits.total %]
[% for my $hit (A "hits.hits") { %]   - "[%=
        $hit->{fields}{distribution} %]"
[% } %]')
$ echo "$reshaped"
size: 13
   - "Template-Toolkit"
   - "Pod-Markdown"
   - "GraphViz"
   - "Pinto"
   - "Parse-RecDescent"
   - "Path-Class"
   - "Dancer"
   - "JSON"
   - "WWW-Mechanize"
   - "Dist-Zilla"
   - "WWW-Mechanize-Shell"
   - "libwww-perl"
   - "Moo"

We will have to modify our template at this point, but it’s also cleaner to expect an array as input and handle the shaping in the template itself. Here’s our second take at the template (we will call the file lastv-favs-2.json):

    "query" : {
        "terms" : {
            "release.distribution" : [ [%
                print join ", ", map { qq{"$_"} } A 'distros';
            %] ]
    "filter" : { "term" : { "release.status" : "latest" } },
    "fields" : [ "distribution", "version" ],
    "size"   : [% size %]

The query then becomes:

$ query=$(teepee -t "lastv-favs-2.json" -Y"$reshaped")

with similar results as before.

This reshaping does not necessarily have to be applied for generating new YAML or JSON though. If you’re still interested into getting values into shell variables, you can prepare the right text and then eval it, to get all values in one shot:

$ variables=$(teepee -I "$favs" -T 'list_array=[%=
    my $list = join ", ", map { qq["$_->{fields}{distribution}"]}
        A "hits.hits";
    quotemeta("[ $list ]");
size=[%= quotemeta(V "hits.total" ) %]
$ eval "$variables"
$ echo "size: $size - array: $list_array"
size: 13 - array: [ "Template-Toolkit", "Pod-Markdown", ...

Don’t use eval unless you’re 200% sure about what you are doing! To be on the safe side, either avoid this technique completely, or use it only on data you trust.

Pretty-Printing and Isolating

Some APIs choose to return pretty-printed data, trading some space for ease of use. Other ones go for compactness, and leave you the burden to pretty print the response if you need to read it (as a human).

teepee allows you to re-print your input data either in JSON or YAML format. This also comes handy if you want to trasform from one to the other, by the way; so you might have data that is already pretty-printed, and re-pretty-print it into another format (I usually find YAML a better reading experience).

Pretty-printing is done through a couple of functions that are available in the templates; unsurprisingly, these functions are called YAML and JSON. This is how it would be done:

$ ap='http://www.astro-phys.com/api/de406'
$ mars=$(curl "$ap/coefficients?date=1972-11-9&bodies=mars")
$ echo "$mars"
{"date": 2441630.5, "type": "chebyshev", "results": {"mars": ...

$ teepee -J "$mars" -T '[%= YAML %]'
date: 2441630.5
        - -221246363.667206
        - 26761105.8067001
        - -80259893.9503651
        - -50770737.7568579
    end: 2441680.5
    start: 2441616.5
type: chebyshev
unit: km

JSON would work similarly. This construct is so handy that it made sense to provide a slightly shorter way to type it. In particular, option -F provides a way to specify a template without too much boilerplate, so the following two calls are actually equivalent:

$ teepee -Fwhatever ...
# ...
$ teepee -T '[%= whatever %]'

Hence, pretty-printing in YAML is as simple as this:

$ teepee -FYAML -J "$mars"
date: 2441630.5

The two functions can also take an optional parameter, namely a reference to a data structure. Guess what? They will pretty-print that! So, if we are interested only in the results.mars.coefficients we can isolate them as follows:

$ coeffs=$(teepee -F'YAML V "results.mars.coefficients"' -J"$mars")
$ echo "$coeffs"
  - -221246363.667206
  - 26761105.8067001
  - 4016544.02022364

This can be useful if you’re only interested into a subsection of a complex response, because you can isolate that subsection into a shell variable (like $coeffs in our example above) and then run teepee over that variable with shorter paths.

A Few Examples

Here are a few examples of consuming APIs from the shell with the help of teepee… I hope they will inspire you!

What’s the Weather Like?

OpenWeatherMap delivers 1 billion [weather] forecasts per day. It should be able to cope with a few requests from us!

To use it, you will need to register (freely) at the registration page and get an API key.

Yes, I know that the examples in the Current Weather Data page work fine and include a valid API key, but you SHOULD get your own key to be fair!

Every API call is a GET and parameters are passed in the URI, encoded. One of them is the API key, so we’ll start with the following definition:


Accessing the latest weather data is as simple as sending a query to http://api.openweathermap.org/data/2.5/weather?appid=$key. Response parameters are explained here. We will format a little report according to the following template (saved as weather.tmpl):

    # convenience function for cutting excess decimals
    sub fmt { return sprintf '%.1lf', shift; }
%]Hi! Here's some facts about [% name %] [[% sys.country %]]:
  - position is about latitude [% coord.lat %]N and longitude [%
      coord.lon %]E
  - [% weather.0.main %]: [% weather.0.description %]
  - temperature is [%= fmt(V('main.temp') - 273.15) %]°C ([%=
      fmt(V('main.temp_min') - V('main.temp')) %]/+[%=
      fmt(V('main.temp_max') - V('main.temp')) %]°C)
  - humidity is [% main.humidity %]%
  - last sunrise was on [%= scalar localtime V('sys.sunrise') %]
  - last sunset  was on [%= scalar localtime V('sys.sunset') %]

Now, we’re ready to get some facts about Roma, my city:

$ owm_weather_api="http://api.openweathermap.org/data/2.5/weather"
$ curl "$owm_weather_api?appid=$key&q=Roma,it" \
    | teepee -t weather.tmpl
Hi! Here are some facts about Roma [IT]:
  - position is about latitude 41.89N and longitude 12.48E
  - Clear: Sky is Clear
  - temperature is 8.1°C (-2.1/+0.9°C)
  - humidity is 87%
  - last sunrise was on Tue Dec 15 07:31:04 2015
  - last sunset  was on Tue Dec 15 16:39:56 2015

Not exactly hot… but lovely for this time of the year in the night, isn’t it? Let’s look how it will go in the coming days, using forecast-daily.tmpl:

    sub fmt { sprintf '%.1lf', shift }
%]Forecast for [% city.name %] [[% city.country %]] ([%
        city.coord.lat %]N, [% city.coord.lon %]E):[%
    for my $day (A 'list') {
- [%= (my $d = scalar localtime $day->{dt}) =~ s{\d\d:.*}{}mxs;
    $d; %]: [%=
        fmt $day->{temp}{min} %]°C/[%= fmt $day->{temp}{max} %]°C [%=
        $day->{weather}[0]{main} %] ([%=
        $day->{weather}[0]{description} %])[%

and the following query:

$ owm_fd="http://api.openweathermap.org/data/2.5/forecast/daily"
$ curl "$owm_fd?appid=$key&q=Roma,it&units=metric&cnt=16" \
    | teepee -t forecast-daily.tmpl
Forecast for Roma [IT] (41.894741N, 12.4839E):
  - Tue Dec 15 : 7.3°C/7.8°C Clear (sky is clear)
  - Wed Dec 16 : 5.8°C/12.6°C Clouds (few clouds)
  - Thu Dec 17 : 4.2°C/11.4°C Clear (sky is clear)
  - Fri Dec 18 : 8.4°C/13.3°C Rain (light rain)
  - Sat Dec 19 : 9.9°C/11.5°C Rain (moderate rain)
  - Sun Dec 20 : 6.2°C/12.1°C Clear (sky is clear)
  - Mon Dec 21 : 7.0°C/13.4°C Rain (light rain)
  - Tue Dec 22 : 10.0°C/13.2°C Rain (light rain)
  - Wed Dec 23 : 13.5°C/15.2°C Rain (light rain)
  - Thu Dec 24 : 9.2°C/15.4°C Clear (sky is clear)
  - Fri Dec 25 : 7.9°C/14.5°C Clear (sky is clear)
  - Sat Dec 26 : 10.9°C/14.7°C Rain (light rain)
  - Sun Dec 27 : 9.2°C/14.2°C Rain (light rain)
  - Mon Dec 28 : 7.2°C/13.6°C Rain (light rain)
  - Tue Dec 29 : 10.0°C/13.4°C Rain (light rain)
  - Wed Dec 30 : 10.6°C/14.4°C Rain (light rain)

A little too rainy for my taste… but it’s life!

Where Can I Go From…

Wikipedia is the biggest online encyclopedia, and can be a real time drag as you go through the pages, following links over links (even only internal).

For example… how many links are contained in a few pages, e.g. about Perl, Bash or Pearl Jam? Let’s see:

$ wp='https://en.wikipedia.org/w/api.php'
$ wpq="$wp?action=query&prop=links&format=json&pllimit=500"
$ for title in 'Perl' 'Bash' 'Pearl_Jam' ; do
    curl -s "$wpq&titles=$title" \
        | teepee -nT '[%=
            my ($d) = HV "query.pages";
            my $n = scalar @{$d->{links}};
            "$d->{title}: $n";
Perl: 450
Bash: 14
Pearl Jam: 455

Well… it seems that there is a slight better chance to get lost reading about Pearl Jam than about Perl, but they’re almost there together!

What’s the Last xkcd Strip?

I hope you love xkcd as much as I do. You’re in the terminal and you would like to know what’s the last strip, just to see if there’s anything new…

$ curl http://xkcd.com/info.0.json \
    | teepee -n \
        -T '#[%num%] "[%safe_title%]", [%year%]-[%month%]-[%day%]'
#1616 "Lunch", 2015-12-14

When you call it you don’t get too much data, e.g.:

$ xkcd_last=$(curl http://xkcd.com/info.0.json)
$ echo "$xkcd_last"
{"month": "12", "num": 1616, "link": "", "year": "2015", "news": "", "safe_title": "Lunch", "transcript": "", "alt": "I'm trying to be healthier, so after I eat this brick of cheese, I'll have a spoonful of grease-soaked vegetables.", "img": "http:\/\/imgs.xkcd.com\/comics\/lunch.png", "title": "Lunch", "day": "14"}

Well… it’s not that readable, is it? All that scrolling to the right… This can use some pretty printing, e.g. in YAML:

$ teepee -J "$xkcd_last" -FYAML
alt: "I'm trying to be healthier, so after I eat this brick of cheese, I'll have a spoonful of grease-soaked vegetables."
day: '14'
img: http://imgs.xkcd.com/comics/lunch.png
link: ''
month: '12'
news: ''
num: 1616
safe_title: Lunch
title: Lunch
transcript: ''
year: '2015'

… And So On…

I hope you got your feet wet at this point. Be sure to go (again) through the examples in section Quick! Show Me Something!, they can be a bit more understandable at this point!

Time’s Up!

If you made it to the end of this article… congratulations! I hope you will consider teepee as a tool worth using in your next shell project.

If you want to play a bit, a good entry point for finding out APIs to do some testing is Programmable Web, although for Perl enthusiast also meta::cpan is worth a look. Some good starting points that do not require registration are the following:

  • meta::cpan is a fast growing (feature-wise) search tool for CPAN. meta::cpan APIs (entry point) allow programmale access to the database.

  • MusicBrainz is an open music encyclopedia that collects music metadata and makes it available to the public. Development explains how to consume their APIs, with details on the JSON interface. (Entry point).

  • Star API provides access the Digital Universe Data set. (Entry point).

  • OpenWeatherMap delivers 1 billion forecasts per day. API description is here. Well, you’re supposed to register actually, as already written before…

  • Wikipedia is a wonderful resource for information… although you always have to remember that it’s not fully peer-reviewed. It has an API Tutorial.

  • xkcd is A webcomic of romance, sarcasm, math, and language. Very funny. API hints here.

There are many more… including your very own API for the next-decade killer application!

  1. Photo credits: Teepees on the Columbia by Ralph Irving Gifford, Ute Pagre by H.H. Tammen.

  2. You are still supposed to know how your data are shaped, although you might not know where the different elements in an array are placed.